<?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>ohmeow</title>
<link>https://ohmeow.com/</link>
<atom:link href="https://ohmeow.com/index.xml" rel="self" type="application/rss+xml"/>
<description>A resource for full stack web application and machine learning developement</description>
<image>
<url>https://ohmeow.com/images/ohmeow_logo.png</url>
<title>ohmeow</title>
<link>https://ohmeow.com/</link>
<height>46</height>
<width>144</width>
</image>
<generator>quarto-1.6.39</generator>
<lastBuildDate>Tue, 24 Dec 2024 08:00:00 GMT</lastBuildDate>
<item>
  <title>Gemini (Part II) - The Unified SDK</title>
  <dc:creator>Wayde Gilliam</dc:creator>
  <link>https://ohmeow.com/posts/2024-12-24-gemini-part-2-sdk.html</link>
  <description><![CDATA[ 




<section id="hallelujah" class="level2">
<h2 class="anchored" data-anchor-id="hallelujah">Hallelujah!</h2>
<p>In the previous post we looked at how Gemini, espeically 2.0, compares with other models relative to both performance and cost and why you should consider it as a potential “go to” in building AI powered applications of almost any kind. Today, we’ll discuss how to get started with their new unified SDK that both Gemini API and Vertex API users can use to build applications.</p>
<blockquote class="twitter-tweet blockquote">
<p lang="en" dir="ltr">
Is it just me, but I'm more hyped about this than all the new sick features in <a href="https://twitter.com/Google?ref_src=twsrc%5Etfw"><span class="citation" data-cites="google">@google</span></a> Gemini 2.0 …<a href="https://t.co/mMiba2pwMq">https://t.co/mMiba2pwMq</a><br><br>"The new Google Gen AI SDK provides a unified interface … through both the Gemini Developer API and the Gemini Enterprise API ( Vertex AI)"
</p>
— Wayde Gilliam (<span class="citation" data-cites="waydegilliam">@waydegilliam</span>) <a href="https://twitter.com/waydegilliam/status/1866959913312010394?ref_src=twsrc%5Etfw">December 11, 2024</a>
</blockquote>
<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
<p>Amongst the biggest complaints from Gemini devs, has been the inconsistency of the SDKs for both the Gemini API and Vertex API. Well it looks like Google has finally heard our cries and as part of the Gemini 2.0 release, they’ve released a new unified SDK that both Gemini API and Vertex API users can use to build applications. This makes is super easy to bounce back-and-forth between the two API options without having to understand the nuances of two somewhat different SDKs and what might break when you switch between them.</p>
</section>
<section id="initializing-the-sdk-client" class="level2">
<h2 class="anchored" data-anchor-id="initializing-the-sdk-client">Initializing the SDK client</h2>
<section id="a-note-on-the-gemini-api-and-vertex-ai-from-the-official-docs" class="level3">
<h3 class="anchored" data-anchor-id="a-note-on-the-gemini-api-and-vertex-ai-from-the-official-docs">A note on the Gemini API and Vertex AI (from the official docs)</h3>
<blockquote class="blockquote">
<p>In the whitepapers, most of the example code uses the Enterprise <a href="https://cloud.google.com/vertex-ai">Vertex AI platform</a>. In contrast, this notebook, along with the others in this series, will use the <a href="https://ai.google.dev/gemini-api/">Gemini Developer API</a> and <a href="https://aistudio.google.com/">AI Studio</a>.</p>
<p>Both APIs provide access to the Gemini family of models, and the code to interact with the models is very similar. Vertex provides a world-class platform for enterprises, governments and advanced users that need powerful features like data governance, ML ops and deep Google Cloud integration.</p>
<p>AI Studio is free to use and only requires a compatible Google account to log in and get started. It is deeply integrated with the Gemini API, which comes with a generous <a href="https://ai.google.dev/pricing">free tier</a> that you can use to run the code in these exercises.</p>
<p>If you are already set up with Google Cloud, you can check out the <a href="https://cloud.google.com/vertex-ai/generative-ai/docs/model-reference/inference">Enterprise Gemini API</a> through Vertex AI, and run the samples directly from the supplied whitepapers.</p>
</blockquote>
<p>I’ll be showing how to use both platforms below, but the first step is the same either way … a single pip install :)</p>
<div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb1-1">pip install google<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>genai</span></code></pre></div>
<div class="callout callout-style-default 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">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>Here are some reference links to the new SDK docs and a Getting Started notebook courtesy of Google with a lot more information and examples …</p>
<ul>
<li><a href="https://googleapis.github.io/python-genai/#">2.0 SDK Docs</a></li>
<li><a href="https://github.com/google-gemini/cookbook/blob/main/gemini-2/get_started.ipynb">2.0 SDK Getting Started Notebook</a></li>
</ul>
</div>
</div>
</section>
<section id="if-you-are-using-the-gemini-developer-api" class="level3">
<h3 class="anchored" data-anchor-id="if-you-are-using-the-gemini-developer-api">If you are using the Gemini Developer API …</h3>
<div class="sourceCode" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb2-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># with Google AI API key</span></span>
<span id="cb2-2">GOOGLE_AI_API_KEY <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> os.getenv(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"GOOGLE_AI_API_KEY"</span>)</span>
<span id="cb2-3"></span>
<span id="cb2-4">client <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> genai.Client(api_key<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>GOOGLE_AI_API_KEY)</span>
<span id="cb2-5"></span>
<span id="cb2-6">response <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> client.models.generate_content(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;">"gemini-2.0-flash-exp"</span>, contents<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"How far is the moon from the earth?"</span>)</span>
<span id="cb2-7"></span>
<span id="cb2-8">display(Markdown(response.text))</span>
<span id="cb2-9"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># The distance between the Earth and the Moon isn't constant, as the Moon travels in an elliptical orbit around our planet. Therefore, we talk about the distance in terms of averages:</span></span>
<span id="cb2-10"></span>
<span id="cb2-11"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Average distance: Approximately 238,855 miles (384,400 kilometers).</span></span>
<span id="cb2-12"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># However, keep in mind:</span></span>
<span id="cb2-13"></span>
<span id="cb2-14"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Perigee (Closest Approach): The Moon can get as close as about 225,623 miles (363,104 kilometers).</span></span>
<span id="cb2-15"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Apogee (Farthest Distance): The Moon can be as far as about 252,088 miles (405,696 kilometers).</span></span>
<span id="cb2-16"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># So, while the average distance is a good figure to keep in mind, it's important to remember that the actual distance varies throughout the month.</span></span>
<span id="cb2-17"></span>
<span id="cb2-18"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(response.usage_metadata)</span>
<span id="cb2-19"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># cached_content_token_count=None candidates_token_count=181 prompt_token_count=10 total_token_count=191</span></span></code></pre></div>
<div class="callout callout-style-default 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">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>The <code>resonse</code> is an instance of <code>GenerateContentResponse</code>. In addition to the generated content, it includes a bunch of other information including the token usage (via <code>response.usage_metadata</code>), a safety rating and explanations, and a variety of other information that will prove more useful depending on how we use Gemini (e.g., whether we use it with multimodal inputs, or with tool calling, code execution, etc…). You’ll see what I mean down below.</p>
<p>There is an async version of <code>generate_content</code> available via the <code>aio</code> property on your <code>client</code> instance. You just need to add <code>await</code> in front of the call.</p>
<div class="sourceCode" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb3-1">response <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> client.aio.models.generate_content(</span>
<span id="cb3-2">    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;">"gemini-2.0-flash-exp"</span>, contents<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"How far is the moon from the earth?"</span>, config<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>gen_config</span>
<span id="cb3-3">)</span></code></pre></div>
</div>
</div>
<div class="callout callout-style-default callout-tip 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">
Tip
</div>
</div>
<div class="callout-body-container callout-body">
<p>The <code>text</code> response is almost always going to be in Markdown, so why not make it look pretty in notebooks by doing a <code>from IPython.display import Markdown, display</code> and then <code>display(Markdown(response.text))</code>?</p>
</div>
</div>
</section>
<section id="if-you-are-using-vertex" class="level3">
<h3 class="anchored" data-anchor-id="if-you-are-using-vertex">If you are using Vertex …</h3>
<div class="sourceCode" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb4-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># this is the path to your json credentials file (at least it is to mine, :))</span></span>
<span id="cb4-2">GOOGLE_VERTEX_AI_CREDS <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> os.getenv(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"GOOGLE_VERTEX_AI_CREDS"</span>)</span>
<span id="cb4-3"></span>
<span id="cb4-4">SCOPES <span 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://www.googleapis.com/auth/cloud-platform"</span>]</span>
<span id="cb4-5">creds <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> service_account.Credentials.from_service_account_file(GOOGLE_VERTEX_AI_CREDS, scopes<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>SCOPES)</span>
<span id="cb4-6"></span>
<span id="cb4-7">client <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> genai.Client(vertexai<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>, project<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"generative-playground"</span>, location<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"us-central1"</span>, credentials<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>creds)</span>
<span id="cb4-8"></span>
<span id="cb4-9">response <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> client.models.generate_content(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;">"gemini-2.0-flash-exp"</span>, contents<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"How far is the moon from the earth?"</span>)</span>
<span id="cb4-10"></span>
<span id="cb4-11">display(Markdown(response.text))</span>
<span id="cb4-12"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># The distance between the Earth and the Moon is not constant, as the Moon's orbit is elliptical (an oval shape), not a perfect circle. Here's a breakdown:</span></span>
<span id="cb4-13"></span>
<span id="cb4-14"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Average Distance: The average distance is about 384,400 kilometers (238,900 miles). This is the number most commonly used.</span></span>
<span id="cb4-15"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Perigee: This is the point in the Moon's orbit where it is closest to Earth. At perigee, the distance can be as close as 363,104 kilometers (225,623 miles).</span></span>
<span id="cb4-16"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Apogee: This is the point in the Moon's orbit where it is furthest from Earth. At apogee, the distance can reach as far as 405,696 kilometers (252,088 miles).</span></span>
<span id="cb4-17"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># So, the answer is variable, but the average distance is approximately 384,400 kilometers (238,900 miles).</span></span>
<span id="cb4-18"></span>
<span id="cb4-19"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(response.usage_metadata)</span>
<span id="cb4-20"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># cached_content_token_count=None candidates_token_count=221 prompt_token_count=9 total_token_count=230</span></span></code></pre></div>
<p>We should expect to get something close to the same response from both the Gemini API and Vertex API. The only difference is with how you instantiate your Gemini <code>client</code>.</p>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>As of the time of this writing, Gemini 2.0 models are ONLY available at the “us-central1” location.</p>
</div>
</div>
<div class="callout callout-style-default 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">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>The previous SDK had a <code>list_models</code> method that would return a list of models (at least the Gemini API did). This is not supported in the new SDK at the time of this writing.</p>
<div class="sourceCode" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb5-1"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> model <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> client.models.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>():</span>
<span id="cb5-2">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(model)  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># ain't returning nothing useful</span></span></code></pre></div>
</div>
</div>
</section>
</section>
<section id="controlling-generation" class="level2">
<h2 class="anchored" data-anchor-id="controlling-generation">Controlling Generation</h2>
<p>You can influence the generation of content by providing a <code>GenerateContentConfig</code> object. With this object, you can provide a system instruction, safety settings, and generation parameters (e.g., temperature, top_p, etc.).</p>
<p>See also:</p>
<ul>
<li><a href="https://cloud.google.com/vertex-ai/generative-ai/docs/multimodal/content-generation-parameters">Content Generation Parameters</a></li>
<li><a href="https://cloud.google.com/vertex-ai/generative-ai/docs/multimodal/configure-safety-filters#harm_categories">Safety Settings</a></li>
</ul>
<div class="callout callout-style-default callout-tip 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">
Tip
</div>
</div>
<div class="callout-body-container callout-body">
<p>I tend to turn all of these “safety” settings off and it would be great if there is an easier way to do this in one-line vs what you see below</p>
</div>
</div>
<div class="sourceCode" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb6-1">safety_settings <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [</span>
<span id="cb6-2">    types.SafetySetting(category<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"HARM_CATEGORY_HATE_SPEECH"</span>, threshold<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"BLOCK_NONE"</span>),</span>
<span id="cb6-3">    types.SafetySetting(category<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"HARM_CATEGORY_DANGEROUS_CONTENT"</span>, threshold<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"BLOCK_NONE"</span>),</span>
<span id="cb6-4">    types.SafetySetting(category<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"HARM_CATEGORY_HARASSMENT"</span>, threshold<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"BLOCK_NONE"</span>),</span>
<span id="cb6-5">    types.SafetySetting(category<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"HARM_CATEGORY_SEXUALLY_EXPLICIT"</span>, threshold<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"BLOCK_NONE"</span>),</span>
<span id="cb6-6">]</span>
<span id="cb6-7"></span>
<span id="cb6-8">gen_config <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> types.GenerateContentConfig(</span>
<span id="cb6-9">    system_instruction<span 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 are an expert in all things astronomy and you ONLY provide very concise answers"</span>,</span>
<span id="cb6-10">    safety_settings<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>safety_settings,</span>
<span id="cb6-11">    temperature<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="cb6-12">    top_p<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.95</span>,</span>
<span id="cb6-13">    top_k<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;">20</span>,</span>
<span id="cb6-14">    candidate_count<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="cb6-15">    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;">5</span>,</span>
<span id="cb6-16">    max_output_tokens<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;">100</span>,</span>
<span id="cb6-17">    stop_sequences<span 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="cb6-18">    presence_penalty<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.0</span>,</span>
<span id="cb6-19">    frequency_penalty<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.0</span>,</span>
<span id="cb6-20">)</span>
<span id="cb6-21"></span>
<span id="cb6-22">response <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> client.models.generate_content(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;">"gemini-2.0-flash-exp"</span>, contents<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"How far is the moon from the earth?"</span>, config<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>gen_config)</span></code></pre></div>
<p>With that in place we can see that our response is now much more concise and to the point.</p>
<div class="sourceCode" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb7-1">response <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> client.models.generate_content(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;">"gemini-2.0-flash-exp"</span>, contents<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"How far is the moon from the earth?"</span>, config<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>gen_config)</span>
<span id="cb7-2"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(response.text)</span>
<span id="cb7-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># About 384,400 kilometers.</span></span>
<span id="cb7-4"></span>
<span id="cb7-5"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(response.usage_metadata)</span>
<span id="cb7-6"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># cached_content_token_count=None candidates_token_count=12 prompt_token_count=24 total_token_count=36</span></span></code></pre></div>
</section>
<section id="tokenization-goodies" class="level2">
<h2 class="anchored" data-anchor-id="tokenization-goodies">Tokenization Goodies</h2>
<p>You can use the <code>count_tokens</code> method to calculate <strong>the number of input tokens</strong> before sending a request to the Gemini API. Super helpful to understanding the cost implications of your requests. Async operations are available for both <code>count_tokens</code> and <code>compute_tokens</code> as well as most other methods on your <code>client</code> instance via the <code>aio</code> property.</p>
<div class="sourceCode" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb8-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># count_tokens</span></span>
<span id="cb8-2">response <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> client.models.count_tokens(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;">"gemini-2.0-flash-exp"</span>, contents<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"How far is the moon from the earth?"</span>)</span>
<span id="cb8-3"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(response)</span>
<span id="cb8-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># total_tokens=9 cached_content_token_count=None</span></span>
<span id="cb8-5"></span>
<span id="cb8-6"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</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</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</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb8-7"></span>
<span id="cb8-8"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># count_tokens async</span></span>
<span id="cb8-9">response <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> client.aio.models.count_tokens(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;">"gemini-2.0-flash-exp"</span>, contents<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"How far is the moon from the earth?"</span>)</span>
<span id="cb8-10"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(response)</span>
<span id="cb8-11"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># total_tokens=9 cached_content_token_count=None</span></span></code></pre></div>
<div class="callout callout-style-default 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">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>All of the <code>async</code> bits are available via the <code>aio</code> property on your <code>client</code> instance.</p>
</div>
</div>
<p>You can use <code>compute_tokens</code> to get the tokenized inputs (only available in Vertex AI). This can be really helpful in terms of understanding how the Gemini models tokenize your input and troubleshooing issues that might arise from generation.</p>
<div class="sourceCode" id="cb9" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb9-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># compute_tokens</span></span>
<span id="cb9-2">response <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> client.models.compute_tokens(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;">"gemini-2.0-flash-exp"</span>, contents<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"How far is the moon from the earth?"</span>)</span>
<span id="cb9-3"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(response)</span>
<span id="cb9-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># tokens_info=[TokensInfo(role='user', token_ids=['2299', '2166', '603', '573', '11883', '774', '573', '6683', '235336'], tokens=[b'How', b' far', b' is', b' the', b' moon', b' from', b' the', b' earth', b'?'])]</span></span>
<span id="cb9-5"></span>
<span id="cb9-6"></span>
<span id="cb9-7"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</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</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</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb9-8"></span>
<span id="cb9-9"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># compute_tokens async</span></span>
<span id="cb9-10">response <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> client.aio.models.compute_tokens(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;">"gemini-2.0-flash-exp"</span>, contents<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"How far is the moon from the earth?"</span>)</span>
<span id="cb9-11"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(response)</span>
<span id="cb9-12"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># tokens_info=[TokensInfo(role='user', token_ids=['2299', '2166', '603', '573', '11883', '774', '573', '6683', '235336'], tokens=[b'How', b' far', b' is', b' the', b' moon', b' from', b' the', b' earth', b'?'])]</span></span></code></pre></div>
<div class="callout callout-style-default callout-tip 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">
Tip
</div>
</div>
<div class="callout-body-container callout-body">
<p>Tokenization issues are often some of the biggest gotchas in issues folks have with working with LLMs. There’s an entire <a href="https://hamel.dev/blog/posts/course/" target="_blank">course</a> about the importance of looking at your data … and that means looking at your tokens.</p>
</div>
</div>
</section>
<section id="streaming-content" class="level2">
<h2 class="anchored" data-anchor-id="streaming-content">Streaming Content</h2>
<p>We’ve already seen how we can use the <code>generate_content</code> method to generate content but what if we want to stream the content as it is being generated?</p>
<p>The <code>generate_content_stream</code> method is a great way to stream content as it is generated. This is useful for things like chat interfaces or long-form content where you want to see the progress as it is being generated.</p>
<p>An async version is also available via the <code>aio</code> property.</p>
<div class="sourceCode" id="cb10" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb10-1"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> chunk <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> client.models.generate_content_stream(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;">"gemini-2.0-flash-exp"</span>, contents<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"How far is the moon from the earth?"</span>):</span>
<span id="cb10-2">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(chunk.text, end<span 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>, flush<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="cb10-3"></span>
<span id="cb10-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># The| distance between the Earth and the Moon is not constant, as the Moon's| orbit is elliptical. Here's a breakdown:</span></span>
<span id="cb10-5"></span>
<span id="cb10-6"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># * **Average Distance:**| The average distance between the Earth and the Moon is about **384,400 kilometers (238,900 miles)**. This| is the most commonly cited figure.</span></span>
<span id="cb10-7"></span>
<span id="cb10-8"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># * **Perigee:** This is the point in the Moon's orbit when it is closest to Earth. At| perigee, the distance can be as little as about **363,104 kilometers (225,623 miles)**.</span></span>
<span id="cb10-9"></span>
<span id="cb10-10"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># * **Apogee:** This is the point in the Moon's orbit| when it is farthest from Earth. At apogee, the distance can be as much as about **405,696 kilometers (252,088 miles)**.</span></span>
<span id="cb10-11"></span>
<span id="cb10-12"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># **Key Takeaway:** While we often| talk about the average distance, remember that the Moon's distance varies throughout its orbit, fluctuating between perigee and apogee.</span></span>
<span id="cb10-13"></span>
<span id="cb10-14"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># So, while the average is 384,400 kilometers, it's more accurate to say the distance ranges from about 363,000| km to 406,000 km.</span></span>
<span id="cb10-15"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|</span></span></code></pre></div>
<p>I’ve included the pipe character so you can see the chunks as they are being generated.</p>
</section>
<section id="multi-turn-chat" class="level2">
<h2 class="anchored" data-anchor-id="multi-turn-chat">Multi-Turn Chat</h2>
<p>The <code>chats</code> module provides a way to interact with the Gemini API in a multi-turn chat interface.</p>
<p>The <code>create</code> method is used to create a new chat session. The <code>send_message</code> method is used to send a message to the chat session.</p>
<p>The <code>history</code> parameter is used to provide the chat history.</p>
<div class="sourceCode" id="cb11" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb11-1">system_instruction <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> dedent(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb11-2"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">  You are an expert software developer and a helpful coding assistant.</span></span>
<span id="cb11-3"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">  You are able to generate high-quality code in any programming language.</span></span>
<span id="cb11-4"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"""</span>).strip()</span>
<span id="cb11-5"></span>
<span id="cb11-6">convo <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> []</span>
<span id="cb11-7">chat <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> client.chats.create(</span>
<span id="cb11-8">    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;">"gemini-2.0-flash-exp"</span>, config<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>types.GenerateContentConfig(system_instruction<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>system_instruction, temperature<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>), history<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>convo</span>
<span id="cb11-9">)</span></code></pre></div>
<p>You can now use <code>send_message</code> to add a message to the chat.</p>
<div class="sourceCode" id="cb12" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb12-1">response <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> chat.send_message(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Write a simple python program that accepts a person's name and returns a greeting."</span>)</span>
<span id="cb12-2"></span>
<span id="cb12-3">Markdown(response.text)</span>
<span id="cb12-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># def greet_person(name):</span></span>
<span id="cb12-5"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#   """</span></span>
<span id="cb12-6"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#   Greets a person by name.</span></span>
<span id="cb12-7"></span>
<span id="cb12-8"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#   Args:</span></span>
<span id="cb12-9"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#     name: The name of the person to greet (string).</span></span>
<span id="cb12-10"></span>
<span id="cb12-11"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#   Returns:</span></span>
<span id="cb12-12"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#     A greeting string.</span></span>
<span id="cb12-13"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#   """</span></span>
<span id="cb12-14"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#   return f"Hello, {name}!"</span></span>
<span id="cb12-15"></span>
<span id="cb12-16"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># if __name__ == "__main__":</span></span>
<span id="cb12-17"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#   person_name = input("Please enter your name: ")</span></span>
<span id="cb12-18"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#   greeting = greet_person(person_name)</span></span>
<span id="cb12-19"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#   print(greeting)</span></span>
<span id="cb12-20"></span>
<span id="cb12-21"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># ... and an extended explanation of the code I'm omitting here ...</span></span></code></pre></div>
<p>Currently we can look at, and even modify, the chat history by accessing the <code>_curated_history</code> property on the <code>chat</code> instance. That <code>_</code> prefix tells me this part of the SDK is still under construction and likely to change.</p>
<div class="sourceCode" id="cb13" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb13-1">chat._curated_history</span>
<span id="cb13-2"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># [Content(parts=[Part(video_metadata=None, code_execution_result=None, executable_code=None, file_data=None, function_call=None, function_response=None, inline_data=None, text="Write a simple python program that accepts a person's name and returns a greeting.")], role='user'),</span></span>
<span id="cb13-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#  Content(parts=[Part(video_metadata=None, code_execution_result=None, executable_code=None, file_data=None, function_call=None, function_response=None, inline_data=None, text='```python\ndef greet_person(name):\n  """\n  Greets a person by name.\n\n  Args:\n    name: The name of the person to greet (string).\n\n  Returns:\n    A greeting string.\n  """\n  return f"Hello, {name}!"\n\nif __name__ == "__main__":\n  person_name = input("Please enter your name: ")\n  greeting = greet_person(person_name)\n  print(greeting)\n```\n\n**Explanation:**\n\n1.  **`def greet_person(name):`**:\n    *   This line defines a function named `greet_person` that takes one argument, `name`.\n    *   The `name` argument will hold the person\'s name as a string.\n\n2.  **`"""..."""`**:\n    *   This is a docstring, which is a multiline string used to document what the function does. It\'s good practice to include docstrings to make your code more understandable.\n\n3.  **`return f"Hello, {name}!"`**:\n    *   This line uses an f-string (formatted string literal) to create the greeting.\n    *   `f"..."`  allows you to embed variables directly into the string by placing them inside curly braces `{}`.\n    *   The function returns the complete greeting string (e.g., "Hello, Alice!").\n\n4.  **`if __name__ == "__main__":`**:\n    *   This is a standard Python construct that ensures the code inside the `if` block only runs when the script is executed directly (not when it\'s imported as a module into another script).\n\n5.  **`person_name = input("Please enter your name: ")`**:\n    *   The `input()` function displays the message "Please enter your name: " to the user and waits for them to type something.\n    *   Whatever the user types is stored as a string in the `person_name` variable.\n\n6.  **`greeting = greet_person(person_name)`**:\n    *   This line calls the `greet_person` function, passing the `person_name` as an argument.\n    *   The function returns the greeting string, which is then stored in the `greeting` variable.\n\n7.  **`print(greeting)`**:\n    *   Finally, this line prints the greeting to the console.\n\n**How to run this code:**\n\n1.  Save the code in a file named, for example, `greeting.py`.\n2.  Open a terminal or command prompt.\n3.  Navigate to the directory where you saved the file.\n4.  Run the command `python greeting.py`.\n5.  The program will prompt you to enter your name. Type your name and press Enter.\n6.  The program will then print the greeting to the console.\n\n**Example Interaction:**\n\n```\nPlease enter your name: Bob\nHello, Bob!\n```\n')], role='model')</span></span></code></pre></div>
<div class="sourceCode" id="cb14" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb14-1">response <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> chat.send_message(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Okay, write a unit test of the generated function."</span>)</span>
<span id="cb14-2"></span>
<span id="cb14-3">Markdown(response.text)</span>
<span id="cb14-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># import unittest</span></span>
<span id="cb14-5"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># from greeting import greet_person  # Assuming the previous code is in greeting.py</span></span>
<span id="cb14-6"></span>
<span id="cb14-7"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># class TestGreeting(unittest.TestCase):</span></span>
<span id="cb14-8"></span>
<span id="cb14-9"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#     def test_greet_with_valid_name(self):</span></span>
<span id="cb14-10"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#         self.assertEqual(greet_person("Alice"), "Hello, Alice!")</span></span>
<span id="cb14-11"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#         self.assertEqual(greet_person("Bob"), "Hello, Bob!")</span></span>
<span id="cb14-12"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#         self.assertEqual(greet_person("Charlie"), "Hello, Charlie!")</span></span>
<span id="cb14-13"></span>
<span id="cb14-14"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#     def test_greet_with_empty_name(self):</span></span>
<span id="cb14-15"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#         self.assertEqual(greet_person(""), "Hello, !")</span></span>
<span id="cb14-16"></span>
<span id="cb14-17"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#     def test_greet_with_name_containing_spaces(self):</span></span>
<span id="cb14-18"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#         self.assertEqual(greet_person("John Doe"), "Hello, John Doe!")</span></span>
<span id="cb14-19"></span>
<span id="cb14-20"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#     def test_greet_with_name_containing_numbers(self):</span></span>
<span id="cb14-21"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#         self.assertEqual(greet_person("User123"), "Hello, User123!")</span></span>
<span id="cb14-22"></span>
<span id="cb14-23"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#     def test_greet_with_special_characters(self):</span></span>
<span id="cb14-24"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#         self.assertEqual(greet_person("!@#$%^"), "Hello, !@#$%^!")</span></span>
<span id="cb14-25"></span>
<span id="cb14-26"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># if __name__ == '__main__':</span></span>
<span id="cb14-27"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#     unittest.main()</span></span>
<span id="cb14-28"></span>
<span id="cb14-29"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># ... and an extended explanation of the code I'm omitting here ...</span></span></code></pre></div>
<p>Pretty cool!</p>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>Note the “role” names are a bit different than what you might expect. With Gemini 2.0, you’ll see “user” when the message comes from the user and “model” when the message comes from the the LLM.</p>
</div>
</div>
</section>
<section id="conclusion" class="level2">
<h2 class="anchored" data-anchor-id="conclusion">Conclusion</h2>
<p>The SDK is still being fleshed out but I’m excited about the prospect of being able build with Gemini regardless of which API I’m using. Hopefully, some of the tips and tricks above will help you get started regardless of which API flavor you prefer.</p>
<p>In the next post, we’ll look at how to take advantage of Gemini’s multimodal capabilities including how to incorporate few-shot examples for both text only and multimodal tasks.</p>


</section>

 ]]></description>
  <category>LLMS</category>
  <category>Gemini</category>
  <category>Google</category>
  <guid>https://ohmeow.com/posts/2024-12-24-gemini-part-2-sdk.html</guid>
  <pubDate>Tue, 24 Dec 2024 08:00:00 GMT</pubDate>
  <media:content url="https://ohmeow.com/posts/images/blog-20241213/blog-20241213-header.png" medium="image" type="image/png" height="144" width="144"/>
</item>
<item>
  <title>Gemini (Part I) - Why You Should Consider Gemini</title>
  <dc:creator>Wayde Gilliam</dc:creator>
  <link>https://ohmeow.com/posts/2024-12-13-gemini-part-1.html</link>
  <description><![CDATA[ 




<section id="gemini-in-a-nutshell" class="level2">
<h2 class="anchored" data-anchor-id="gemini-in-a-nutshell">Gemini in a Nutshell</h2>
<p><img src="https://ohmeow.com/posts/images/blog-20241213/gemini-figure.png" alt="Gemini" style="float:right;border-radius: 15px;width:150px;"></p>
<p>Gemini is a collection of smaller LLMs designed to deliver faster performance and lower costs while offering capabilities comparable to larger models. The recently released Gemini 2.0 builds on this foundation with enhanced performance, innovative real-time features, and a competitive price point that sets it apart from the competition.</p>
<p>In this series, we’ll explore the exciting possibilities with Gemini, including the new real-time features introduced in 2.0. To start, we’ll review the range of Gemini models, their unique capabilities, and how to choose the right one for your needs. From there, we’ll dive into how these models stack up against the competition in terms of both results and cost.</p>
<p>The core hypothesis driving this series is that the future lies in agentic systems composed of smaller and more cost efficient models. I believe organizations will achieve greater value by orchestrating smaller and general-use models to meet their goals, rather than by relying solely on large and expensive LLMs to address every use case.</p>
</section>
<section id="the-gemini-family" class="level2">
<h2 class="anchored" data-anchor-id="the-gemini-family">The Gemini Family</h2>
<p><span style="padding-top:5px;width:100%"> <a href="images/blog-20241213/gemini-model-collection.png" class="lightbox" data-gallery="quarto-lightbox-gallery-1" title="The Gemini Family"><img src="https://ohmeow.com/posts/images/blog-20241213/gemini-model-collection.png" class="img-fluid" style="width:100.0%" alt="The Gemini Family"></a> <em>Figure 1: The Gemini Famly (<a href="https://ai.google.dev/gemini-api/docs/models/gemini#model-variations" target="_blank">google</a>)</em> </span></p>
<div class="callout callout-style-default 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">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>When in doubt, use “Flash” to start and see how far that gets you. Personally, I’m getting great results for structured output tasks with Flash and sometimes even the 8B parameter variant.</p>
</div>
</div>
</section>
<section id="performance" class="level2">
<h2 class="anchored" data-anchor-id="performance">Performance</h2>
<p><strong>Internal Benchmarks</strong></p>
<p>To better understand how the latest Gemini 2.0 Flash Experimental model stacks up against its predecessors, let’s examine the reported benchmark results.</p>
<p>The following table highlights the performance improvements compared to the Gemini 1.5 generation models.</p>
<p><span style="padding-top:5px"> <a href="images/blog-20241213/gemini-benchmarks.jpeg" class="lightbox" data-gallery="quarto-lightbox-gallery-2" title="Overall performance comparison across models"><img src="https://ohmeow.com/posts/images/blog-20241213/gemini-benchmarks.jpeg" class="img-fluid" alt="Overall performance comparison across models"></a> <em>Figure 2: Reported benchmarks (<a href="https://blog.google/technology/google-deepmind/google-gemini-ai-update-december-2024/#gemini-2-0-flash" target="_blank">google</a>)</em> </span></p>
<p>The 1.5 models have worked really well for me across a number of projects and it looks like the 2.0 generation represents a substantial move in the right direction across the board! According to Google’s <a href="https://blog.google/technology/google-deepmind/google-gemini-ai-update-december-2024/" target="\_blank"> announcement post</a> …</p>
<blockquote class="blockquote">
<p>“Gemini 2.0 Flash builds on the success of 1.5 Flash, our most popular model yet for developers, with enhanced performance at similarly fast response times. Notably, 2.0 Flash even outperforms 1.5 Pro on key benchmarks, at twice the speed”</p>
</blockquote>
<p><strong>How Does It Compare to the Competition?</strong>x</p>
<p>Evaluating performance across large language models (LLMs) can be challenging due to the abundance of available benchmarks, not all of which provide consistent or reliable insights. Among these options, one resource that I’ve found consistently aligns with my own experiences is <a href="https://lmarena.ai/" target="\_blank">lmarena.ai (formerly LMSYS)</a>, which I will reference for this comparison.</p>
<p><span style="padding-top:5px"> <a href="images/blog-20241213/lmarena-overall.png" class="lightbox" data-gallery="quarto-lightbox-gallery-3" title="Overall performance comparison across models"><img src="https://ohmeow.com/posts/images/blog-20241213/lmarena-overall.png" class="img-fluid" data-margin="20px" alt="Overall performance comparison across models"></a> <em>Figure 2: Overall performance comparison across leading LLM models (courtesy of <a href="https://lmarena.ai/" target="_blank">lmarena.ai</a>)</em> </span> <span style="padding-top:5px"> <a href="images/blog-20241213/lmarena-overall-flash1-5.png" class="lightbox" data-gallery="quarto-lightbox-gallery-4" title="Gemini 1.5 Flash"><img src="https://ohmeow.com/posts/images/blog-20241213/lmarena-overall-flash1-5.png" class="img-fluid" data-margin="20px" alt="Gemini 1.5 Flash"></a> </span></p>
<p><span style="padding-top:5px"> <a href="images/blog-20241213/lmarena-details.png" class="lightbox" data-gallery="quarto-lightbox-gallery-5" title="Detailed performance metrics by category"><img src="https://ohmeow.com/posts/images/blog-20241213/lmarena-details.png" class="img-fluid" alt="Detailed performance metrics by category"></a> <em>Figure 3: Detailed breakdown of performance metrics across different categories (courtesy of <a href="https://lmarena.ai/" target="_blank">lmarena.ai</a>)</em> </span> <span style="padding-top:5px"> <a href="images/blog-20241213/lmarena-details-flash1-5.png" class="lightbox" data-gallery="quarto-lightbox-gallery-6" title="Gemini 1.5 Flash"><img src="https://ohmeow.com/posts/images/blog-20241213/lmarena-details-flash1-5.png" class="img-fluid" data-margin="20px" alt="Gemini 1.5 Flash"></a> </span></p>
<p>That’s alot of Geminis up there at the top!</p>
</section>
<section id="cost" class="level2">
<h2 class="anchored" data-anchor-id="cost">Cost</h2>
<p>As AI becomes an increasingly integral part of application infrastructure, the cost of using these models is becoming a critical consideration. Understanding how costs vary across providers like OpenAI, Anthropic, and others is essential for making informed decisions. So, how do the costs of using these models generally compare, and where does Gemini stand in this landscape?</p>
<table class="caption-top table">
<colgroup>
<col style="width: 12%">
<col style="width: 22%">
<col style="width: 13%">
<col style="width: 25%">
<col style="width: 26%">
</colgroup>
<thead>
<tr class="header">
<th>Provider</th>
<th>Model</th>
<th>Max Tokens</th>
<th>Input Cost (per 1M)</th>
<th>Output Cost (per 1M)</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>OpenAI</td>
<td>GPT-4o</td>
<td>128,000</td>
<td>$2.50</td>
<td>$10.00</td>
</tr>
<tr class="even">
<td>OpenAI</td>
<td>GPT-4o mini</td>
<td>128,000</td>
<td>$0.15</td>
<td>$0.60</td>
</tr>
<tr class="odd">
<td>OpenAI</td>
<td>GPT-4 Turbo</td>
<td>128,000</td>
<td>$10.00</td>
<td>$30.00</td>
</tr>
<tr class="even">
<td>OpenAI</td>
<td>GPT-3.5 Turbo</td>
<td>16,384</td>
<td>$0.50</td>
<td>$1.50</td>
</tr>
<tr class="odd">
<td>Anthropic</td>
<td>Claude 3.5 Sonnet</td>
<td>200,000</td>
<td>$3.00</td>
<td>$15.00</td>
</tr>
<tr class="even">
<td>Anthropic</td>
<td>Claude 3.5 Haiku</td>
<td>200,000</td>
<td>$0.25</td>
<td>$1.25</td>
</tr>
<tr class="odd">
<td>Google</td>
<td>Gemini 1.5 Pro</td>
<td>1,048,576</td>
<td>$1.25</td>
<td>$5.00</td>
</tr>
<tr class="even">
<td>Google</td>
<td>Gemini 1.5 Flash</td>
<td>1,048,576</td>
<td>$0.075</td>
<td>$0.30</td>
</tr>
</tbody>
</table>
<p><em>Note: Input tokens refer to the tokens in the prompt sent to the model, while output tokens are those generated by the model in response.</em></p>
<div class="callout callout-style-default 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">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>The cost of using Gemini is often a fraction of the cost of other models. In fact, for “experimental” models, you aren’t billed at all</p>
<blockquote class="blockquote">
<p>You aren’t billed for the usage of experimental Google models.<br>
<a href="https://cloud.google.com/vertex-ai/generative-ai/docs/gemini-v2" target="\_blank">Generative AI on Vertex AI pricing for experimental models</a></p>
</blockquote>
</div>
</div>
</section>
<section id="conclusion" class="level2">
<h2 class="anchored" data-anchor-id="conclusion">Conclusion</h2>
<p>If the future is indeed agentic, as I hypothesize, and cost-efficient, high-performing, general-use models play a central role in that vision, then Gemini emerges as a compelling choice. Based on the comparison of performance between Gemini models and those of other major API providers, combined with its cost-effectiveness, Gemini is undoubtedly worth considering as part of your AI strategy moving forward.</p>
<p>In the next blog in this series, we’ll explore the basics of using Gemini and dive into some of its standout features that set it apart from the competition using the new and improved unified SDK in 2.0. This unified SDK is one of the more exicting bits to developers like myself that have had to bounce back-and-forth between using the Gemini API and Vertex API to talk with Gemini. With 2.0, we finally have one SDK to rule them all (even if it still means we need to understand how the two different API options vary and when to use one over the other … something we’ll talk about in the next post as well).</p>


</section>

 ]]></description>
  <category>LLMS</category>
  <category>Gemini</category>
  <category>Google</category>
  <guid>https://ohmeow.com/posts/2024-12-13-gemini-part-1.html</guid>
  <pubDate>Fri, 13 Dec 2024 08:00:00 GMT</pubDate>
  <media:content url="https://ohmeow.com/posts/images/blog-20241213/blog-20241213-header.png" medium="image" type="image/png" height="144" width="144"/>
</item>
<item>
  <title>LLM Workshop #4 - L1 Evals and Dataset Curation (Part I)</title>
  <dc:creator>Wayde Gilliam</dc:creator>
  <link>https://ohmeow.com/posts/2024-07-25-llm-workshop-evals-dataset-curation.html</link>
  <description><![CDATA[ 




<section id="iterating-quickly" class="level2">
<h2 class="anchored" data-anchor-id="iterating-quickly">Iterating Quickly</h2>
<div>
<p>Two recurring themes from the workshop are “look at your data (alot)” and iterate quickly. When building AI powered applications, we will need three things in place to make both a reality.</p>
<p><img src="https://ohmeow.com/posts/images/blog-20240727/hamel-eval-flow.png" alt="Hame's Evalulation Workflow" style="float:right;border-radius: 15px;width:450px;"></p>
<ol type="1">
<li><p>A mechanism to evaluate performance.</p></li>
<li><p>A mechanism to look at our data and see where things are working well or not so well (overall and by example).</p></li>
<li><p>The ability to make modifications to our system and measure how well they improved things or not.</p></li>
<li><p>The ability to curate datasets that can be used for better evals and fine tuning.</p></li>
</ol>
</div>
<div style="clear:both;padding-top:20px;">
<p>So having prototyed our tool calling application with off the shelf models, the recommendation is to get going in building such a mechanism with the inclusion of “simple tests and assertions.” Hamel calls these tests <strong>“L1 Evals”</strong> (e.g., Level 1: Unit Tests) and describes them like this in his blog post, <a href="https://hamel.dev/blog/posts/evals/" target="\_blank">“Your AI Product Needs Evals”</a>:</p>
<blockquote class="blockquote">
<p>Unit tests for LLMs are assertions (like you would write in pytest). Unlike typical unit tests, you want to organize these assertions for use in places beyond unit tests, such as data cleaning and automatic retries (using the assertion error to course-correct) during model inference. The important part is that these assertions should run fast and cheaply as you develop your application so that you can run them every time your code changes. <img src="https://ohmeow.com/posts/images/blog-20240603/hamel-icon.png" alt="Hamel" style="border-radius:30px;width:auto;height:25px;"></p>
</blockquote>
<p>In the case of our tool calling project here, these may take the form of scoring functions that verify the model returns JSON, calls all the tools expected, and doesn’t generate any errors.</p>
<p>To begin with, what makes for a “great” eval and how do great evals allow us to “look at our data” and iterate with speed?</p>
</div>
</section>
<section id="what-is-a-great-eval" class="level2">
<h2 class="anchored" data-anchor-id="what-is-a-great-eval">What is a “Great Eval”?</h2>
<p>I really liked the definition <a href="https://x.com/ankrgyl" target="\_blank">Ankur Goyal</a>’s provided in his conference talk on doing <a href="https://www.braintrust.dev/" target="\_blank">LLM Eval For Text2SQL</a>. He says that a “great eval” is comprised of three componnents:</p>
<ol type="1">
<li>Some <strong>data</strong> to act on</li>
<li>A <strong>task</strong> to perform with that data (e.g., “I want you to take some input and generate some output”)</li>
<li>One or more <strong>scoring</strong> functions that measure how well your task did the job</li>
</ol>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://ohmeow.com/posts/images/blog-20240727/ankur-great-eval-def.png" class="img-fluid figure-img"></p>
<figcaption>The anatomy of a great eval</figcaption>
</figure>
</div>
<div class="callout callout-style-default 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">
Why you should eval?
</div>
</div>
<div class="callout-body-container callout-body">
<p>Ankur provides 4 key reasons:</p>
<ol type="1">
<li>To understand whether an update you made is an improvement or a regression (is it easy to figure this out?)</li>
<li>Drill down into good or bad examples (is it easy to get at them?)</li>
<li>Diff specific examples vs.&nbsp;prior runs (is it easy to see how your current evals did against your last evals?)</li>
<li>Avoid playing whack-a-mole (can you easily track and know what you broke and/or fixed as you develop)</li>
</ol>
</div>
</div>
<p>So as we iterate through our evaluation pipeline, that’s what we’ll do. At each step we’ll grab some data, define a task, and configure a number of scoring functions. It’s really that simple. That is an “eval.”</p>
<p>But before we get to that, what exaclty is an “L1” eval?</p>
</section>
<section id="level-1-unit-tests-l1-evals" class="level2">
<h2 class="anchored" data-anchor-id="level-1-unit-tests-l1-evals">Level 1: Unit Tests (L1 Evals)</h2>
<p>From the blog post mentioned above, we can infer some things about these particular evals.</p>
<ol type="1">
<li><p>Each should test a specific feature or scenario (e.g., the model called all the tools we expected).</p></li>
<li><p>They can also be general tests that aren’t specific to any feature or scenario (e.g., the model returns valid JSON).</p></li>
<li><p>You can use an LLM to synthetically generate inputs for these evals if necessary (<a href="https://hamel.dev/blog/posts/evals/#step-2-create-test-cases" target="\_blank">see here for an exmaple</a>)</p></li>
<li><p>You need to be able to track the results of these tests over time.</p></li>
</ol>
<div class="callout callout-style-default callout-important 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">
You will continuously update these evals
</div>
</div>
<div class="callout-body-container callout-body">
<p>As you observe new failures, you should update your evals to capture those use cases. “You must constantly update these tests as you observe data through human evaluation and debugging. The key is to make these as challenging as possible while representing users’ interactions with the system.” <img src="https://ohmeow.com/posts/images/blog-20240603/hamel-icon.png" alt="Hamel" style="border-radius:30px;width:auto;height:25px;"></p>
</div>
</div>
<p>And remember this very important advice on interpreting the worthiness of your evals …</p>
<div class="callout callout-style-default callout-important 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">
The pass rate is a product decision
</div>
</div>
<div class="callout-body-container callout-body">
<p>“One signal you are writing good tests and assertions is when the model struggles to pass them - these failure modes become problems you can solve with techniques like fine-tuning later on … unlike traditional unit tests, you don’t necessarily need a 100% pass rate. Your pass rate is a product decision, depending on the failures you are willing to tolerate.” <img src="https://ohmeow.com/posts/images/blog-20240603/hamel-icon.png" alt="Hamel" style="border-radius:30px;width:auto;height:25px;"></p>
</div>
</div>
<p>Lucky for us there is a really great tool that does all of this. It’s called <a href="https://www.braintrust.dev/" target="\_blank"><strong>Braintrust</strong></a> and it’s awesome! Before we get to it, we need to prepare a dataset to generate some predictions from.</p>
</section>
<section id="eval-preparation" class="level2">
<h2 class="anchored" data-anchor-id="eval-preparation">Eval Preparation</h2>
<p>Before we start eval’ng, we need to define our tools and a few methods for building a dataset we can pipe into Braintrust to get some initial feedback.</p>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>At this stage it’s important to note that we don’t have any “targets” or “expected” outputs to measure our “outputs” by. As this is where we really want to get too, we’ll use these iteration to build up such a dataset one experiment at at time.</p>
</div>
</div>
<section id="dataset" class="level3">
<h3 class="anchored" data-anchor-id="dataset">Dataset</h3>
<p>We need to be able to build representative sampled datasets of various sizes at this stage. We want to create a varied set of examples each time we pull a subset of data, where each example has the following attributes:</p>
<ul>
<li>A prompt to call one or more tools</li>
<li>The document(s) to act on as context</li>
<li>The number of tools we expect to be called</li>
<li>A list of the tools we expect to be called.</li>
</ul>
<p>When building the “prompt” for each example, I randomly grab a task specific prompt for each tool that should be called and merge them all together to make up the final “prompt”.</p>
<div class="callout callout-style-default callout-tip 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">
Tip: Use an LLM for synthetic data generation
</div>
</div>
<div class="callout-body-container callout-body">
<p>In retrospect, it probably would have been better if I had used an LLM to generate these prompts synthetically so as to make them more grammatically correct.</p>
</div>
</div>
<p>Anyhow, I’m not going to get into this step as its so use case specific. The code is posted below. Feel free to take a look (or not) for some inspiration on ideas you may be able to apply in your own work. As always, if you see improvements I could make … let me know. :)</p>
<div id="cell-6" class="cell">
<details class="code-fold">
<summary>Code to create evaluation datasets</summary>
<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;"># For each task/tool, I include a number of prompts I imagine a user might use to implore the AI to perform</span></span>
<span id="cb1-2"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># that task.  When I build the actually examples, I randomly grab a single item for each task that should</span></span>
<span id="cb1-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># be called to build the final user prompt</span></span>
<span id="cb1-4">example_translation_asks <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [</span>
<span id="cb1-5">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"If the text below is not in English, translate it into English; otherwise, return the text as is"</span>,</span>
<span id="cb1-6">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Translate the text below into English if it is not already in English; if it is, return it unchanged"</span>,</span>
<span id="cb1-7">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"If the provided text is in a language other than English, translate it to English; if it's already in English, return it without changes"</span>,  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># noqa: E501</span></span>
<span id="cb1-8">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Translate the following text to English if it is not written in English; otherwise, leave it unaltered"</span>,</span>
<span id="cb1-9">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"If the text below is not in English, convert it to English; if it is in English, return it without modification"</span>,</span>
<span id="cb1-10">]</span>
<span id="cb1-11"></span>
<span id="cb1-12">example_summarization_asks <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [</span>
<span id="cb1-13">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Provide a short summary of the text below and identify any overarching themes"</span>,</span>
<span id="cb1-14">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Summarize the document below and highlight any broad themes present"</span>,</span>
<span id="cb1-15">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Create a concise summary of the following document and identify any general themes"</span>,</span>
<span id="cb1-16">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Extract a brief 1-2 sentence summary from the text below and determine any broad themes"</span>,</span>
<span id="cb1-17">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Summarize the text below in 1-2 sentences and identify any major themes within it"</span>,</span>
<span id="cb1-18">]</span>
<span id="cb1-19">example_ner_asks <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [</span>
<span id="cb1-20">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Extract the named entities from the author's statement below"</span>,</span>
<span id="cb1-21">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Determine the named entities in the document below"</span>,</span>
<span id="cb1-22">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Identify the specific named entities in the statement below"</span>,</span>
<span id="cb1-23">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Perform NER on the text below"</span>,</span>
<span id="cb1-24">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Do NER on the document below"</span>,</span>
<span id="cb1-25">]</span>
<span id="cb1-26">example_sentiment_asks <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [</span>
<span id="cb1-27">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Determine the sentiment expressed in the document below"</span>,</span>
<span id="cb1-28">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Do sentiment analysis on the text below"</span>,</span>
<span id="cb1-29">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Identify and classify the sentiments expressed in the following document"</span>,</span>
<span id="cb1-30">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Perform sentiment analysis on the document below"</span>,</span>
<span id="cb1-31">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Extract the sentiment from the document below"</span>,</span>
<span id="cb1-32">]</span>
<span id="cb1-33">example_theme_asks <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [</span>
<span id="cb1-34">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Identify the theme in the documents below and create an action plan based on them"</span>,</span>
<span id="cb1-35">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Determine the theme in the provided documents and develop an action plan accordingly"</span>,</span>
<span id="cb1-36">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Extract the theme in the documents below and formulate an action plan based on your findings"</span>,</span>
<span id="cb1-37">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Based on the documents provided, extract their theme and an action plan based on them"</span>,</span>
<span id="cb1-38">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"What is a good theme that describes the text below? Also include an action plan based on the provided documents"</span>,</span>
<span id="cb1-39">]</span>
<span id="cb1-40"></span>
<span id="cb1-41"></span>
<span id="cb1-42"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Given a list of tools to call and whether our context is a single document or a colleciton of documents,</span></span>
<span id="cb1-43"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># this utility function does the work of coallesicing all the asks into a single human prompt.  Note how</span></span>
<span id="cb1-44"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># for "translation" tasks we sometimes ask for translation specifically and at other times we don't because</span></span>
<span id="cb1-45"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># I hope that ultimately, the model can just see the text is not in English and do the translation task</span></span>
<span id="cb1-46"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># without being specifically asked too.</span></span>
<span id="cb1-47"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> build_hypothetical_prompt(tool_names, is_doc: <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>
<span id="cb1-48">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Vary the overall format of the prompt for different styles by which a user may ask for</span></span>
<span id="cb1-49">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># different tasks</span></span>
<span id="cb1-50">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> random.choice([<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>]):</span>
<span id="cb1-51">        queries <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> []</span>
<span id="cb1-52">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> tool_name <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> tool_names:</span>
<span id="cb1-53">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> tool_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;">"TranslationTask"</span>:</span>
<span id="cb1-54">                <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Vary this being asked explicity so model can learn to call this tool whenver</span></span>
<span id="cb1-55">                <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># it detects a non-English document</span></span>
<span id="cb1-56">                <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> random.choice([<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>]):</span>
<span id="cb1-57">                    queries.append(random.choice(example_translation_asks))</span>
<span id="cb1-58">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">elif</span> tool_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;">"DocumentSummaryTask"</span>:</span>
<span id="cb1-59">                queries.append(random.choice(example_summarization_asks))</span>
<span id="cb1-60">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">elif</span> tool_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;">"DocumentNERTask"</span>:</span>
<span id="cb1-61">                queries.append(random.choice(example_ner_asks))</span>
<span id="cb1-62">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">elif</span> tool_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;">"DocumentSentimentTask"</span>:</span>
<span id="cb1-63">                queries.append(random.choice(example_sentiment_asks))</span>
<span id="cb1-64">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">elif</span> tool_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;">"TopicSummaryTask"</span>:</span>
<span id="cb1-65">                queries.append(random.choice(example_theme_asks))</span>
<span id="cb1-66"></span>
<span id="cb1-67">        prompt <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> queries[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>]</span>
<span id="cb1-68">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> q <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> queries[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>:]:</span>
<span id="cb1-69">            prompt <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>q<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="cb1-70">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span>:</span>
<span id="cb1-71">        tasks <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> []</span>
<span id="cb1-72">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> tool_name <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> tool_names:</span>
<span id="cb1-73">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> tool_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;">"DocumentSummaryTask"</span>:</span>
<span id="cb1-74">                tasks.append(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"summarization"</span>)</span>
<span id="cb1-75">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">elif</span> tool_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;">"DocumentNERTask"</span>:</span>
<span id="cb1-76">                tasks.append(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"named entity recognition (ner)"</span>)</span>
<span id="cb1-77">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">elif</span> tool_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;">"DocumentSentimentTask"</span>:</span>
<span id="cb1-78">                tasks.append(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"sentiment analysis"</span>)</span>
<span id="cb1-79">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">elif</span> tool_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;">"TopicSummaryTask"</span>:</span>
<span id="cb1-80">                tasks.append(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"thematic analysis/action planning"</span>)</span>
<span id="cb1-81"></span>
<span id="cb1-82">        random.shuffle(tasks)</span>
<span id="cb1-83"></span>
<span id="cb1-84">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> is_doc:</span>
<span id="cb1-85">            tasks.insert(<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;">"translation (if the document is not in English)"</span>)</span>
<span id="cb1-86"></span>
<span id="cb1-87">        prompt <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"Tasks: </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;">', '</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>join(tasks)<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="cb1-88"></span>
<span id="cb1-89">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> prompt.strip()</span>
<span id="cb1-90"></span>
<span id="cb1-91"></span>
<span id="cb1-92"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># When building examples, I use these weights to ensure some tasks are more frequently asked for than</span></span>
<span id="cb1-93"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># others. I'm doing this because it's my observation that this is what is more likely to be seen at</span></span>
<span id="cb1-94"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># inference time.</span></span>
<span id="cb1-95"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> get_tool_option_weights(tool_options: <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;">str</span>]):</span>
<span id="cb1-96">    weights <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [</span>
<span id="cb1-97">        <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.1</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> i <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="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.9</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;">len</span>(tool_options) <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="cb1-98">        <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;">1</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(tool_options) <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="cb1-99">    ]</span>
<span id="cb1-100">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> weights</span>
<span id="cb1-101"></span>
<span id="cb1-102"></span>
<span id="cb1-103"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># This is the function that will be called to build a sampled dataset. It's designed to give the</span></span>
<span id="cb1-104"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># developer the ability to determine how many, and of what type, of data it should get from the</span></span>
<span id="cb1-105"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># document datasets created earlier. It also determines a random number of tools to call and</span></span>
<span id="cb1-106"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># includes that information in the dataset to be used for evals (e.g., testing that all expected</span></span>
<span id="cb1-107"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># tools were called, etc...)</span></span>
<span id="cb1-108"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> get_sample(</span>
<span id="cb1-109">    docs_df: pd.DataFrame,</span>
<span id="cb1-110">    topics_df: pd.DataFrame,</span>
<span id="cb1-111">    n_docs: <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;">5</span>,</span>
<span id="cb1-112">    n_docs_non_english: <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;">2</span>,</span>
<span id="cb1-113">    n_chunks: <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;">5</span>,</span>
<span id="cb1-114">    n_topics: <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;">5</span>,</span>
<span id="cb1-115">    random_state: <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="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;">None</span>,</span>
<span id="cb1-116">):</span>
<span id="cb1-117">    random.seed(random_state)</span>
<span id="cb1-118"></span>
<span id="cb1-119">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Add in some full and chunked documents for single document analysis</span></span>
<span id="cb1-120">    df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> docs_df.copy()</span>
<span id="cb1-121">    test_df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> df[df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"AnswerLang"</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;">"Spanish"</span>].sample(</span>
<span id="cb1-122">        n<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>n_docs_non_english, random_state<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>random_state</span>
<span id="cb1-123">    )</span>
<span id="cb1-124">    test_df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"AnswerText"</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> test_df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"AnswerText_NonEnglish"</span>]</span>
<span id="cb1-125">    test_df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> pd.concat(</span>
<span id="cb1-126">        [</span>
<span id="cb1-127">            test_df,</span>
<span id="cb1-128">            df[df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"AnswerLang"</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;">"English"</span>].sample(</span>
<span id="cb1-129">                n<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>n_docs, random_state<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>random_state</span>
<span id="cb1-130">            ),</span>
<span id="cb1-131">        ]</span>
<span id="cb1-132">    )</span>
<span id="cb1-133">    test_df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"_seq_id"</span>] <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="cb1-134">    test_df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"_chunk_id"</span>] <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="cb1-135">    test_df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> test_df.rename(columns<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>{<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"AnswerText"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"_text"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"AnswerLang"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"_lang"</span>})</span>
<span id="cb1-136">    test_df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> test_df[[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"MLVerbatimId"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"_seq_id"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"_chunk_id"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"_text"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"_lang"</span>]]</span>
<span id="cb1-137"></span>
<span id="cb1-138">    chunk_df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> df.sample(n<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>n_chunks, random_state<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>random_state)</span>
<span id="cb1-139">    chunk_df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> chunk_df.rename(columns<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>{<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"_chunk"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"_text"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"AnswerLang"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"_lang"</span>})</span>
<span id="cb1-140">    chunk_df[<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;">"English"</span></span>
<span id="cb1-141">    chunk_df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> chunk_df[[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"MLVerbatimId"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"_seq_id"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"_chunk_id"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"_text"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"_lang"</span>]]</span>
<span id="cb1-142"></span>
<span id="cb1-143">    test_df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> pd.concat([test_df, chunk_df])</span>
<span id="cb1-144">    test_df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> test_df.drop_duplicates(subset<span 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>], keep<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"first"</span>)</span>
<span id="cb1-145"></span>
<span id="cb1-146">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Get a list as of dicts</span></span>
<span id="cb1-147">    test_data_d <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> test_df.to_dict(orient<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"records"</span>)</span>
<span id="cb1-148"></span>
<span id="cb1-149">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Randomize the tools and the number of tools being called for variety</span></span>
<span id="cb1-150">    tool_options <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"DocumentSummaryTask"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"DocumentNERTask"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"DocumentSentimentTask"</span>]</span>
<span id="cb1-151">    tool_option_weights <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> get_tool_option_weights(tool_options)</span>
<span id="cb1-152">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> example <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> test_data_d:</span>
<span id="cb1-153">        tools_to_call <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> []</span>
<span id="cb1-154">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> example[<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;">"English"</span>:</span>
<span id="cb1-155">            tools_to_call.append(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"TranslationTask"</span>)</span>
<span id="cb1-156"></span>
<span id="cb1-157">        n_tools <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> random.choices(</span>
<span id="cb1-158">            <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;">1</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(tool_options) <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>), weights<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>tool_option_weights, k<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="cb1-159">        )[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>]</span>
<span id="cb1-160">        tools_to_call <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+=</span> random.sample(tool_options, n_tools)</span>
<span id="cb1-161"></span>
<span id="cb1-162">        <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;">len</span>(example[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"_text"</span>]) <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;">940</span>:</span>
<span id="cb1-163">            <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># For longer documents, vary the inclusion of 'TopicSummary'</span></span>
<span id="cb1-164">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> random.choice([<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>]):</span>
<span id="cb1-165">                tools_to_call.append(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"TopicSummaryTask"</span>)</span>
<span id="cb1-166"></span>
<span id="cb1-167">        example[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"_n_tools"</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;">len</span>(tools_to_call)</span>
<span id="cb1-168">        example[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"_tools"</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tools_to_call</span>
<span id="cb1-169">        example[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ask"</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> build_hypothetical_prompt(tools_to_call, is_doc<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-170"></span>
<span id="cb1-171">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Add in some summaries for related document analsysis</span></span>
<span id="cb1-172">    df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> topics_df.copy()</span>
<span id="cb1-173">    test_df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> df[df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"pred_theme_id"</span>] <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>].sample(</span>
<span id="cb1-174">        n<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>n_topics, random_state<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>random_state</span>
<span id="cb1-175">    )</span>
<span id="cb1-176">    test_df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> test_df.rename(columns<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>{<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"_chunk"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"_text"</span>})</span>
<span id="cb1-177">    test_df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> test_df[[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"pred_theme_id"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"_text"</span>]]</span>
<span id="cb1-178"></span>
<span id="cb1-179">    test_df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> test_df.drop_duplicates(subset<span 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>], keep<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"first"</span>)</span>
<span id="cb1-180"></span>
<span id="cb1-181">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Get a list as of dicts</span></span>
<span id="cb1-182">    topics_test_data_d <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> test_df.to_dict(orient<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"records"</span>)</span>
<span id="cb1-183"></span>
<span id="cb1-184">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Randomize the tools and the number of tools being called for variety</span></span>
<span id="cb1-185">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> example <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> topics_test_data_d:</span>
<span id="cb1-186">        tools_to_call <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"TopicSummaryTask"</span>]</span>
<span id="cb1-187">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Randomly throw in the sentiment task 'DocumentSentimentTask'</span></span>
<span id="cb1-188">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> random.choice([<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>]):</span>
<span id="cb1-189">            tools_to_call.append(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"DocumentSentimentTask"</span>)</span>
<span id="cb1-190"></span>
<span id="cb1-191">        example[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"_n_tools"</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;">len</span>(tools_to_call)</span>
<span id="cb1-192">        example[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"_tools"</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tools_to_call</span>
<span id="cb1-193">        example[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ask"</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> build_hypothetical_prompt(tools_to_call, is_doc<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="cb1-194"></span>
<span id="cb1-195">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> test_data_d <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> topics_test_data_d</span></code></pre></div>
</details>
</div>
</section>
</section>
<section id="build-evals-with-braintrust" class="level2">
<h2 class="anchored" data-anchor-id="build-evals-with-braintrust">Build Evals with Braintrust</h2>
<p>To get started, log into braintrust, click the dropdown in the top-left (will have your username in there) and select “+ Create Project”. Give that project a name (e.g., ftcourse_project) and you’re good to go. You’ll need to create an API key and add it to your environmental variables to interact with that project in your code.</p>
<div class="callout callout-style-default 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">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>One of the things I love about Braintrust is how clean and intuitive the product is. You can tell it is built by folks who have themselves been in the trenches. It isn’t cluttered with a bunch of information I don’t care about, navigation is easy, and I can usually figure out where I need to go and what I need to do without have to consult the documentation. It provides the kind of experience every vendor should aspire too!</p>
<p>Tools like this go a long way in minimizing friction and allowing us to iterate faster.</p>
</div>
</div>
<section id="iteration-0-initial-evals" class="level3">
<h3 class="anchored" data-anchor-id="iteration-0-initial-evals">Iteration 0: Initial Evals</h3>
<p><strong>Objective</strong>: Generate a small set of examples (&lt; 25) to validate the evaluation pipeline with some simple scoring functions since we don’t have any expected values to compare our predictions with. We will remedy this by using the output from this iteration to begin building a “golden dataset” (reviewed/corrected inputs and outputs). After review, we’ll be able to incorporate this dataset in further evals and as a training dataset if we decide to finetune our own model.</p>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>Just like with training a neural network, the recommendation her is to start with a very small datasent with which you can verify your eval pipeline works as expected.</p>
</div>
</div>
<p>So lets define a “great” eval. For that we need some data, a task, and some scoring functions.</p>
<section id="data" class="level4">
<h4 class="anchored" data-anchor-id="data">Data</h4>
<p>See the <code>get_sample()</code> function in the eval prep section above if you’re curious about how I’m building sampled datasets for this project.</p>
<div id="cell-11" class="cell">
<div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb2-1">docs_df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> pd.read_parquet(</span>
<span id="cb2-2">    <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>DATA_DIR<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;">/clean/</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>DATA_FILENAME<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;">_sample_14k_chunked.parquet"</span></span>
<span id="cb2-3">)</span>
<span id="cb2-4"><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;">len</span>(docs_df))</span>
<span id="cb2-5"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># 18955</span></span>
<span id="cb2-6"></span>
<span id="cb2-7">topics_df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> pd.read_parquet(</span>
<span id="cb2-8">    <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>DATA_DIR<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;">/clean/</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>DATA_FILENAME<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;">_sample_14k_topics.parquet"</span></span>
<span id="cb2-9">)</span>
<span id="cb2-10"><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;">len</span>(topics_df))</span>
<span id="cb2-11"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># 976</span></span>
<span id="cb2-12"></span>
<span id="cb2-13">test_data <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> get_sample(</span>
<span id="cb2-14">    docs_df,</span>
<span id="cb2-15">    topics_df,</span>
<span id="cb2-16">    n_docs<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="cb2-17">    n_docs_non_english<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="cb2-18">    n_chunks<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="cb2-19">    n_topics<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="cb2-20">    random_state<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="cb2-21">)</span>
<span id="cb2-22"><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;">len</span>(test_data))</span>
<span id="cb2-23"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># 15</span></span></code></pre></div>
</div>
<div class="callout callout-style-default 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">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>Look at your data … ALOT! I think Hamel is the “look at your data” guy but honestly, I heard it from so many folks in the workshop there might be many “look at your data” guys. Either way, this is solid advice for any ML/AI application.</p>
</div>
</div>
<p>Here you can see the user prompt dynamically created for this example, the number of tools it should call, what tools it should specifically call, along with the text we want to operate on and a unique ID for this collection of documents.</p>
<div id="cell-13" class="cell">
<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">r <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> test_data[<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="cb3-2">r</span></code></pre></div>
</div>
<div id="cell-14" class="cell">
<div class="sourceCode cell-code" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb4-1">{<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'pred_theme_id'</span>: <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">159</span>,</span>
<span id="cb4-2"> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'_text'</span>: array([<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span>a <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span> of strings<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span>],dtype<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;">object</span>),</span>
<span id="cb4-3"> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'_n_tools'</span>: <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>,</span>
<span id="cb4-4"> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'_tools'</span>: [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'TopicSummaryTask'</span>],</span>
<span id="cb4-5"> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'ask'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Based on the documents provided, extract their theme and an action plan based on them'</span>}</span></code></pre></div>
</div>
</section>
<section id="task" class="level4">
<h4 class="anchored" data-anchor-id="task">Task</h4>
<p>For any functions we wanted traces for, we simply decorate those functions with <code>@braintrust.traced</code>. A “trace” is anything you wan’t logged in your experiment tracking system. After we run the acutal eval experiment below I’ll show you where these traces show up in the Braintrust UI.</p>
<p>Here’s a utility function we can use to engage our LLM. Note the decorator.</p>
<div id="cell-17" class="cell">
<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="at" style="color: #657422;
background-color: null;
font-style: inherit;">@braintrust.traced</span></span>
<span id="cb5-2"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> ask_ai(</span>
<span id="cb5-3">    client,</span>
<span id="cb5-4">    is_doc: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">bool</span>,</span>
<span id="cb5-5">    system_msg: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>,</span>
<span id="cb5-6">    human_msg: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>,</span>
<span id="cb5-7">    model: <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;">"gpt-4o"</span>,</span>
<span id="cb5-8">    instructor_kwargs: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">dict</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {},</span>
<span id="cb5-9">) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> DocumentAnalysis <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|</span> RelatedDocumentAnalysis:</span>
<span id="cb5-10">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">try</span>:</span>
<span id="cb5-11">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> client.chat.completions.create(</span>
<span id="cb5-12">            model<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>model,</span>
<span id="cb5-13">            response_model<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>DocumentAnalysis <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> is_doc <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span> RelatedDocumentAnalysis,</span>
<span id="cb5-14">            max_retries<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="cb5-15">            messages<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[</span>
<span id="cb5-16">                {</span>
<span id="cb5-17">                    <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;">"system"</span>,</span>
<span id="cb5-18">                    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"content"</span>: system_msg,</span>
<span id="cb5-19">                },</span>
<span id="cb5-20">                {</span>
<span id="cb5-21">                    <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>
<span id="cb5-22">                    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"content"</span>: human_msg,</span>
<span id="cb5-23">                },</span>
<span id="cb5-24">            ],</span>
<span id="cb5-25">            <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">**</span>instructor_kwargs,</span>
<span id="cb5-26">        )</span>
<span id="cb5-27">    <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>
<span id="cb5-28">        <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(e)</span></code></pre></div>
</div>
<p><code>convert_analysis_call_to_json</code> takes the tool calls captured in a Pydantic object and formats them into a representation that will make it easier for us to build more complex scoring functions later.</p>
<div id="cell-19" class="cell">
<div class="sourceCode cell-code" id="cb6" 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> convert_analysis_call_to_json(</span>
<span id="cb6-2">    analysis_obj: DocumentAnalysis <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|</span> RelatedDocumentAnalysis,</span>
<span id="cb6-3">):</span>
<span id="cb6-4">    j <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [</span>
<span id="cb6-5">        {<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"function_call"</span>: task.__class__.<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">__name__</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"args"</span>: task.model_dump()}</span>
<span id="cb6-6">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> task <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> analysis_obj.tasks</span>
<span id="cb6-7">    ]</span>
<span id="cb6-8">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> j</span></code></pre></div>
</div>
<p><code>generate_tool_calls</code> uses <a href="https://python.useinstructor.com/" target="\_blank">Instructor</a> to make our LLM calls and I’ve included options for either using OpenAI (the default) or Anthropic models here.</p>
<p>The dictionary return represents the “output” included in our Braintrust traces.</p>
<div id="cell-21" class="cell">
<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="at" style="color: #657422;
background-color: null;
font-style: inherit;">@braintrust.traced</span></span>
<span id="cb7-2"><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> generate_tool_calls(</span>
<span id="cb7-3">    item_d: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">dict</span>,</span>
<span id="cb7-4">    ask_attr: <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;">"ask"</span>,</span>
<span id="cb7-5">    text_attr: <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;">"_text"</span>,</span>
<span id="cb7-6">    tools_attr: <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;">"_tools"</span>,</span>
<span id="cb7-7">    model_vender: <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;">"openai"</span>,</span>
<span id="cb7-8">    model_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> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"gpt-4o"</span>,</span>
<span id="cb7-9">):</span>
<span id="cb7-10">    is_doc <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;">isinstance</span>(item_d[text_attr], <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>)</span>
<span id="cb7-11"></span>
<span id="cb7-12">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Prep messages and defined required tools</span></span>
<span id="cb7-13">    required_tools <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> item_d[tools_attr]</span>
<span id="cb7-14">    ask <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> item_d[ask_attr]</span>
<span id="cb7-15">    doc <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> item_d[text_attr] <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> is_doc <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="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>.join(item_d[text_attr])</span>
<span id="cb7-16"></span>
<span id="cb7-17">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> is_doc:</span>
<span id="cb7-18">        system_msg <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> dedent(<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>
<span id="cb7-19"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">            Execute each analysis task.</span></span>
<span id="cb7-20"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">            Always translate any non-English documents into English before executing other tasks."""</span>)</span>
<span id="cb7-21">        human_msg <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>ask<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;">. Document: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>doc<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="cb7-22">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span>:</span>
<span id="cb7-23">        system_msg <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> dedent(<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>
<span id="cb7-24"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">            Execute each analysis task."""</span>)</span>
<span id="cb7-25">        human_msg <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>ask<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;">. Documents:</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>doc<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="cb7-26"></span>
<span id="cb7-27">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Generate the response</span></span>
<span id="cb7-28">    tool_calls <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="cb7-29">    error <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="cb7-30">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">try</span>:</span>
<span id="cb7-31">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> model_vender <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"openai"</span>:</span>
<span id="cb7-32">            client <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> instructor.from_openai(OpenAI())</span>
<span id="cb7-33">            results <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> ask_ai(</span>
<span id="cb7-34">                client,</span>
<span id="cb7-35">                is_doc,</span>
<span id="cb7-36">                system_msg,</span>
<span id="cb7-37">                human_msg,</span>
<span id="cb7-38">                instructor_kwargs<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>{<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"temperature"</span>: <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.0</span>},</span>
<span id="cb7-39">            )</span>
<span id="cb7-40"></span>
<span id="cb7-41">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">elif</span> model_vender <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"anthropic"</span>:</span>
<span id="cb7-42">            client <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> instructor.from_anthropic(Anthropic())</span>
<span id="cb7-43">            results <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> ask_ai(</span>
<span id="cb7-44">                client,</span>
<span id="cb7-45">                is_doc,</span>
<span id="cb7-46">                system_msg,</span>
<span id="cb7-47">                human_msg,</span>
<span id="cb7-48">                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;">"claude-3-5-sonnet-20240620"</span>,</span>
<span id="cb7-49">                instructor_kwargs<span 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_tokens"</span>: <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1024</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"temperature"</span>: <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.0</span>},</span>
<span id="cb7-50">            )</span>
<span id="cb7-51"></span>
<span id="cb7-52">        tool_calls <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> convert_analysis_call_to_json(results)</span>
<span id="cb7-53">    <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>
<span id="cb7-54">        error <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> e</span>
<span id="cb7-55"></span>
<span id="cb7-56">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> {</span>
<span id="cb7-57">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"prompt"</span>: ask,</span>
<span id="cb7-58">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"required_tools"</span>: required_tools,</span>
<span id="cb7-59">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"tool_calls"</span>: tool_calls <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">or</span> [],</span>
<span id="cb7-60">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"error"</span>: error,</span>
<span id="cb7-61">    }</span></code></pre></div>
</div>
<p>One of the many things I love about Braintrust is how easy it is to test the individual parts of your evals locally. Here, we’ll test our “task” function defined above</p>
<div id="cell-23" class="cell">
<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">output <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> generate_tool_calls(</span>
<span id="cb8-2">    item_d<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>r</span>
<span id="cb8-3">)  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># , model_vender="anthropic", model_name="claude-3-5-sonnet-20240620")</span></span>
<span id="cb8-4">output</span></code></pre></div>
</div>
<div id="cell-24" class="cell">
<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>
<span id="cb9-2">    <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;">"Based on the documents provided, extract their theme and an action plan based on them"</span>,</span>
<span id="cb9-3">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"required_tools"</span>: [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"TopicSummaryTask"</span>],</span>
<span id="cb9-4">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"tool_calls"</span>: [</span>
<span id="cb9-5">        {</span>
<span id="cb9-6">            <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"function_call"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"TopicSummaryTask"</span>,</span>
<span id="cb9-7">            <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"args"</span>: {</span>
<span id="cb9-8">                <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"theme_name"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Campus Recreation and Fitness Programs"</span>,</span>
<span id="cb9-9">                <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"action_plan"</span>: [</span>
<span id="cb9-10">                    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Promote the variety of fitness classes available to all levels."</span>,</span>
<span id="cb9-11">                    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Highlight the benefits of free and low-cost classes to students."</span>,</span>
<span id="cb9-12">                    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Encourage participation in 'try it before you buy it' promotional weeks."</span>,</span>
<span id="cb9-13">                    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Emphasize the positive impact of fitness classes on physical and mental well-being."</span>,</span>
<span id="cb9-14">                    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Showcase the ease of registration and the supportive staff."</span>,</span>
<span id="cb9-15">                ],</span>
<span id="cb9-16">            },</span>
<span id="cb9-17">        }</span>
<span id="cb9-18">    ],</span>
<span id="cb9-19">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"error"</span>: <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>,</span>
<span id="cb9-20">}</span></code></pre></div>
</div>
</section>
<section id="scoring" class="level4">
<h4 class="anchored" data-anchor-id="scoring">Scoring</h4>
<p>Since we have no targets, our initial scoring functions will simply inform us if all the expected analysis tasks are being called, if the structured output is valid JSON, and if any errors occurred.</p>
<div id="cell-26" class="cell">
<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"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> overall_no_error(output):</span>
<span id="cb10-2">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> output[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"error"</span>] <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">is</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span></span>
<span id="cb10-3"></span>
<span id="cb10-4"></span>
<span id="cb10-5"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> overall_is_valid_json(output):</span>
<span id="cb10-6">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">try</span>:</span>
<span id="cb10-7">        json.loads(json.dumps(output[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"tool_calls"</span>]))</span>
<span id="cb10-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;">True</span></span>
<span id="cb10-9">    <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;">ValueError</span>:</span>
<span id="cb10-10">        <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;">False</span></span>
<span id="cb10-11"></span>
<span id="cb10-12"></span>
<span id="cb10-13"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> overall_called_all_tools_acc(output):</span>
<span id="cb10-14">    required_tools <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> output[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"required_tools"</span>]</span>
<span id="cb10-15"></span>
<span id="cb10-16">    tool_calls <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> output[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"tool_calls"</span>]</span>
<span id="cb10-17">    actual_tools_used <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (</span>
<span id="cb10-18">        [item[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"function_call"</span>] <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> item <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> tool_calls] <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> tool_calls <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span> []</span>
<span id="cb10-19">    )</span>
<span id="cb10-20"></span>
<span id="cb10-21">    correct_matches <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>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">set</span>(required_tools).intersection(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">set</span>(actual_tools_used)))</span>
<span id="cb10-22">    total_possible_matches <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>(required_tools)</span>
<span id="cb10-23"></span>
<span id="cb10-24">    accuracy <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> correct_matches <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> total_possible_matches</span>
<span id="cb10-25">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> accuracy</span></code></pre></div>
</div>
<p>And just like our “task”, we can test our “scoring” functions locally to ensure all is working as expected before running our full experiment.</p>
<div id="cell-28" class="cell">
<div class="sourceCode cell-code" id="cb11" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb11-1"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(overall_no_error(output))</span>
<span id="cb11-2"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(overall_is_valid_json(output))</span>
<span id="cb11-3"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(overall_called_all_tools_acc(output))</span></code></pre></div>
</div>
<div id="cell-29" class="cell">
<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"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span></span>
<span id="cb12-2"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span></span>
<span id="cb12-3"><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.0</span></span></code></pre></div>
</div>
</section>
<section id="eval" class="level4">
<h4 class="anchored" data-anchor-id="eval">Eval</h4>
<p>Ok, sick!</p>
<p>We have some data, a defined and tested task, and several defined and tested scoring fucntions, its time to run our evals over the entire dataset. All our inputs, outputs, metadata, and metrics will be uploaded to Braintrust for review. Note the inclusion of some “metadata” so we can track what model and what kind of context is used for the examples in this dataset. More on how this can be used in later blog posts.</p>
<div id="cell-31" class="cell">
<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"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">await</span> Eval(</span>
<span id="cb13-2">    EVAL_PROJECT_NAME,</span>
<span id="cb13-3">    experiment_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;">"it_000: Initial Dataset"</span>,</span>
<span id="cb13-4">    data<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[</span>
<span id="cb13-5">        {</span>
<span id="cb13-6">            <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"input"</span>: d,</span>
<span id="cb13-7">            <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"metadata"</span>: {</span>
<span id="cb13-8">                <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"model_vendor"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"openai"</span>,</span>
<span id="cb13-9">                <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"model_name"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"gpt-4o"</span>,</span>
<span id="cb13-10">                <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"is_single_doc"</span>: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">isinstance</span>(d[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"_text"</span>], <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>),</span>
<span id="cb13-11">            },</span>
<span id="cb13-12">        }</span>
<span id="cb13-13">        <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> test_data</span>
<span id="cb13-14">    ],</span>
<span id="cb13-15">    task<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>partial(</span>
<span id="cb13-16">        generate_tool_calls</span>
<span id="cb13-17">    ),  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># , model_vender="anthropic", model_name="claude-3-sonnet-20240229"),</span></span>
<span id="cb13-18">    scores<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[overall_no_error, overall_is_valid_json, overall_called_all_tools_acc],</span>
<span id="cb13-19">)</span></code></pre></div>
</div>
<p>When this finishes, we’ll see a print out of the results and a link directly to the experiment.</p>
<div class="sourceCode" id="cb14" style="background: #f1f3f5;"><pre class="sourceCode markdown code-with-copy"><code class="sourceCode markdown"><span id="cb14-1">=========================SUMMARY=========================</span>
<span id="cb14-2">100.00% 'overall_called_all_tools_acc' score</span>
<span id="cb14-3">100.00% 'overall_is_valid_json' score</span>
<span id="cb14-4">100.00% 'overall_no_error' score</span>
<span id="cb14-5"></span>
<span id="cb14-6">29.03s duration</span>
<span id="cb14-7"></span>
<span id="cb14-8">See results for it_000: Initial Dataset at &lt;link to experiment here&gt;</span></code></pre></div>
<p>Congrats! You just ran your first set of evals. Let’s see what it looks like in BrainTrust.</p>
</section>
</section>
</section>
<section id="review-results" class="level2">
<h2 class="anchored" data-anchor-id="review-results">Review Results</h2>
<p>After your evals finish running, you can click on the summary link and/or just navigate to the “Experiments” tab of your project in BrainTrust to see the results. Out initial iteration above looks like this:</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://ohmeow.com/posts/images/blog-20240727/bt-1.png" class="img-fluid figure-img"></p>
<figcaption>Experiment Overview</figcaption>
</figure>
</div>
<p>You can see for our initial experiment against 15 examples, our model performed very well with perfect scores across our three metrics. Clicking on our experiment name will allows us to look at how each example did.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://ohmeow.com/posts/images/blog-20240727/bt-2.png" class="img-fluid figure-img"></p>
<figcaption>Experiment Detail</figcaption>
</figure>
</div>
<p>From here we can look at specific examples by clicking on any one of them.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://ohmeow.com/posts/images/blog-20240727/bt-3.png" class="img-fluid figure-img"></p>
<figcaption>Example Details</figcaption>
</figure>
</div>
<p>Here we can see both the input provided to the task and it’s output. Notice how each of the methods we decorated with the <code>@braintrust.traced</code> got included here in our trace. This allows us to look at each individually if we want too.</p>
<p>What I’m going to do is select all 15 examples, and add them to a dataset I named “golden dataset”. You can do that pretty easily as pictured below.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://ohmeow.com/posts/images/blog-20240727/bt-4.png" class="img-fluid figure-img"></p>
<figcaption>Adding Experiment Data to a Dataset</figcaption>
</figure>
</div>
<p>Navigating to the “Datasets” tab, I can click on my “golden dataset” and see the rows I just added. I decided to review each one of these examples and correct their outputs by updating the “Expected” section for each.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://ohmeow.com/posts/images/blog-20240727/bt-5.png" class="img-fluid figure-img"></p>
<figcaption>A Dataset</figcaption>
</figure>
</div>
<p>In the configuration sectoin of Braintrust I created a “reviewed-wg” tag I can apply to any rows in a dataset that I have personally reviewed/corrected. I can use this to know what examples need review and also for filtering out non-reviewed rows in this dataset when I use it in subsequent evals.</p>
</section>
<section id="takeaways" class="level2">
<h2 class="anchored" data-anchor-id="takeaways">Takeaways</h2>
<p>We’ve only just begun, but hopefully you can see that Braintrust provides a comprehensive platform for everything we need to build out our evaluation pipeline! It provides …</p>
<ol type="1">
<li><p>A mechanism to evaluate performance <strong>via scoring functions</strong>.</p></li>
<li><p>A mechanism to look at our data and see where things are working well or not so well overall and with specific examples <strong>via the Braintrust UI where we can look at overall runs and example-specific metrics</strong>.</p></li>
<li><p>The ability to make modifications to our system and measure how well they improved things or not <strong>via subsequent experiments and the ability to look at improvements and regressions on a case-by-case basis</strong>.</p></li>
<li><p>The ability to curate datasets that can be used for better evals and fine tuning <strong>via the ability to add the results of experiments to datasets that can be reviewed, corrected, and used for more complex evals and fine tunes</strong></p></li>
</ol>
<p>I’m a big fan of the platform and encourage y’all to watch Ankur’s talk from the workshop included below to learn more (I’ve already watched it 3x).</p>
<div class="quarto-video ratio ratio-16x9"><iframe data-external="1" src="https://www.youtube.com/embed/UGmenkjGXqM" title="" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe></div>
</section>
<section id="next-steps" class="level2">
<h2 class="anchored" data-anchor-id="next-steps">Next Steps</h2>
<p>Initially, I was planning on showing y’all a couple more iterations in the eval pipeline before I realized this post is already long as hell. Braintrust is an awesome tool and I want to do it justice, and so my next blog post will cover two more experiments I ran before moving on to generate a dataset for fine tuning. In particular, I’ll cover the following:</p>
<ul>
<li>How to merge the “golden dataset” with more sampled data to build up our dataset along with better and more task specific scoring functions.</li>
<li>How to really “look at the data” and review both improvements and regressions on a case-by-case basis.</li>
<li>How to improve our prompts and tool definitions based on what we see and then see how things measure up by comparing results to previous runs.</li>
</ul>
<p>Anyways, I know this was a lot but I hope it encourages you to adopt a “evals first” type of thinking and also to give Braintrust a go. If you made it this far, thanks for reading!</p>


</section>

 ]]></description>
  <category>NLP</category>
  <category>LLMS</category>
  <category>OpenAI</category>
  <category>BrainTrust</category>
  <category>Evals</category>
  <category>Datasets</category>
  <category>learning</category>
  <category>projects</category>
  <guid>https://ohmeow.com/posts/2024-07-25-llm-workshop-evals-dataset-curation.html</guid>
  <pubDate>Thu, 25 Jul 2024 07:00:00 GMT</pubDate>
  <media:content url="https://ohmeow.com/posts/images/blog-20240727/blog-20240727-header.png" medium="image" type="image/png" height="144" width="144"/>
</item>
<item>
  <title>LLM Workshop #3 - How Far Can We Get With Prompting Alone?”</title>
  <dc:creator>Wayde Gilliam</dc:creator>
  <link>https://ohmeow.com/posts/2024-07-18-llm-workshop-prompt-only.html</link>
  <description><![CDATA[ 




<section id="in-the-beginning" class="level2">
<h2 class="anchored" data-anchor-id="in-the-beginning">In The Beginning …</h2>
<blockquote class="blockquote">
<p>“you should prototype with a powerful model to see what is possible” <img src="https://ohmeow.com/posts/images/blog-20240603/hamel-icon.png" alt="Hamel" style="border-radius:30px;width:auto;height:25px;"></p>
</blockquote>
<p>This is our chance to do a “vibe check” and create confidence that our objectives are doable. It’s also a good time to get a sense of which knobs we can turn to potentially improve results, understand likely primary failure modes, and see how far we can push the bigger models without fine tuning. As the general advice from the workshop is to avoid fine tuning until you can prove you need it, this step will also provide the base on top of which we begin building our evaluation pipeline for that very purpose.</p>
<div class="callout callout-style-default callout-tip 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">
Tip: Miminize friction
</div>
</div>
<div class="callout-body-container callout-body">
<p>The best way to learn if something will work is to build it. A common theme from the workshop revolves around “minimizing friction”, and in a nutshell you can read that as being encouraged to “get going and build!” The best way to do this in the generative space is to try out one or more of the high quality models available to us via an API.</p>
</div>
</div>
<p><strong>What do we want our model to do again?</strong></p>
<p>Before we begin, let’s distill <a href="https://ohmeow.com/posts/2024-07-14-llm-workshop-objectives-data-filtration.html#objective-definition" target="\_blank">our objectives</a> into a few clear bullet points:</p>
<ol type="1">
<li><p>It should work on a single document or a collection of related documents in the domain of higher education surveys.<br>
(See <a href="https://ohmeow.com/posts/2024-07-14-llm-workshop-objectives-data-filtration.html#data-refinement" target="\_blank">the “Data Refinement” section</a> in the previous post in this series where we’ve curated a set of documents representative of what we expect to see generally)</p></li>
<li><p>We should be able to provide it NLP task-specific tools to use to perform analysis on those documents</p></li>
<li><p>Core tools for translation, summarization, sentiment, NER, and thematic analysis will always be provided and designed to work against English texts</p></li>
<li><p>A translation tool is required and need to be executed first if any documents are not in English</p></li>
<li><p>The results are formatted as structured output.</p></li>
</ol>
<p>With that, let’s define some tools. In partuclar, we will define the “core” tools that should should always be made available to the LLM.</p>
</section>
<section id="tools" class="level2">
<h2 class="anchored" data-anchor-id="tools">Tools</h2>
<p>If you didn’t know this already, apparently “Pydantic is all you need”. There’s even this video by <a href="https://x.com/jxnlco" target="\_blank">Jason Liu</a> to prove it.</p>
<div class="quarto-video ratio ratio-16x9"><iframe data-external="1" src="https://www.youtube.com/embed/yj-wSRJwrrc" title="" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe></div>
<div class="callout callout-style-default callout-tip 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">
Tip: Use Pydantic to define your structured outputs
</div>
</div>
<div class="callout-body-container callout-body">
<p>Pydantic is is my preferred way to define tools for structured output for <a href="https://python.useinstructor.com/blog/2024/06/15/zero-cost-abstractions/?h=pydantic#pydantic-more-powerful-than-plain-dictionaries" target="\_blank">a number of reasons</a>. In particular, I like how …</p>
<ul>
<li><p>It’s widely supported across most IDEs and libraries (e.g, FastAPI, LangChain, Instructor, OpenAI, etc.., etc…).</p></li>
<li><p>It makes your intentions and expectations crystal clear, especially for any developer with OO experience (which is everyone).</p></li>
<li><p>It has error handling baked in.</p></li>
<li><p>It provides all kinds of hooks you can use in the pre/post-processing of your class attributes.</p></li>
<li><p>It enables you to build complex structured outputs composed on nested objects quite intuitively. Even a non-developer can look at your object hierarchy and understand what it is supposed to produce.</p></li>
</ul>
</div>
</div>
<p>Let’s use it to build out our core tools that we’ll want to always make available for our users.</p>
<section id="core-tools" class="level3">
<h3 class="anchored" data-anchor-id="core-tools">Core Tools</h3>
<div id="cell-4" class="cell">
<details class="code-fold">
<summary>Pydantic classes for the core tools</summary>
<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;"># Translation</span></span>
<span id="cb1-2"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> TranslationTask(BaseModel):</span>
<span id="cb1-3">    english_translation: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span></span>
<span id="cb1-4">    source_language: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span></span>
<span id="cb1-5"></span>
<span id="cb1-6"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Document summarization</span></span>
<span id="cb1-7"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> DocumentSummaryTask(BaseModel):</span>
<span id="cb1-8">    summary: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span></span>
<span id="cb1-9">    themes: <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;">str</span>]</span>
<span id="cb1-10"></span>
<span id="cb1-11"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># NER</span></span>
<span id="cb1-12"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> NamedEntityType(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>, Enum):</span>
<span id="cb1-13">    PERSON <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"PERSON"</span></span>
<span id="cb1-14">    NORP <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"NORP"</span></span>
<span id="cb1-15">    FAC <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"FAC"</span></span>
<span id="cb1-16">    ORG <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ORG"</span></span>
<span id="cb1-17">    GPE <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"GPE"</span></span>
<span id="cb1-18">    LOC <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"LOC"</span></span>
<span id="cb1-19">    PRODUCT <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"PRODUCT"</span></span>
<span id="cb1-20">    EVENT <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"EVENT"</span></span>
<span id="cb1-21">    WORK_OF_ART <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"WORK_OF_ART"</span></span>
<span id="cb1-22">    LAW <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"LAW"</span></span>
<span id="cb1-23">    LANGUAGE <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"LANGUAGE"</span></span>
<span id="cb1-24">    DATE <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"DATE"</span></span>
<span id="cb1-25">    TIME <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"TIME"</span></span>
<span id="cb1-26">    PERCENT <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"PERCENT"</span></span>
<span id="cb1-27">    MONEY <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"MONEY"</span></span>
<span id="cb1-28">    QUANTITY <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"QUANTITY"</span></span>
<span id="cb1-29">    ORDINAL <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ORDINAL"</span></span>
<span id="cb1-30">    CARDINAL <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"CARDINAL"</span></span>
<span id="cb1-31">    OTHER <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"OTHER"</span></span>
<span id="cb1-32"></span>
<span id="cb1-33"></span>
<span id="cb1-34"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> NamedEntity(BaseModel):</span>
<span id="cb1-35">    entity_type: NamedEntityType</span>
<span id="cb1-36">    entity_mention: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span> </span>
<span id="cb1-37"></span>
<span id="cb1-38"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> DocumentNERTask(BaseModel):</span>
<span id="cb1-39">    named_entities: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>[NamedEntity]</span>
<span id="cb1-40"></span>
<span id="cb1-41"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Sentiment</span></span>
<span id="cb1-42"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> DocumentSentimentTask(BaseModel):</span>
<span id="cb1-43">    positivity: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span></span>
<span id="cb1-44">    positive_statements: <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;">str</span>]</span>
<span id="cb1-45">    negative_statements: <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;">str</span>]</span>
<span id="cb1-46">    has_suggestions: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">bool</span> </span>
<span id="cb1-47">    suggestions: <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;">str</span>]</span>
<span id="cb1-48">    feels_threatened: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">bool</span></span>
<span id="cb1-49">    feels_threatened_examples: <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;">str</span>]</span>
<span id="cb1-50">    profanity: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">bool</span></span>
<span id="cb1-51">    is_nonsense: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">bool</span></span>
<span id="cb1-52"></span>
<span id="cb1-53"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Topic summarization</span></span>
<span id="cb1-54"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> TopicSummaryTask(BaseModel):</span>
<span id="cb1-55">    theme_name: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span></span>
<span id="cb1-56">    action_plan: <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;">str</span>]</span>
<span id="cb1-57">```</span></code></pre></div>
</details>
</div>
</section>
<section id="tools-for-tool-calling" class="level3">
<h3 class="anchored" data-anchor-id="tools-for-tool-calling">“Tools” For “Tool Calling”</h3>
<p>We’re going to use <a href="https://python.useinstructor.com/" target="\_blank">Instructor</a> here because this is what Hamel suggests …</p>
<blockquote class="blockquote">
<p>For open models you should use outlines. for closed models APIs you should use instructor. <img src="https://ohmeow.com/posts/images/blog-20240603/hamel-icon.png" alt="Hamel" style="border-radius:30px;width:auto;height:25px;"></p>
</blockquote>
<div class="callout callout-style-default callout-warning 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">
Warning
</div>
</div>
<div class="callout-body-container callout-body">
<p>TBH, I’m a noob relative to Instructor use. If anything I say below is wrong and/or can be improved … please, please let me know!</p>
</div>
</div>
<p>Moving along, as I understand the library, it is designed to work against a <em>single</em> Pydantic class that you pass into it and from which an instance of that class will be returned at the conclusion of your LLM call. BUT, we’ve defined multiple classes as tools and we only want the LLM to call the tools it deems necessary to fulfill the user’s request. What are we going to do?</p>
<p>My answer, perhaps not suprisingly, is to use another Pydantic class. It looks like this:</p>
<div class="sourceCode" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb2-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> DocumentAnalysis(BaseModel):</span>
<span id="cb2-2">    tasks: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>[TranslationTask <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|</span> DocumentSummaryTask <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|</span> DocumentNERTask <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|</span> DocumentSentimentTask <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|</span> TopicSummaryTask]</span></code></pre></div>
<p>This makes it easy to support a flexible tool calling system where a user can create their own <code>Analysis</code> class with whatever “tasks” they want the LLM to operate with and use with Instructor. For example, I’ll use the class below when working with collections of related documents since the the available tools should be limited for this use case:</p>
<div class="sourceCode" id="cb3" 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;">class</span> RelatedDocumentAnalysis(BaseModel):</span>
<span id="cb3-2">    tasks: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>[TopicSummaryTask <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|</span> DocumentSentimentTask <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|</span> TopicSummaryTask]</span></code></pre></div>
<p>With our Pydantic army above, we can now move to experimenting with the big dogs to see what works and what doesn’t.</p>
<div class="callout callout-style-default 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">
Tip: Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>Because of the propietary nature of the survey comments, I can’t show you the actual results. What I can show you is the code and my observations. With that in hand you should have everything you need to get going with your own use cases. If anything isn’t clear, drop a comment below or hit me up on X.</p>
</div>
</div>
</section>
</section>
<section id="single-document-analysis" class="level2">
<h2 class="anchored" data-anchor-id="single-document-analysis">Single Document Analysis</h2>
<section id="data" class="level3">
<h3 class="anchored" data-anchor-id="data">Data</h3>
<p>Let’s sample 5 rows from our sampled chunked dataset created in the previous post. We’ll use the full survey comments for exploration here and ensure that 2 of those samples are in Spanish.</p>
<div class="callout callout-style-default callout-tip 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">
Tip: Test with representative examples
</div>
</div>
<div class="callout-body-container callout-body">
<p>Think about what kind of examples are like to be seen at inference time and test a few out here. Our goal is to get a sense of how well our model will generalize over asks its likely to see in the future.</p>
</div>
</div>
<div class="sourceCode" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb4-1">df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> pd.read_parquet(<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>DATA_DIR<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;">/clean/</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>DATA_FILENAME<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;">_sample_14k_chunked.parquet"</span>)</span>
<span id="cb4-2"></span>
<span id="cb4-3">test_df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> df[df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"AnswerLang"</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;">"Spanish"</span>].sample(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;">2</span>)</span>
<span id="cb4-4">test_df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"AnswerText"</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> test_df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"AnswerText_NonEnglish"</span>]</span>
<span id="cb4-5">test_df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> pd.concat([test_df, df[df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"AnswerLang"</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;">"English"</span>].sample(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;">3</span>)])</span></code></pre></div>
</section>
<section id="llm-utility" class="level3">
<h3 class="anchored" data-anchor-id="llm-utility">LLM Utility</h3>
<p>We’ll define the following function to make it easy for us to test different APIs with <a href="https://python.useinstructor.com/" target="\_blank">Instructor</a>. I designed this function for use with OpenAI, Antrhopic, and Fireworks specifically though it will likely work with any supported vendor with little or no modification.</p>
<div class="sourceCode" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb5-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> ask_ai(</span>
<span id="cb5-2">    client,</span>
<span id="cb5-3">    content: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>,</span>
<span id="cb5-4">    query: <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="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="cb5-5">    model: <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;">"gpt-4o"</span>,</span>
<span id="cb5-6">    instructor_kwargs: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">dict</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {},</span>
<span id="cb5-7">) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> DocumentAnalysis:</span>
<span id="cb5-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> query:</span>
<span id="cb5-9">        query <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Tasks: translation (if the document is not in English), summarization, ner, sentiment analysis."</span></span>
<span id="cb5-10">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">try</span>:</span>
<span id="cb5-11">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> client.chat.completions.create(</span>
<span id="cb5-12">            model<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>model,</span>
<span id="cb5-13">            response_model<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>DocumentAnalysis,</span>
<span id="cb5-14">            max_retries<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="cb5-15">            messages<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[</span>
<span id="cb5-16">                {</span>
<span id="cb5-17">                    <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;">"system"</span>,</span>
<span id="cb5-18">                    <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;">"""</span></span>
<span id="cb5-19"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">Execute each analysis task.</span></span>
<span id="cb5-20"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">Always translate any non-English documents into English before executing other tasks."""</span>,</span>
<span id="cb5-21">                },</span>
<span id="cb5-22">                {</span>
<span id="cb5-23">                    <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>
<span id="cb5-24">                    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"content"</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>query<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;">. Document: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>content<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="cb5-25">                },</span>
<span id="cb5-26">            ],</span>
<span id="cb5-27">            <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">**</span>instructor_kwargs,</span>
<span id="cb5-28">        )</span>
<span id="cb5-29">    <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>
<span id="cb5-30">        <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(e)</span></code></pre></div>
</section>
<section id="experiments" class="level3">
<h3 class="anchored" data-anchor-id="experiments">Experiments</h3>
<section id="openai" class="level4">
<h4 class="anchored" data-anchor-id="openai">OpenAI</h4>
<div class="sourceCode" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb6-1">client <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> instructor.from_openai(OpenAI())</span>
<span id="cb6-2"></span>
<span id="cb6-3"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> r_idx, r <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> test_df.iterrows():</span>
<span id="cb6-4">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"=========="</span>)</span>
<span id="cb6-5">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">":: Document ::"</span>)</span>
<span id="cb6-6">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(r[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"AnswerText"</span>])</span>
<span id="cb6-7">    results <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> ask_ai(client, r[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"AnswerText"</span>])</span>
<span id="cb6-8"></span>
<span id="cb6-9">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">":: Results ::"</span>)</span>
<span id="cb6-10">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(results.model_dump_json(indent<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="cb6-11">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"=========="</span>)</span></code></pre></div>
<section id="observations" class="level5">
<h5 class="anchored" data-anchor-id="observations">Observations</h5>
<ol type="1">
<li><p>Performed the translation step where needed correctly and used the English translation in the rest of the tools.</p></li>
<li><p>Generally did an outstanding job of calling the tools and providing results that were as good, and sometimes better, than what I would have done.</p></li>
<li><p>Occasionally ran into validation errors because it couldn’t set various properties correctly. This usually happend with the summarization or sentiment tools where I’d get an error like this:<br>
<code>tasks.0.DocumentSummaryTask.summary Input should be a valid string [type=string_type, input_value={'summary': 'The author c... 'inadequate planning']}, input_type=dict]</code></p></li>
</ol>
</section>
</section>
<section id="anthropic" class="level4">
<h4 class="anchored" data-anchor-id="anthropic">Anthropic</h4>
<div class="sourceCode" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb7-1">client <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> instructor.from_anthropic(Anthropic())</span>
<span id="cb7-2"></span>
<span id="cb7-3"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> r_idx, r <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> test_df.iterrows():</span>
<span id="cb7-4">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"=========="</span>)</span>
<span id="cb7-5">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">":: Document ::"</span>)</span>
<span id="cb7-6">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(r[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"AnswerText"</span>])</span>
<span id="cb7-7">    results <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> ask_ai(</span>
<span id="cb7-8">        client, r[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"AnswerText"</span>], 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;">"claude-3-5-sonnet-20240620"</span>, instructor_kwargs<span 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_tokens"</span>: <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1024</span>}</span>
<span id="cb7-9">    )</span>
<span id="cb7-10"></span>
<span id="cb7-11">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">":: Results ::"</span>)</span>
<span id="cb7-12">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(results.model_dump_json(indent<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="cb7-13">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"=========="</span>)</span></code></pre></div>
<section id="observations-1" class="level5">
<h5 class="anchored" data-anchor-id="observations-1">Observations</h5>
<ol type="1">
<li><p>Performed the translation step where needed correctly and used the English translation in the rest of the tools.</p></li>
<li><p>Generally did an outstanding job of calling the tools and providing results that were as good, and sometimes better, than what I would have done.</p></li>
<li><p>Occassionally, it would struggle with the NER task for some reason. I talk about this more in my <a href="https://python.useinstructor.com/" target="\_blank">Structuring Enums for Flawless LLM results with Instructor</a> post. I can’t say if this is an Instructor issue and/or something particular to this model itself.</p></li>
</ol>
</section>
</section>
<section id="fireworks" class="level4">
<h4 class="anchored" data-anchor-id="fireworks">Fireworks</h4>
<div class="sourceCode" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb8-1">client <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> instructor.patch(</span>
<span id="cb8-2">    OpenAI(</span>
<span id="cb8-3">        base_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://api.fireworks.ai/inference/v1"</span>,</span>
<span id="cb8-4">        api_key<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>os.environ[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"FIREWORKS_API_KEY"</span>],</span>
<span id="cb8-5">    ),</span>
<span id="cb8-6">)</span>
<span id="cb8-7"></span>
<span id="cb8-8"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> r_idx, r <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> test_df.iterrows():</span>
<span id="cb8-9">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"=========="</span>)</span>
<span id="cb8-10">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">":: Document ::"</span>)</span>
<span id="cb8-11">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(r[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"AnswerText"</span>])</span>
<span id="cb8-12">    results <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> ask_ai(client, r[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"AnswerText"</span>], 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;">"accounts/fireworks/models/firefunction-v2"</span>)</span>
<span id="cb8-13"></span>
<span id="cb8-14">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">":: Results ::"</span>)</span>
<span id="cb8-15">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(results.model_dump_json(indent<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="cb8-16">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"=========="</span>)</span></code></pre></div>
<section id="observations-2" class="level5">
<h5 class="anchored" data-anchor-id="observations-2">Observations</h5>
<ol type="1">
<li><p>Did not reliably perform the translation step where required</p></li>
<li><p>Did not reliably call all the tools</p></li>
<li><p>Where called, the results of each tool call were not as accurate as either the OpenAI or Anthropic models</p></li>
<li><p>Encountered validation errors more frequently.</p></li>
<li><p>It is FAST! Like really fast to run.</p></li>
</ol>
<p>The speed difference is pretty noticeable, but I wonder if it comes at the cost of being able to use Fireworks for any complex structured output?</p>
</section>
</section>
</section>
</section>
<section id="related-document-analysis" class="level2">
<h2 class="anchored" data-anchor-id="related-document-analysis">Related Document Analysis</h2>
<section id="data-1" class="level3">
<h3 class="anchored" data-anchor-id="data-1">Data</h3>
<p>Let’s sample 5 rows (topics) from our topics dataset created in the previous post.</p>
<div class="sourceCode" id="cb9" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb9-1">df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> pd.read_parquet(<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>DATA_DIR<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;">/clean/</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>DATA_FILENAME<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;">_sample_14k_topics.parquet"</span>)</span>
<span id="cb9-2">test_df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> df.sample(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;">5</span>)</span></code></pre></div>
</section>
<section id="llm-utility-1" class="level3">
<h3 class="anchored" data-anchor-id="llm-utility-1">LLM Utility</h3>
<p>This is essentially the same utility function used above. The only bits we’ve modified are the prompt template and the <code>response_model</code>.</p>
<div class="sourceCode" id="cb10" 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> ask_ai(</span>
<span id="cb10-2">    client,</span>
<span id="cb10-3">    content: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>,</span>
<span id="cb10-4">    query: <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="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="cb10-5">    model: <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;">"gpt-4o"</span>,</span>
<span id="cb10-6">    instructor_kwargs: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">dict</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {},</span>
<span id="cb10-7">) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> RelatedDocumentAnalysis:</span>
<span id="cb10-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> query:</span>
<span id="cb10-9">        query <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Tasks: thematic analysis/action planning and sentiment analysis."</span></span>
<span id="cb10-10">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">try</span>:</span>
<span id="cb10-11">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> client.chat.completions.create(</span>
<span id="cb10-12">            model<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>model,</span>
<span id="cb10-13">            response_model<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>RelatedDocumentAnalysis,</span>
<span id="cb10-14">            max_retries<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="cb10-15">            messages<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[</span>
<span id="cb10-16">                {</span>
<span id="cb10-17">                    <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;">"system"</span>,</span>
<span id="cb10-18">                    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"content"</span>: dedent(<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>
<span id="cb10-19"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">                        Execute each analysis task."""</span>),</span>
<span id="cb10-20">                },</span>
<span id="cb10-21">                {</span>
<span id="cb10-22">                    <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>
<span id="cb10-23">                    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"content"</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>query<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;">. Documents:</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>content<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="cb10-24">                },</span>
<span id="cb10-25">            ],</span>
<span id="cb10-26">            <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">**</span>instructor_kwargs,</span>
<span id="cb10-27">        )</span>
<span id="cb10-28">    <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>
<span id="cb10-29">        <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(e)</span></code></pre></div>
</section>
<section id="experiments-1" class="level3">
<h3 class="anchored" data-anchor-id="experiments-1">Experiments</h3>
<section id="openai-1" class="level4">
<h4 class="anchored" data-anchor-id="openai-1">OpenAI</h4>
<div class="sourceCode" id="cb11" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb11-1">client <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> instructor.from_openai(OpenAI())</span>
<span id="cb11-2"></span>
<span id="cb11-3"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> r_idx, r <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> test_df.iterrows():</span>
<span id="cb11-4">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"=========="</span>)</span>
<span id="cb11-5">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">":: Document ::"</span>)</span>
<span id="cb11-6">    docs <span 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>.join(r[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"_chunk"</span>])</span>
<span id="cb11-7">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(docs)</span>
<span id="cb11-8"></span>
<span id="cb11-9">    results <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> ask_ai(client, docs)</span>
<span id="cb11-10"></span>
<span id="cb11-11">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">":: Results ::"</span>)</span>
<span id="cb11-12">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(results.model_dump_json(indent<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="cb11-13">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"=========="</span>)</span></code></pre></div>
<section id="observations-3" class="level5">
<h5 class="anchored" data-anchor-id="observations-3">Observations</h5>
<ol type="1">
<li><p>Generally did an outstanding job of calling the tools and providing results that were as good, and sometimes better, than what I would have done.</p></li>
<li><p>I didn’t encounter any errors!</p></li>
</ol>
<p>Perhaps, GPT-4o simply struggles when too many tools are made available to it?</p>
</section>
</section>
<section id="anthropic-1" class="level4">
<h4 class="anchored" data-anchor-id="anthropic-1">Anthropic</h4>
<div class="sourceCode" id="cb12" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb12-1">client <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> instructor.from_anthropic(Anthropic())</span>
<span id="cb12-2"></span>
<span id="cb12-3"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> r_idx, r <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> test_df.iterrows():</span>
<span id="cb12-4">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"=========="</span>)</span>
<span id="cb12-5">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">":: Document ::"</span>)</span>
<span id="cb12-6">    docs <span 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>.join(r[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"_chunk"</span>])</span>
<span id="cb12-7">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(docs)</span>
<span id="cb12-8"></span>
<span id="cb12-9">    results <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> ask_ai(</span>
<span id="cb12-10">        client, docs, 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;">"claude-3-5-sonnet-20240620"</span>, instructor_kwargs<span 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_tokens"</span>: <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1024</span>}</span>
<span id="cb12-11">    )</span>
<span id="cb12-12"></span>
<span id="cb12-13">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">":: Results ::"</span>)</span>
<span id="cb12-14">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(results.model_dump_json(indent<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="cb12-15">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"=========="</span>)</span></code></pre></div>
<section id="observations-4" class="level5">
<h5 class="anchored" data-anchor-id="observations-4">Observations</h5>
<ol type="1">
<li><p>Generally did an outstanding job of calling the tools and providing results that were as good, and sometimes better, than what I would have done.</p></li>
<li><p>I didn’t encounter any errors!</p></li>
</ol>
</section>
</section>
<section id="fireworks-1" class="level4">
<h4 class="anchored" data-anchor-id="fireworks-1">Fireworks</h4>
<div class="sourceCode" id="cb13" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb13-1">client <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> instructor.patch(</span>
<span id="cb13-2">    OpenAI(</span>
<span id="cb13-3">        base_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://api.fireworks.ai/inference/v1"</span>,</span>
<span id="cb13-4">        api_key<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>os.environ[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"FIREWORKS_API_KEY"</span>],</span>
<span id="cb13-5">    ),</span>
<span id="cb13-6">)</span>
<span id="cb13-7"></span>
<span id="cb13-8"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> r_idx, r <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> test_df.iterrows():</span>
<span id="cb13-9">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"=========="</span>)</span>
<span id="cb13-10">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">":: Document ::"</span>)</span>
<span id="cb13-11">    docs <span 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>.join(r[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"_chunk"</span>])</span>
<span id="cb13-12">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(docs)</span>
<span id="cb13-13"></span>
<span id="cb13-14">    results <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> ask_ai(client, docs, 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;">"accounts/fireworks/models/firefunction-v2"</span>)</span>
<span id="cb13-15"></span>
<span id="cb13-16">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">":: Results ::"</span>)</span>
<span id="cb13-17">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(results.model_dump_json(indent<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="cb13-18">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"=========="</span>)</span></code></pre></div>
<section id="observations-5" class="level5">
<h5 class="anchored" data-anchor-id="observations-5">Observations</h5>
<ol type="1">
<li><p>Generally did an outstanding job of calling the tools and providing results that were as good, and sometimes better, than what I would have done.</p></li>
<li><p>I didn’t encounter any errors!</p></li>
</ol>
<p>Perhaps, GPT-4o simply struggles when too many tools are made available to it?</p>
</section>
</section>
</section>
</section>
<section id="exprimenting-with-replicate" class="level2">
<h2 class="anchored" data-anchor-id="exprimenting-with-replicate">Exprimenting with Replicate</h2>
<p><a href="https://replicate.com/" target="\_blank">Replicate</a> is quickly becoming a favorite tool in my LLM arsenal. Hamel has <a href="https://replicate.com/hamelsmu/llama-3-70b-instruct-awq-with-tools" target="\_blank">a really nice example/tutorial for getting tool calling to work with the Llama3-70B Instruct model</a> out of the box (not fine tuned). I stole some of his ideas and put together a simple workflow that allows me to incorporate testing with Llama3 variants here.</p>
<p>Below, I share running the single document analysis experiment against both the 70B and 8B variants.</p>
<div class="sourceCode" id="cb14" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb14-1">doc_analysis_schema <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> DocumentAnalysis.model_json_schema()</span>
<span id="cb14-2"></span>
<span id="cb14-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># doc_analysis_schema</span></span></code></pre></div>
<div class="sourceCode" id="cb15" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb15-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> format_tools():</span>
<span id="cb15-2">    doc_analysis_schema <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> DocumentAnalysis.model_json_schema()</span>
<span id="cb15-3"></span>
<span id="cb15-4">    result <span 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="cb15-5">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> k, v <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> doc_analysis_schema[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"$defs"</span>].items():</span>
<span id="cb15-6">        result <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"&lt;function name='</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>k<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;">'&gt;</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="cb15-7">        result <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+=</span> json.dumps(v, indent<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="cb15-8">        result <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="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">&lt;/function name='</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>k<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;">'&gt;</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="cb15-9">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> result.strip()</span></code></pre></div>
<div class="sourceCode" id="cb16" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb16-1">PROMPT_TEMPLATE <span 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;">\</span></span>
<span id="cb16-2"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">&lt;|begin_of_text|&gt;&lt;|start_header_id|&gt;system&lt;|end_header_id|&gt;</span></span>
<span id="cb16-3"></span>
<span id="cb16-4"><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{system_message}</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">&lt;|eot_id|&gt;&lt;|start_header_id|&gt;user&lt;|end_header_id|&gt;</span></span>
<span id="cb16-5"></span>
<span id="cb16-6"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">&lt;query&gt;</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{prompt}</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">&lt;/query&gt;&lt;|eot_id|&gt;&lt;|start_header_id|&gt;assistant&lt;|end_header_id|&gt;</span></span>
<span id="cb16-7"></span>
<span id="cb16-8"><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{prefill}</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb16-9"></span>
<span id="cb16-10"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># print(PROMPT_TEMPLATE)</span></span></code></pre></div>
<div class="sourceCode" id="cb17" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb17-1">SYSTEM_PROMPT <span 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;">\</span></span>
<span id="cb17-2"><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{system_persona}</span></span>
<span id="cb17-3"></span>
<span id="cb17-4"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">You are given a set of tasks to perform and a document inside &lt;query&gt; tags and a set of possible functions inside &lt;function-definitions&gt; tags.</span></span>
<span id="cb17-5"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">Calling these functions are optional. Carefully consider the question and determine if one or more functions can be used to answer the question. Place your thoughts and reasoning behind your decision in &lt;function-thoughts&gt; tags.</span></span>
<span id="cb17-6"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">Below is a list of function definitions:</span></span>
<span id="cb17-7"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">&lt;function-definitions&gt;</span></span>
<span id="cb17-8"><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{tools}</span></span>
<span id="cb17-9"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">&lt;/function-definitions&gt;</span></span>
<span id="cb17-10"></span>
<span id="cb17-11"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">For each function you want to call, execute the function and use the answer to provide values to each function parameter in a way that conforms to that function's schema. Include the function name and parameter values inside the &lt;function-calls&gt; tag.</span></span>
<span id="cb17-12"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">Function calls MUST be in this format: &lt;function-thoughts&gt;Calling func1 would be helpful because of ...&lt;/function-thoughts&gt;&lt;function-calls&gt;[func1_name(params_name=params_value, params_name2=params_value2...), func2_name(params)]&lt;/function-calls&gt;, WITHOUT any answer.</span></span>
<span id="cb17-13"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">If the query is not in English, always translate it into English first and then proceed to call any other functions using the English translation.</span></span>
<span id="cb17-14"></span>
<span id="cb17-15"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">If you do not wish to call any functions, say so in the &lt;function-thoughts&gt; tags followed by &lt;function-calls&gt;None&lt;/function-calls&gt;"""</span></span>
<span id="cb17-16"></span>
<span id="cb17-17">system_persona <span 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;">\</span></span>
<span id="cb17-18"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">You are an expert NLP data scientist, skilled in machine translation, text summarization, NER, thematic analysis, strategic planning, sentiment analysis, and classification tasks."""</span></span>
<span id="cb17-19"></span>
<span id="cb17-20"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># print(SYSTEM_PROMPT)</span></span></code></pre></div>
<div class="sourceCode" id="cb18" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb18-1">tools <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> format_tools()  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># .replace("\n", "")</span></span>
<span id="cb18-2">system_message <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> SYSTEM_PROMPT.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">format</span>(system_persona<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>system_persona, tools<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>tools)</span>
<span id="cb18-3"></span>
<span id="cb18-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># print(system_message)</span></span></code></pre></div>
<div class="sourceCode" id="cb19" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb19-1"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> r_idx, r <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> test_df.iterrows():</span>
<span id="cb19-2">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"=========="</span>)</span>
<span id="cb19-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"Document:</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>r[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'AnswerText'</span>]<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="cb19-4"></span>
<span id="cb19-5">    prompt <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"Translate the document below into English if necessary. After that, perform the following tasks on the document below: summarize, perform named entity recognition, and sentiment analysis. Document:</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>r[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'AnswerText'</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="cb19-6"></span>
<span id="cb19-7">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">input</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {</span>
<span id="cb19-8">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"max_tokenx"</span>: <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1024</span>,</span>
<span id="cb19-9">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"temperature"</span>: <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>,</span>
<span id="cb19-10">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"top_p"</span>: <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.9</span>,</span>
<span id="cb19-11">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"top_k"</span>: <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">50</span>,</span>
<span id="cb19-12">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"presence_penalty"</span>: <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>,</span>
<span id="cb19-13">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"frequency_penalty"</span>: <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>,</span>
<span id="cb19-14">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"system_prompt"</span>: system_message,</span>
<span id="cb19-15">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"prompt"</span>: <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"&lt;query&gt;</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>prompt<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;">&lt;/query&gt;"</span>,</span>
<span id="cb19-16">    }</span>
<span id="cb19-17">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"--- Example ---"</span>)</span>
<span id="cb19-18">    <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"prompt: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>prompt<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="cb19-19">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">""</span>)</span>
<span id="cb19-20"></span>
<span id="cb19-21">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"===== Llama3-70B-Instruct ====="</span>)</span>
<span id="cb19-22">    output <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> replicate.run(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"meta/meta-llama-3-70b-instruct"</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">input</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;">input</span>)</span>
<span id="cb19-23">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">""</span>.join(output))</span>
<span id="cb19-24">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">""</span>)</span>
<span id="cb19-25"></span>
<span id="cb19-26">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"===== Llama3-8B-Instruct ====="</span>)</span>
<span id="cb19-27">    output <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> replicate.run(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"meta/meta-llama-3-8b-instruct"</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">input</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;">input</span>)</span>
<span id="cb19-28">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">""</span>.join(output))</span>
<span id="cb19-29">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">""</span>)</span></code></pre></div>
<section id="observations-6" class="level5">
<h5 class="anchored" data-anchor-id="observations-6">Observations</h5>
<ol type="1">
<li><p>Generally the 70B model did an outstanding job of calling the tools and providing results that were as good, and sometimes better, than what I would have done.</p></li>
<li><p>The 8B model would return decent results most of the time, but the formatting was all over the place.</p></li>
</ol>
<p>This gave me a lot of confidence that open source models are a contender to consider. Even though the 8B model didn’t produce reliable results, the fact that the correct information was returned along with how well the 70B model performed, definitely make me think it might do really well in fine tuning.</p>
</section>
</section>
<section id="takeaways" class="level2">
<h2 class="anchored" data-anchor-id="takeaways">Takeaways</h2>
<p>After all this, I’m confident that my ideas are worthy to pursue. Based on the results above, it seems worthwhile to explore turning the following knobs to boost performance with these models:</p>
<ol type="1">
<li><p>Improved descriptions in the Pydantic classes</p></li>
<li><p>Improve the sytem prompt</p></li>
<li><p>Formulate varied human messages to simulate different ways the user may prompt the model</p></li>
</ol>
<p>Can you think of any other adjustments that might be beneficial? If so, drop a comment below!</p>
</section>
<section id="next-steps" class="level2">
<h2 class="anchored" data-anchor-id="next-steps">Next Steps</h2>
<p>With some insights about what I can play with to improve my results, it’s time for some experimentation. But how can I know whether or not the changes I’m making present meaningful progress? How can I know specificially where the model is struggling and look at those examples to inform future experiments?</p>
<p>The answer: I need to set up an initial evaluation pipeline along with some scoring functions.</p>
<p>And that is exactly what we’ll do in this next post in this series … stay tuned.</p>


</section>

 ]]></description>
  <category>NLP</category>
  <category>LLMS</category>
  <category>OpenAI</category>
  <category>Anthropic</category>
  <category>Meta</category>
  <category>FireworksAI</category>
  <category>Replicate</category>
  <category>Llama</category>
  <category>learning</category>
  <category>projects</category>
  <guid>https://ohmeow.com/posts/2024-07-18-llm-workshop-prompt-only.html</guid>
  <pubDate>Thu, 18 Jul 2024 07:00:00 GMT</pubDate>
  <media:content url="https://ohmeow.com/posts/images/blog-20240718/blog-20240718-header.png" medium="image" type="image/png" height="144" width="144"/>
</item>
<item>
  <title>LLM Workshop #2 - From Noise to Knowledge: Mastering the Art of Objective Definition and Data Refinement”</title>
  <dc:creator>Wayde Gilliam</dc:creator>
  <link>https://ohmeow.com/posts/2024-07-14-llm-workshop-objectives-data-filtration.html</link>
  <description><![CDATA[ 




<section id="what-do-you-want-to-build-and-should-you-build-it" class="level2">
<h2 class="anchored" data-anchor-id="what-do-you-want-to-build-and-should-you-build-it">What Do You Want To Build and Should You Build It?</h2>
<p>If you want to avoid a lot of needless back-and-forth as you go through the process of curating datasets for evaluation and/or fine tuning, building your eval pipeleines, training models, and so forth, stop and ask yourself, “What do I want to build and why?”. How you answer those questions will inform everything going forward!</p>
<p>Why am I making a big deal about this?</p>
<p>Simple, when I started … I didn’t do it.</p>
<p>I had a general idea of building a tool calling system for work and just dove in, and as I would get into various aspects of development I’d be like, “Hold on, this isn’t right … why am I trying to do this when all I really need is this?” In the end, I had to start over a few times, and before the last time, I decided to go outside with the dogs and a good cup of coffee and <strong><em>really</em></strong> think about what I wanted to accomplish and why.</p>
<p>Below is the result of that quiet time well spent.</p>
<div class="callout callout-style-default callout-tip 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">
Tip: Give your objectices a good think!
</div>
</div>
<div class="callout-body-container callout-body">
<p>It’s crucial to deeply consider what you aim to achieve and understand the reasons behind it. Reflecting on your objectives and motivations helps ensure that your efforts are purposeful and aligned with your aspirations. It will also help prevent you from needlessly starting over, as well as, give you confidence that what you “think you want” is realistic, useful, and will add value.</p>
<p>Things to ask yourself:</p>
<ul>
<li><p>What do you want the model to do for your end users?</p></li>
<li><p>Can you define specifically what the model is supposed to do, or is it so general that you find it difficult to scope or measure quality?</p></li>
<li><p>How diverse and varied does your data need to be to get the model to do what you want?</p></li>
</ul>
</div>
</div>
</section>
<section id="objective-definition" class="level2">
<h2 class="anchored" data-anchor-id="objective-definition">Objective Definition</h2>
<p>For this project I’ll be building a system where a user can ask an AI to perform various NLP tasks on one or more text documents. These documents represent survey comments sourced from several kinds of surveys delievered in higher education institutions (e.g., staff, faculty, student satisfaction and engagement surveys). There are core tasks that I need to perform like machine translation and sentiment analysis, but I’d also like to build a system whereby a user can provide it their own tools focused on NLP and the system figure out how to use them correctly.</p>
<section id="version-1.0" class="level3">
<h3 class="anchored" data-anchor-id="version-1.0">Version 1.0</h3>
<p>Currently I have a pipeline, that for every task, makes a call to GPT-4 for every document. I did this because I couldn’t get good results by giving GPT several somewhat complex tools for it to use based on what the user asked. The tools would get called but the results weren’t great. Evaluation has been left to the eyeballs of myself and other human data scientists, which of course isn’t optimal either.</p>
<p>Given that this current system is slow to process any substantial set of survey comments, relatively expensive given the number of calls to OpenAI I’m making, and doesn’t have a real evaluation-first workflow … I figured it was a good candidate for the course project. At the very least I could build an eval framework to really understand how well things were working and maybe fine tune a smaller model that could understand how to properly call all the tools to satisfy an end user’s ask in a single go.</p>
</section>
<section id="the-surface-area" class="level3">
<h3 class="anchored" data-anchor-id="the-surface-area">The Surface Area</h3>
<p>If your objectives are too general, for example a general purpose chatbot or even a general purpose tool calling machine, you are likely headed to some rough times. Considering my objective above, what can I infer about what I really want to build here?</p>
<ol type="1">
<li><p>The model should use <strong>NLP tools</strong> for specifically understanding <strong>survey comments from staff, students, and faculty in higher education</strong>. These comments are sourced from a number of surveys delievered to higher education audiences all over the country</p></li>
<li><p><strong>Some clients allow for their surveys to be taken into Spanish</strong>, so the machine translation tool will need to be called initially for each of these comments so that the remaining tasks can be performed wholistically on English texts.</p></li>
<li><p>Aside from machine translation, <strong>the core tools consist of functions for sentiment analysis, NER, summarization, and thematic analysis.</strong></p></li>
<li><p><strong>Each task operations on either whole survey comments or on semantically chunked comments</strong> that need to be associated to a “topic” for thematic analysis.</p></li>
<li><p>The <strong>tools should be focused on performing NLP tasks well, particular in the business domain of survey comments in higher educational settings.</strong></p></li>
</ol>
</section>
<section id="retrospective" class="level3">
<h3 class="anchored" data-anchor-id="retrospective">Retrospective</h3>
<p>Considering the above, this system definitely needs a solid eval workflow but also presents a potential great argument for fine tuning.</p>
<div class="callout callout-style-default callout-tip 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">
Narrow domains are great for fine tuning
</div>
</div>
<div class="callout-body-container callout-body">
<p>The more specific and specialized the task and/or data, the more likely you are to find success in fine tuning</p>
</div>
</div>
<p>Both the domain and tasks are very specific to higher education and NLP analysis in that setting, I have access to a lot of diverse data, and there is definite business value in creating a model that might reduce costs, speed up processing, and perform at the same level as GPT-4.</p>
<p>Given all this, I feel pretty good about proceeding.</p>
</section>
</section>
<section id="data-refinement" class="level2">
<h2 class="anchored" data-anchor-id="data-refinement">Data Refinement</h2>
<p>Based on my objectives, I need to chiefly be able to support two uses cases:</p>
<ol type="1">
<li><p><strong>Tasks that need to be performed on a single document</strong> (e.g., translation, summary, NER, sentiment). Traditionally we have only done sentiment on chunks because it is the chunks that are associated to topics and we want to report sentiment by topic. This still needs to happen but it might also be interesting to predict sentiment across the full comment as well.</p></li>
<li><p><strong>Tasks that need to be performed on a collection of related documents</strong> (.e.,g thematic analysis, topic sentiment).</p></li>
</ol>
<p>In this section we ask, “How can I curate a set of survey comments and semantically related chunks that are varied enough to support these two use cases across all our survey clients?”</p>
<section id="build-some-datasets" class="level3">
<h3 class="anchored" data-anchor-id="build-some-datasets">Build Some Datasets</h3>
<p>I need a diverse set of documents from different survey clients, delivered to different audiences (staff, student, and faculty), and with a subset being in Spanish. I also need to clean up these documents so they are actually useful. If they are too short or represent useless statements like “N/A” or “I don’t know”, they probably won’t be very helpful.</p>
<p>I don’t need to synthetically create any of the raw documents since I created the survey sytem and have access to the Microsoft SQL Server database it lies in.</p>
<p>Thinking about the use cases I need to support, the following four datasets will be created:</p>
<ol type="1">
<li><p><code>_clean</code>: A cleaned up version of the raw document dataset</p></li>
<li><p><code>_sample_Xk</code>: A sample of <code>X</code> rows from <code>cleaned</code> (mine will end up to be roughly 14k survey comments)</p></li>
<li><p><code>_sample_Xk_chunked</code>: A properly chunked version of <code>_sample_Xk</code> that includes predicted topics as well.</p></li>
<li><p><code>_sample_Xk_topics</code>: The chunks associated to each topic</p></li>
</ol>
<p>Document analysis tasks will use a mix of datasets #2 and #3 so they can learn to operate of both full and chunked comments. Related document analysis will use dataset #4 for thematic analysis and sentiment.</p>
<p>I am prohibited from sharing the actual data, but I can share the code I wrote to create these datasets for this project.</p>
<section id="step-1-cleanup" class="level4">
<h4 class="anchored" data-anchor-id="step-1-cleanup">Step 1: Cleanup</h4>
<p>I have almost 500k comments that span decades of surveys. Before building a representative sample, I want to remove those comments that aren’t likely to be used or even of much use for NLP tasks. For example, comments that are too short or uninformative (e.g., like “N/A”, or “Great”) shouldn’t be part of eval/training datasets. Preprocessing in version 1.0 takes these comments out in current pipeline so we’ll do so here as well.</p>
<p>After loading the full dataset and filtering on the columns I need to build up the datasets above, my DataFrame looks like this: <img src="https://ohmeow.com/posts/images/blog-20240714/raw-dataframe.png" class="img-fluid" alt="The raw data from the production DB"></p>
<p>In particular, we’ll run the functions below to slim this dataset down and give us quality comments we can confidently use in building out our sampled datasets.</p>
<section id="a.-remove-nans-and-trim-whitespaces" class="level5">
<h5 class="anchored" data-anchor-id="a.-remove-nans-and-trim-whitespaces">A. Remove NaNs and Trim Whitespaces</h5>
<div class="sourceCode" id="cb1" 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> init_document_preprocessing(df: pd.DataFrame, text_col: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>):</span>
<span id="cb1-2">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""Remove empty documents and clean up whitespace."""</span></span>
<span id="cb1-3">    df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> df.copy()</span>
<span id="cb1-4"></span>
<span id="cb1-5">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Remove all rows where `text_attr` is Nan</span></span>
<span id="cb1-6">    df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> df.dropna(subset<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;">set</span>([attr <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> attr <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> [text_col] <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> attr <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>])), how<span 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"</span>)</span>
<span id="cb1-7"></span>
<span id="cb1-8">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Remove all whitespace from `text_attr`, `language_attr`, `non_english_text_attr`</span></span>
<span id="cb1-9">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> attr <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;">list</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">set</span>([text_col, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"AnswerLang"</span>])):</span>
<span id="cb1-10">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> attr <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>
<span id="cb1-11">            df[attr] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> df[attr].<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">apply</span>(<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">lambda</span> v: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>(v).strip())</span>
<span id="cb1-12"></span>
<span id="cb1-13">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> df</span>
<span id="cb1-14"></span>
<span id="cb1-15">df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> init_document_preprocessing(raw_df, text_col<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"AnswerText"</span>)</span></code></pre></div>
</section>
<section id="b.-remove-duplicate-documents" class="level5">
<h5 class="anchored" data-anchor-id="b.-remove-duplicate-documents">B. Remove Duplicate Documents</h5>
<p>Duplicate comments won’t be helpful and they definitely exist even within a single survey. For example, some users try to game the system by repeating the same comment thoughout the survey in hopes of making sure their points float to the top.</p>
<div class="sourceCode" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb2-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> remove_duplicate_documents(df: pd.DataFrame, text_col: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>):</span>
<span id="cb2-2">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""Eliminate duplicate documents."""</span></span>
<span id="cb2-3">    df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> df.copy()</span>
<span id="cb2-4">    unique_attrs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [text_col]</span>
<span id="cb2-5"></span>
<span id="cb2-6">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Remove duplicate rows (keeping the first instance)</span></span>
<span id="cb2-7">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> df.drop_duplicates(subset<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>unique_attrs).copy()</span>
<span id="cb2-8"></span>
<span id="cb2-9">df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> remove_duplicate_documents(verbatims_df, text_col<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"AnswerText"</span>)</span></code></pre></div>
</section>
<section id="c.-remove-duplicated-sentences" class="level5">
<h5 class="anchored" data-anchor-id="c.-remove-duplicated-sentences">C. Remove Duplicated Sentences</h5>
<p>The same folks above also like to try and game the system by repeating the same phrase over and over again. The below code does a decent job at eliminating a string of repetitive content.</p>
<div class="sourceCode" id="cb3" 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> remove_duplicate_sentences(text: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>):</span>
<span id="cb3-2">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""Remove duplicated sentences throughout an entire text sequence."""</span></span>
<span id="cb3-3">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> text <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">is</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>:</span>
<span id="cb3-4">        text <span 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="cb3-5"></span>
<span id="cb3-6">    text <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> re.sub(<span class="vs" style="color: #20794D;
background-color: null;
font-style: inherit;">r"(?&lt;=[.!?])\s*"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">" "</span>, text)</span>
<span id="cb3-7">    sentences <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> nltk.sent_tokenize(text)</span>
<span id="cb3-8">    unique_sentences <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;">dict</span>.fromkeys(sentences))</span>
<span id="cb3-9"></span>
<span id="cb3-10">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Tokenize the text into sentences and remove duplicates by converting to set and back to list</span></span>
<span id="cb3-11">    <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;">" "</span>.join(unique_sentences)</span>
<span id="cb3-12"></span>
<span id="cb3-13"></span>
<span id="cb3-14"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> remove_duplicate_sentences_in_documents(df: pd.DataFrame, text_col: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>):</span>
<span id="cb3-15">    df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> df.copy()</span>
<span id="cb3-16">    df[text_col] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> df[text_col].<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">apply</span>(<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">lambda</span> v: remove_duplicate_sentences(v))</span>
<span id="cb3-17">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> df</span>
<span id="cb3-18"></span>
<span id="cb3-19">df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> remove_duplicate_sentences_in_documents(verbatims_df, text_col<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"AnswerText"</span>)</span></code></pre></div>
</section>
<section id="d.-remove-meaningless-and-short-documents" class="level5">
<h5 class="anchored" data-anchor-id="d.-remove-meaningless-and-short-documents">D. Remove Meaningless and Short Documents</h5>
<p>Comments that are too short or uninformative aren’t helpful to any NLP tasks. The code below removes much of this based on my examination of the data and running classification models that predicts whether a comment <code>is_nonsense</code>.</p>
<div class="sourceCode" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb4-1">remove_texts <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [</span>
<span id="cb4-2">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"none"</span>,</span>
<span id="cb4-3">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"nothing"</span>,</span>
<span id="cb4-4">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"not sure"</span>,</span>
<span id="cb4-5">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"no suggestions"</span>,</span>
<span id="cb4-6">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"no comment"</span>,</span>
<span id="cb4-7">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"no comments"</span>,</span>
<span id="cb4-8">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"nothing to add"</span>,</span>
<span id="cb4-9">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"n/a"</span>,</span>
<span id="cb4-10">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"none at this time"</span>,</span>
<span id="cb4-11">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"no comments at all"</span>,</span>
<span id="cb4-12">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"see previous comment"</span>,</span>
<span id="cb4-13">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"not really"</span>,</span>
<span id="cb4-14">]</span>
<span id="cb4-15"></span>
<span id="cb4-16"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> is_bad_value(s, remove_texts<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[]):</span>
<span id="cb4-17">    is_bad <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-18">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> rt <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> remove_texts:</span>
<span id="cb4-19">        is_bad <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;">bool</span>(re.match(<span class="vs" style="color: #20794D;
background-color: null;
font-style: inherit;">rf"^</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>rt<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>lower()<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>strip()<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="vs" style="color: #20794D;
background-color: null;
font-style: inherit;">[!.,;:?]*$"</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>(s).lower().strip()))</span>
<span id="cb4-20">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> is_bad:</span>
<span id="cb4-21">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">break</span></span>
<span id="cb4-22"></span>
<span id="cb4-23">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> is_bad</span>
<span id="cb4-24"></span>
<span id="cb4-25"></span>
<span id="cb4-26"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> remove_meaningless_documents(df, text_col: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>):</span>
<span id="cb4-27">    df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> df.copy()</span>
<span id="cb4-28">    df[text_col] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> df[text_col].<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">apply</span>(<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">lambda</span> v: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>(v) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> v <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;">and</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">not</span> is_bad_value(v, remove_texts) <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="cb4-29">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> df</span>
<span id="cb4-30"></span>
<span id="cb4-31"></span>
<span id="cb4-32"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> remove_short_documents(df: pd.DataFrame, text_col: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>, min_text_length: <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;">5</span>):</span>
<span id="cb4-33">    df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> df.copy()</span>
<span id="cb4-34">    df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> df[pd.notna(df[text_col]) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;</span> (df[text_col].<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;">len</span>() <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;=</span> min_text_length)]</span>
<span id="cb4-35">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> df</span>
<span id="cb4-36"></span>
<span id="cb4-37">df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> remove_meaningless_documents(verbatims_df, text_col<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"AnswerText"</span>)</span>
<span id="cb4-38">df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> remove_short_documents(verbatims_df, text_col<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"AnswerText"</span>)</span></code></pre></div>
<p>That’s it for dataset #1, let’s save it</p>
<div class="sourceCode" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb5-1">df.to_parquet(<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>DATA_DIR<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;">/clean/documents_all.parquet"</span>)</span></code></pre></div>
</section>
</section>
<section id="step-2-sample" class="level4">
<h4 class="anchored" data-anchor-id="step-2-sample">Step 2: Sample</h4>
<p>There are a lot of documents so we’ll create a subset of &lt; 15k with enough variation for meaningful scoring functions and finetunes</p>
<section id="a.-build-a-representative-subset" class="level5">
<h5 class="anchored" data-anchor-id="a.-build-a-representative-subset">A. Build a Representative Subset</h5>
<p>There are two core types of surveys, satisfaction and engagement. There are many more instances of the satisfaction surveys so we’ll want to have more of those in our sampled dataset to mimic reality.</p>
<div class="sourceCode" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb6-1">filtered_df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> df[(df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"BenchmarkSurveyType"</span>].<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>.startswith(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"CSS-"</span>))]</span>
<span id="cb6-2"></span>
<span id="cb6-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Calculate the number of samples for each BenchmarkSurveyType</span></span>
<span id="cb6-4">sample_sizes <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> filtered_df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"BenchmarkSurveyType"</span>].value_counts(normalize<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> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10000</span></span>
<span id="cb6-5">sample_sizes <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> sample_sizes.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">round</span>().astype(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>)</span>
<span id="cb6-6"></span>
<span id="cb6-7"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Sample records proportionally with a bias towards longer comments</span></span>
<span id="cb6-8">sampled_df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> pd.DataFrame()</span>
<span id="cb6-9"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> survey_type, size <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> sample_sizes.items():</span>
<span id="cb6-10">    subset <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> filtered_df[filtered_df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"BenchmarkSurveyType"</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> survey_type]</span>
<span id="cb6-11">    weights <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> subset[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"AnswerTextCharacterCount"</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> subset[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"AnswerTextCharacterCount"</span>].<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>()</span>
<span id="cb6-12">    sampled_records <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> subset.sample(n<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>size, weights<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>weights, random_state<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="cb6-13">    sampled_df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> pd.concat([sampled_df, sampled_records])</span>
<span id="cb6-14"></span>
<span id="cb6-15"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Reset index if needed</span></span>
<span id="cb6-16">sampled_df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> sampled_df.reset_index(drop<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-17"></span>
<span id="cb6-18"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># This gets us down to 10k examples of customer satisfaction like surveys.</span></span>
<span id="cb6-19"></span>
<span id="cb6-20">sampled_df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> pd.concat([sampled_df, df[(df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"BenchmarkSurveyType"</span>].<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>.startswith(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"SAW"</span>))]])</span>
<span id="cb6-21"></span>
<span id="cb6-22"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Adding in these staff engagement surveys get us to a total of almost 14k examples</span></span></code></pre></div>
</section>
<section id="b.-add-in-some-spanish-documents" class="level5">
<h5 class="anchored" data-anchor-id="b.-add-in-some-spanish-documents">B. Add in some Spanish Documents</h5>
<p>I lied when I said there was no syntetically generated data because we’re going to use an LLM to generate some Spanish content from our English survey comments. We’ll use one of my favorite libraries, <a href="https://www.langchain.com/" target="_blank">LangChain</a>, to generate 250 Spanish examples.</p>
<div class="sourceCode" id="cb7" 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;">class</span> SpanishTranslation(BaseModel):</span>
<span id="cb7-2">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""The translation of a document from English to Spanish."""</span></span>
<span id="cb7-3"></span>
<span id="cb7-4">    spanish_translation: <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> Field(..., description<span 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 English tranlsation"</span>)</span>
<span id="cb7-5"></span>
<span id="cb7-6"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> get_openai_translation_messages(domain: <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;">"survey comments"</span>):</span>
<span id="cb7-7">    system_msg <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"You are a world class translator. Translate the English </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>domain<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;"> below to Spanish. Properly escape strings."</span></span>
<span id="cb7-8">    human_msg <span 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="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{input}</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span></span>
<span id="cb7-9"></span>
<span id="cb7-10">    prompt_msgs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [SystemMessage(content<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>system_msg), HumanMessagePromptTemplate.from_template(human_msg)]</span>
<span id="cb7-11">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> prompt_msgs</span>
<span id="cb7-12"></span>
<span id="cb7-13">llm <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> ChatOpenAI(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;">"gpt-4"</span>)</span>
<span id="cb7-14">messages <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> get_openai_translation_messages()</span>
<span id="cb7-15"></span>
<span id="cb7-16">prompt <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> ChatPromptTemplate(messages<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>messages)</span>
<span id="cb7-17">functions <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [convert_to_openai_function(SpanishTranslation)]</span>
<span id="cb7-18"></span>
<span id="cb7-19">chain <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> prompt <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|</span> llm.bind(function_call<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>{<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"name"</span>: SpanishTranslation.<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">__name__</span>}, functions<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>functions) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|</span> JsonOutputFunctionsParser()</span>
<span id="cb7-20"></span>
<span id="cb7-21">spanish_sample_df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> sampled_df.sample(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">250</span>, random_state<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;">9</span>)</span>
<span id="cb7-22"></span>
<span id="cb7-23">spanish_translations <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> []</span>
<span id="cb7-24"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> r_idx, r <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> spanish_sample_df.iterrows():</span>
<span id="cb7-25">    rsp <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> chain.invoke({<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"input"</span>: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>(r[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"AnswerText"</span>])})</span>
<span id="cb7-26">    spanish_translations.append(rsp[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"spanish_translation"</span>])</span>
<span id="cb7-27"></span>
<span id="cb7-28">sampled_df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"AnswerText_NonEnglish"</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>
<span id="cb7-29">sampled_df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"AnswerLang"</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;">"English"</span></span>
<span id="cb7-30"></span>
<span id="cb7-31">spanish_sample_df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"AnswerText_NonEnglish"</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> spanish_translations</span>
<span id="cb7-32">spanish_sample_df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"AnswerLang"</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;">"Spanish"</span></span>
<span id="cb7-33"></span>
<span id="cb7-34"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Set 'MLVerbatId' as the index for both DataFrames</span></span>
<span id="cb7-35">sampled_df.set_index(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"MLVerbatimId"</span>, inplace<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="cb7-36">spanish_sample_df.set_index(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"MLVerbatimId"</span>, inplace<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="cb7-37"></span>
<span id="cb7-38"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Update df1 with values from df2</span></span>
<span id="cb7-39">sampled_df.update(spanish_sample_df)</span>
<span id="cb7-40"></span>
<span id="cb7-41"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Reset index if needed</span></span>
<span id="cb7-42">sampled_df.reset_index(inplace<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>
<p>That’s it for dataset #2, let’s save it</p>
<div class="sourceCode" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb8-1">df.to_parquet(<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>DATA_DIR<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;">/clean/documents_sample_14k.parquet"</span>)</span></code></pre></div>
</section>
</section>
<section id="step-3-chunk" class="level4">
<h4 class="anchored" data-anchor-id="step-3-chunk">Step 3: Chunk</h4>
<p>The core thematic analysis task we need to support operates on semantically related survey comment “chunks”. In addition to predicting themes for these collections, we also need to report the sentiment for each chunk so that we can visualize sentiment as it relates to each topic.</p>
<p>We’ll use the <a href="https://github.com/aurelio-labs/semantic-chunkers" target="\_blank">semantic-chunkers</a> library to build semantically related chunks which is something the current pipeline doesn’t use yet, but makes a lot of sense to me after exploring chunking in depth over the past few months or so. I really like this library and it comes with some nifty visualization capabilities for tuning its hyperparameters.</p>
<p>Chunking can be somewhat complex and use case specific, but for the puposes of survey comments we are usually working with paragraphs and sentences sometimes containing bullet points to further deliniate different topics. Given this, I’ve asked chatGPT about general token usage for English paragraphs and sentences to set a few of these hyperparameters and do some basic preliminary chunking before using the <code>semantic-chunkers</code> library.</p>
<p>According to chatGPT, the average number of characters in an English sentence and paragraph can vary based on factors such as writing style, purpose, and medium. However, general estimates are as follows:</p>
<ol type="1">
<li><p><strong>Average Characters in an English Sentence:</strong></p>
<ul>
<li>An average English sentence typically contains around 15 to 20 words.</li>
<li>Assuming an average word length of 5 characters (including spaces and punctuation), an average sentence would be approximately 75 to 100 characters.</li>
</ul></li>
<li><p><strong>Average Characters in an English Paragraph:</strong></p>
<ul>
<li>An average English paragraph usually contains about 3 to 5 sentences.</li>
<li>Using the upper bound of 5 sentences and assuming each sentence is 100 characters, an average paragraph would be around 300 to 500 characters.</li>
</ul></li>
</ol>
<p>These averages can fluctuate based on the type of text (e.g., academic writing, casual writing, technical documentation) and individual writing styles but it seems reasonable to assume on average:</p>
<ul>
<li>A min sentence has 15 * 1.5 = 23 tokens</li>
<li>A max paragrpah as 20 _ 5 _ 1.5 = 150 tokens</li>
</ul>
<p>If you’re interested in learning about the <code>semantic-chunkers</code>, check out these resources:</p>
<p><a href="https://github.com/aurelio-labs/semantic-chunkers/blob/main/docs/00-chunkers-intro.ipynb" target="\_blank">Semantic Chunkers Into (Colab)</a></p>
<p><a href="https://www.youtube.com/watch?v=TcRRfcbsApw" target="\_blank">Semantic Chunking for RAG (James Briggs)</a></p>
<section id="a.-preliminary-chunking" class="level5">
<h5 class="anchored" data-anchor-id="a.-preliminary-chunking">A. Preliminary Chunking</h5>
<p>We start with the assumption that paragraphs likely represent distinct topics a user is trying to get at in any given survey comment. If there are bullet points, regardless of format, we also assume that each of these likely represent a distinct idea or “chunk.” Given this, we will do some initial chunking based on those assumptions.</p>
<p>Also, I have and continue to look at a lot of this data, so they aren’t really assumptions as much as they simply reflect what I see.</p>
<div class="sourceCode" 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> chunk_paragraphs(text):</span>
<span id="cb9-2">    paragraphs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> re.split(</span>
<span id="cb9-3">        <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;">\r\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;">\\\\</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;">r</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="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="vs" style="color: #20794D;
background-color: null;
font-style: inherit;">r"\\n\s*[-•*o]|\\n\s*\d+[.)]"</span>, text</span>
<span id="cb9-4">    )  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># text.split("\n\n")  # Split text by double line breaks to identify paragraphs</span></span>
<span id="cb9-5"></span>
<span id="cb9-6">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> [chunk.strip() <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> chunk <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> paragraphs <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;">len</span>(chunk.strip()) <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;">4</span>]</span>
<span id="cb9-7"></span>
<span id="cb9-8"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> chunk_texts(df: pd.DataFrame):</span>
<span id="cb9-9">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""Chunk the paragraphs keeping any bullet points alongside their context."""</span></span>
<span id="cb9-10">    df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> df.copy()</span>
<span id="cb9-11"></span>
<span id="cb9-12">    df.insert(<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;">"_seq"</span>, df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"AnswerText"</span>].<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">apply</span>(<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">lambda</span> v: chunk_paragraphs(v)))</span>
<span id="cb9-13"></span>
<span id="cb9-14">    df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> df.explode(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"_seq"</span>).reset_index(drop<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="cb9-15">    df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"_seq"</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"_seq"</span>].<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>.strip()</span>
<span id="cb9-16">    df.insert(<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;">"_seq_id"</span>, df.groupby([<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"MLVerbatimId"</span>]).cumcount())</span>
<span id="cb9-17">    df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"_seq_length"</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"_seq"</span>].<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;">len</span>()</span>
<span id="cb9-18"></span>
<span id="cb9-19">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> df</span>
<span id="cb9-20"></span>
<span id="cb9-21"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> remove_bullet_points(text):</span>
<span id="cb9-22">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> re.sub(<span class="vs" style="color: #20794D;
background-color: null;
font-style: inherit;">r"(^|\n)\s*[-•*o]\s*|\n\s*\d+[.)]\s*"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">" "</span>, text).strip()</span>
<span id="cb9-23"></span>
<span id="cb9-24">chunked_df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> chunk_texts(sampled_df)</span>
<span id="cb9-25">chunked_df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"_seq"</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> chunked_df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"_seq"</span>].<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">apply</span>(remove_bullet_points)</span></code></pre></div>
</section>
<section id="b.-semantic-chunking" class="level5">
<h5 class="anchored" data-anchor-id="b.-semantic-chunking">B. Semantic Chunking</h5>
<p>From the <code>semantic-chunkers</code> intro notebook mentioned above:</p>
<blockquote class="blockquote">
<p>The statistical chunking method our most robust chunking method, it uses a varying similarity threshold to identify more dynamic and local similarity splits. It offers a good balance between accuracy and efficiency but can only be used for text documents (unlike the multi-modal ConsecutiveChunker).</p>
</blockquote>
<blockquote class="blockquote">
<p>The StatisticalChunker can automatically identify a good threshold value to use while chunking our text, so it tends to require less customization than our other chunkers.</p>
</blockquote>
<p>I did some review of specific examples and played with the hyperparameters to get what looked like decent results. Here is what I came up with ultimately for perform the final chunking of the dataset.</p>
<div class="sourceCode" id="cb10" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb10-1">encoder <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> HuggingFaceEncoder(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;">"thenlper/gte-large"</span>)</span>
<span id="cb10-2"></span>
<span id="cb10-3">chunker <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> StatisticalChunker(</span>
<span id="cb10-4">    encoder<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>encoder,</span>
<span id="cb10-5">    threshold_adjustment<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>
<span id="cb10-6">    dynamic_threshold<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="cb10-7">    window_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;">5</span>,  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># 5,</span></span>
<span id="cb10-8">    min_split_tokens<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;">23</span>,  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># 100,</span></span>
<span id="cb10-9">    max_split_tokens<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;">300</span>,  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># 500</span></span>
<span id="cb10-10">    split_tokens_tolerance<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>,</span>
<span id="cb10-11">    plot_chunks<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="cb10-12">    enable_statistics<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="cb10-13">)</span>
<span id="cb10-14"></span>
<span id="cb10-15"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> get_semantic_chunks(txt: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>, min_chars_to_chunk: <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;">90</span>):</span>
<span id="cb10-16">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">try</span>:</span>
<span id="cb10-17">        <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;">len</span>(txt.strip()) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> min_chars_to_chunk:</span>
<span id="cb10-18">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> [txt.strip()]</span>
<span id="cb10-19">        chunks <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> chunker(docs<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[txt])</span>
<span id="cb10-20">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> [chunk.content.strip() <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> chunk <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> chunks[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>]]</span>
<span id="cb10-21">    <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>
<span id="cb10-22">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> [txt.strip()]</span>
<span id="cb10-23"></span>
<span id="cb10-24"></span>
<span id="cb10-25">seqs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> chunked_df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"_seq"</span>].values.tolist()</span>
<span id="cb10-26">chunked_docs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> []</span>
<span id="cb10-27"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> seq <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> tqdm(seqs):</span>
<span id="cb10-28">    chunked_docs.append(get_semantic_chunks(seq))</span>
<span id="cb10-29"></span>
<span id="cb10-30">chunked_df.insert(<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;">"_chunk"</span>, chunked_docs)</span>
<span id="cb10-31">chunked_df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> chunked_df.explode(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"_chunk"</span>).reset_index(drop<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="cb10-32">chunked_df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"_chunk"</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> chunked_df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"_chunk"</span>].<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>.strip()</span>
<span id="cb10-33">chunked_df.insert(<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;">"_chunk_id"</span>, chunked_df.groupby([<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"MLVerbatimId"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"_seq_id"</span>]).cumcount())</span>
<span id="cb10-34">chunked_df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"_chunk_length"</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> chunked_df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"_chunk"</span>].<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;">len</span>()</span></code></pre></div>
</section>
<section id="c.-use-berttopic-associate-each-chunk-to-a-topic" class="level5">
<h5 class="anchored" data-anchor-id="c.-use-berttopic-associate-each-chunk-to-a-topic">C. Use <code>BertTopic</code> Associate Each Chunk To A Topic</h5>
<p>I’m not going to go into the specifics of this step since I don’t get detract from the focuse of this article anymore than I likely already have. Suffice to say, I use <a href="https://maartengr.github.io/BERTopic/index.html" target="\_blank">BERTopic</a> to create and assign topics to each “chunk”. This is another great and feature rich library that I’ve been using for a few years.</p>
<p>The artifact produced at the conclusion of this step is a DataFrame with topic identiferis associated to each <code>_chunk</code>. It looks like this: <img src="https://ohmeow.com/posts/images/blog-20240714/raw-chunked-df.png" class="img-fluid" alt="The chunked dataset with topic identifiers"></p>
<p>That’s it for dataset #3, let’s save it</p>
<div class="sourceCode" id="cb11" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb11-1">chunked_df.to_parquet(<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>DATA_DIR<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;">/clean/documents_sample_14k_chunked.parquet"</span>)</span></code></pre></div>
</section>
</section>
<section id="step-4-topic-summaries" class="level4">
<h4 class="anchored" data-anchor-id="step-4-topic-summaries">Step 4: Topic Summaries</h4>
<p>We need to evaluate the ability for the model to summarize and define action plans for related “chunks” as identified by a topic model. We’ll use the chunked dataset create above to put something together we can use to predict/evaluate the themes and action plans we assign to topics.</p>
<p>Fortunately for you, the reader, there isn’t alot of code to make this happen :)</p>
<div class="sourceCode" id="cb12" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb12-1">topics_df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> chunked_df.copy()</span>
<span id="cb12-2"></span>
<span id="cb12-3">cols <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"pred_theme_id"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"pred_orig_theme_name"</span>]</span>
<span id="cb12-4"></span>
<span id="cb12-5">topics_df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"pred_theme_id"</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> topics_df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"pred_theme_id"</span>].astype(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>)</span>
<span id="cb12-6">topics_df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"_chunk"</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> topics_df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"_chunk"</span>].astype(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>)</span>
<span id="cb12-7"></span>
<span id="cb12-8">summaries_df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> topics_df.groupby(by<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>cols)[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"_chunk"</span>].agg(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>).reset_index()</span></code></pre></div>
<p>That’s it for dataset #4, let’s save it</p>
<div class="sourceCode" id="cb13" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb13-1">summaries_df.to_parquet(<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>DATA_DIR<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;">/clean/documents_sample_14k_topics.parquet"</span>)</span></code></pre></div>
</section>
</section>
</section>
<section id="next-steps" class="level2">
<h2 class="anchored" data-anchor-id="next-steps">Next Steps</h2>
<p>With some high quality context, we’ll move on to getting a “vibe check” for how likely what we want to build is possible by seeing what kinds of structured outputs we get when using the big dogs. In particular we’ll be running some tests with OpenAI, Anthropic, Fireworks, and Replicate to develop a good intutition of how well to expect things might work with both closed and open source models.</p>
<p>Again, I’m using <a href="https://github.com/parlance-labs/ftcourse" target="\_blank">Hamel’s ftcourse repo</a> as a general guide for building this project out so make sure to check it out as y’all start your own journeys. The topic in this blog post isn’t necessarily covered in any of his notebooks so consider this the <code>00</code> notebook that is more or less implied in the course.</p>
<p>Also, I welcome any ideas on improving anything and everything presented above. Especially if you notice any really egregious and glaring errors in my thinking or workflow, I’d defintely appreciate your thoughts. Either way, thanks for reading to the end :)</p>


</section>

 ]]></description>
  <category>NLP</category>
  <category>LLMS</category>
  <category>data cleaning</category>
  <category>learning</category>
  <category>projects</category>
  <guid>https://ohmeow.com/posts/2024-07-14-llm-workshop-objectives-data-filtration.html</guid>
  <pubDate>Sun, 14 Jul 2024 07:00:00 GMT</pubDate>
  <media:content url="https://ohmeow.com/posts/images/blog-20240714/blog-20240714-logo.png" medium="image" type="image/png" height="82" width="144"/>
</item>
<item>
  <title>Structuring Enums for Flawless LLM results with Instructor</title>
  <dc:creator>Wayde Gilliam</dc:creator>
  <link>https://ohmeow.com/posts/2024-07-06-llms-and-enums.html</link>
  <description><![CDATA[ 




<section id="instructor-best-practices-and-cautions" class="level2">
<h2 class="anchored" data-anchor-id="instructor-best-practices-and-cautions">Instructor Best Practices and Cautions</h2>
<div>
<p>I’m spending some time with the <a href="https://x.com/jxnlco" target="_blank">Jason Liu</a>’s <a href="https://useinstructor.com/" target="_blank">Instructor library</a> in building a function calling solution that returns structured output because, well, Hamel recommends it for proprietary models.</p>
<blockquote class="blockquote">
<p><img src="https://ohmeow.com/posts/images/blog-20240603/hamel-icon.png" alt="Hamel" style="border-radius:30px;width:auto;height:25px;"> For open models you should use outlines. for closed models APIs you should use instructor.</p>
</blockquote>
<p>The library is intuitive, fun to use, and has some really nice documentation. When it comes to choosing whether to use enums or literals in your pydantic classes, <a href="https://python.useinstructor.com/tutorials/2-tips/?h=enums" target="_blank">the docs recommend the following</a>:</p>
<blockquote class="blockquote">
<p>For classification we’ve found theres generally two methods of modeling.</p>
<ol type="1">
<li>using Enums</li>
<li>using Literals</li>
</ol>
<p>Use an enum in Python when you need a set of named constants that are related and you want to ensure type safety, readability, and prevent invalid values. Enums are helpful for grouping and iterating over these constants.</p>
<p>Use literals when you have a small, unchanging set of values that you don’t need to group or iterate over, and when type safety and preventing invalid values is less of a concern. Literals are simpler and more direct for basic, one-off values.</p>
</blockquote>
<p>… and they also seems to indicate that <a href="https://python.useinstructor.com/concepts/prompting/?h=enums#tips-for-enumerations" target="_blank">getting them to work as expected might be challenging</a> …</p>
<blockquote class="blockquote">
<p>If you’re having a hard time with Enum an alternative is to use Literal</p>
</blockquote>
<p>I found this out first-hand when I was attempting to define an enum for a number of named entities I wanted an LLM to identifiy in a given document. My intial code worked pretty nicely with GPT-4o but failed miserabley time and time again with every Antrhopic model I tried (I’ll explain why below). If you’re looking for the TL;DR, the final version of my code at the end of this post represents a substantially more resiliant solution that works across vendors (I also tested this with <a href="https://fireworks.ai/" target="_blank">Fireworks</a>), offering a better guaranttee your LLM calls find the entities you care about correctly.</p>
</div>
</section>
<section id="v0-using-enum" class="level2">
<h2 class="anchored" data-anchor-id="v0-using-enum">v0: Using <code>Enum</code></h2>
<p>This is the initial <code>Enum</code> and pydantic classes I started with. It works pretty damn well with OpenAI’s GPT-4o but fails spectacularly when using any of the Anthopic models.</p>
<div class="sourceCode" id="cb1" 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;">class</span> EntityGroup(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>, Enum):</span>
<span id="cb1-2">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""A named entity type."""</span></span>
<span id="cb1-3"></span>
<span id="cb1-4">    PERSON <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"PERSON"</span></span>
<span id="cb1-5">    ORGANIZATION <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ORGANIZATION"</span></span>
<span id="cb1-6">    LOCATION <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"LOCATION"</span></span>
<span id="cb1-7">    DATE <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"DATE"</span></span>
<span id="cb1-8">    TIME <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"TIME"</span></span>
<span id="cb1-9">    PERCENT <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"PERCENT"</span></span>
<span id="cb1-10">    MONEY <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"MONEY"</span></span>
<span id="cb1-11">    QUANTITY <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"QUANTITY"</span></span>
<span id="cb1-12">    ORDINAL <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ORDINAL"</span></span>
<span id="cb1-13">    CARDINAL <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"CARDINAL"</span></span>
<span id="cb1-14">    EMAIL <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"EMAIL"</span></span>
<span id="cb1-15">    PHONE_NUMBER <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"PHONE_NUMBER"</span></span>
<span id="cb1-16">    CREDIT_CARD_NUMBER <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"CREDIT_CARD_NUMBER"</span></span>
<span id="cb1-17">    SSN <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"SSN"</span></span>
<span id="cb1-18"></span>
<span id="cb1-19"></span>
<span id="cb1-20"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> NamedEntity(BaseModel):</span>
<span id="cb1-21">    entity_group: EntityGroup</span>
<span id="cb1-22">    word: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span></span>
<span id="cb1-23"></span>
<span id="cb1-24"></span>
<span id="cb1-25"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> DocumentNER(BaseModel):</span>
<span id="cb1-26">    named_entities: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>[NamedEntity]</span></code></pre></div>
<p>When using the Anthropic models, I would consistently see it trying to set <code>entity_group</code> to a string rather than a proper enum value from the <code>EntityGroup</code> enum.</p>
<p>After iterating through a number of prompt and class/field description modifications, I decided to give up and replace my <code>Enum</code> with a <code>Literal</code>. And guess what, everything worked great across all model vendors.</p>
<p>I also decided to lookup the named entities used in Spacy and use those names in my <code>Enum</code> as it makes sense to me that perhaps these libraries might have been included in the training of these LLMs and so maybe will help it do a better job of finding the entities I care about.</p>
</section>
<section id="v1-using-literal" class="level2">
<h2 class="anchored" data-anchor-id="v1-using-literal">v1: Using <code>Literal</code></h2>
<p>Using the <code>Literal</code> type fixed everything and works great across all models! Here’s what it looks like:</p>
<div class="sourceCode" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb2-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> NamedEntity(BaseModel):</span>
<span id="cb2-2">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""A named entity found in a document."""</span></span>
<span id="cb2-3"></span>
<span id="cb2-4">    entity_type: Literal[</span>
<span id="cb2-5">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"PERSON"</span>,</span>
<span id="cb2-6">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"NORP"</span>,</span>
<span id="cb2-7">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"FAC"</span>,</span>
<span id="cb2-8">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ORG"</span>,</span>
<span id="cb2-9">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"GPE"</span>,</span>
<span id="cb2-10">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"LOC"</span>,</span>
<span id="cb2-11">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"PRODUCT"</span>,</span>
<span id="cb2-12">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"EVENT"</span>,</span>
<span id="cb2-13">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"WORK_OF_ART"</span>,</span>
<span id="cb2-14">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"LAW"</span>,</span>
<span id="cb2-15">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"LANGUAGE"</span>,</span>
<span id="cb2-16">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"DATE"</span>,</span>
<span id="cb2-17">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"TIME"</span>,</span>
<span id="cb2-18">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"PERCENT"</span>,</span>
<span id="cb2-19">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"MONEY"</span>,</span>
<span id="cb2-20">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"QUANTITY"</span>,</span>
<span id="cb2-21">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ORDINAL"</span>,</span>
<span id="cb2-22">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"CARDINAL"</span>,</span>
<span id="cb2-23">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"OTHER"</span>,</span>
<span id="cb2-24">    ]</span>
<span id="cb2-25">    entity: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span></span>
<span id="cb2-26"></span>
<span id="cb2-27"></span>
<span id="cb2-28"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> DocumentNERTask(BaseModel):</span>
<span id="cb2-29">    named_entities: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>[NamedEntity]</span></code></pre></div>
<p>This works great … but I really wanted to use an <code>Enum</code> for the reasons listed at the top of this post. And as I’m the kinda guy who enjoys fighting with CUDA installs on his local DL rig, I decided to give it a go after taking a few hours off to enjoy the Euros and Copa America tourneys (also Germany should have won; that was a handball but nah, I’m not angry, nope, not bent at all).</p>
</section>
<section id="v2-using-enum-revisted" class="level2">
<h2 class="anchored" data-anchor-id="v2-using-enum-revisted">v2: Using <code>Enum</code> Revisted</h2>
<p>Here’s the TL;DR version of the code. This version is working fabulously across all APIs and I have yet to encounter a single exception involving Instructor being unable to assign a valid value from the <code>Enum</code>.</p>
<div class="sourceCode" id="cb3" 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;">class</span> NamedEntityType(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>, Enum):</span>
<span id="cb3-2">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""Valid types of named entities to extract."""</span></span>
<span id="cb3-3"></span>
<span id="cb3-4">    PERSON <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"PERSON"</span></span>
<span id="cb3-5">    NORP <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"NORP"</span></span>
<span id="cb3-6">    FAC <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"FAC"</span></span>
<span id="cb3-7">    ORG <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ORG"</span></span>
<span id="cb3-8">    GPE <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"GPE"</span></span>
<span id="cb3-9">    LOC <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"LOC"</span></span>
<span id="cb3-10">    PRODUCT <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"PRODUCT"</span></span>
<span id="cb3-11">    EVENT <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"EVENT"</span></span>
<span id="cb3-12">    WORK_OF_ART <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"WORK_OF_ART"</span></span>
<span id="cb3-13">    LAW <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"LAW"</span></span>
<span id="cb3-14">    LANGUAGE <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"LANGUAGE"</span></span>
<span id="cb3-15">    DATE <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"DATE"</span></span>
<span id="cb3-16">    TIME <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"TIME"</span></span>
<span id="cb3-17">    PERCENT <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"PERCENT"</span></span>
<span id="cb3-18">    MONEY <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"MONEY"</span></span>
<span id="cb3-19">    QUANTITY <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"QUANTITY"</span></span>
<span id="cb3-20">    ORDINAL <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ORDINAL"</span></span>
<span id="cb3-21">    CARDINAL <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"CARDINAL"</span></span>
<span id="cb3-22">    OTHER <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"OTHER"</span></span>
<span id="cb3-23"></span>
<span id="cb3-24"></span>
<span id="cb3-25"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> NamedEntity(BaseModel):</span>
<span id="cb3-26">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""A named entity result."""</span></span>
<span id="cb3-27"></span>
<span id="cb3-28">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> convert_str_to_named_entity_type(v: <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> NamedEntityType) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> NamedEntityType:</span>
<span id="cb3-29">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""Ensure entity type is a valid enum."""</span></span>
<span id="cb3-30">        <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>(v, NamedEntityType):</span>
<span id="cb3-31">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> v</span>
<span id="cb3-32">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span>:</span>
<span id="cb3-33">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">try</span>:</span>
<span id="cb3-34">                <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> NamedEntityType(v)</span>
<span id="cb3-35">            <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;">ValueError</span>:</span>
<span id="cb3-36">                <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> NamedEntityType.OTHER</span>
<span id="cb3-37"></span>
<span id="cb3-38">    entity_type: Annotated[<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>, BeforeValidator(convert_str_to_named_entity_type)]</span>
<span id="cb3-39">    entity_mention: <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> Field(..., description<span 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 named entity recognized."</span>)</span>
<span id="cb3-40"></span>
<span id="cb3-41"></span>
<span id="cb3-42"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> DocumentNERTask(BaseModel):</span>
<span id="cb3-43">    named_entities: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>[NamedEntity]</span></code></pre></div>
<p>Besides the return of the <code>Enum</code>, the most noticeable change involves the inclusion of a <code>BeforeValidator</code> that ensures the value is assigned to a valid enum as defined in <code>NamedEntity</code>. In cases where it wants to add an entity to the list of <code>named_entities</code> that isn’t defined in the <code>NamedEntityType</code> enum or is named differently (e.g., “ORGANIZATION” vs.&nbsp;“ORG”), it will assign them to <code>OTHER</code>.</p>
<p>With this in place, I now have a solution that is:</p>
<ol type="1">
<li><p>More resiliant</p></li>
<li><p>Can be used in debugging named entity recogintion (e.g, I can explore what named entities might be missing from the <code>Enum</code> or getting named differently by looking at those that get associated with the <code>OTHER</code> value)</p></li>
<li><p>I can use that same beautiful <code>Enum</code> across all parts of my application</p></li>
</ol>
</section>
<section id="v2.0.1-using-enum-and-fuzzywuzzy" class="level2">
<h2 class="anchored" data-anchor-id="v2.0.1-using-enum-and-fuzzywuzzy">v2.0.1: Using <code>Enum</code> and <code>fuzzywuzzy</code></h2>
<p>A suggestion from a Twitter user inspired me to enhance our approach by implementing similarity-based matching rather than relying on exact matches. To make it so, I installed the <code>fuzzywuzzy</code> library and made the necessary modifications to increase the likelihood of delivering high-quality results.</p>
<div class="sourceCode" id="cb4" 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;">class</span> NamedEntityType(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>, Enum):</span>
<span id="cb4-2">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""Valid types of named entities to extract."""</span></span>
<span id="cb4-3"></span>
<span id="cb4-4">    PERSON <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"PERSON"</span></span>
<span id="cb4-5">    NORP <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"NORP"</span></span>
<span id="cb4-6">    FAC <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"FAC"</span></span>
<span id="cb4-7">    ORG <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ORG"</span></span>
<span id="cb4-8">    GPE <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"GPE"</span></span>
<span id="cb4-9">    LOC <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"LOC"</span></span>
<span id="cb4-10">    PRODUCT <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"PRODUCT"</span></span>
<span id="cb4-11">    EVENT <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"EVENT"</span></span>
<span id="cb4-12">    WORK_OF_ART <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"WORK_OF_ART"</span></span>
<span id="cb4-13">    LAW <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"LAW"</span></span>
<span id="cb4-14">    LANGUAGE <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"LANGUAGE"</span></span>
<span id="cb4-15">    DATE <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"DATE"</span></span>
<span id="cb4-16">    TIME <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"TIME"</span></span>
<span id="cb4-17">    PERCENT <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"PERCENT"</span></span>
<span id="cb4-18">    MONEY <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"MONEY"</span></span>
<span id="cb4-19">    QUANTITY <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"QUANTITY"</span></span>
<span id="cb4-20">    ORDINAL <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ORDINAL"</span></span>
<span id="cb4-21">    CARDINAL <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"CARDINAL"</span></span>
<span id="cb4-22">    OTHER <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"OTHER"</span></span>
<span id="cb4-23"></span>
<span id="cb4-24"></span>
<span id="cb4-25"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> NamedEntity(BaseModel):</span>
<span id="cb4-26">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""A named entity result."""</span></span>
<span id="cb4-27"></span>
<span id="cb4-28">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> convert_str_to_named_entity_type(v: <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> NamedEntityType) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> NamedEntityType:</span>
<span id="cb4-29">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""Ensure entity type is a valid enum."""</span></span>
<span id="cb4-30">        <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>(v, NamedEntityType):</span>
<span id="cb4-31">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> v</span>
<span id="cb4-32">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span>:</span>
<span id="cb4-33">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">try</span>:</span>
<span id="cb4-34">                match, score <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> fuzzy_process.extractOne(v.upper(), [e.value <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> e <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;">list</span>(NamedEntityType)])</span>
<span id="cb4-35">                <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> NamedEntityType(match) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> score <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;">60</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span> NamedEntityType.OTHER</span>
<span id="cb4-36">            <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;">ValueError</span>:</span>
<span id="cb4-37">                <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> NamedEntityType.OTHER</span>
<span id="cb4-38"></span>
<span id="cb4-39">    entity_type: Annotated[<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>, BeforeValidator(convert_str_to_named_entity_type)]</span>
<span id="cb4-40">    entity_mention: <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> Field(..., description<span 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 named entity recognized."</span>)</span>
<span id="cb4-41"></span>
<span id="cb4-42"></span>
<span id="cb4-43"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> DocumentNERTask(BaseModel):</span>
<span id="cb4-44">    named_entities: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>[NamedEntity]</span></code></pre></div>
<p>This improves those cases where, for example, the LLM wants to define the entity type as “ORGANIZATION” but it is defined in the <code>Enum</code> as “ORG”.</p>
<p>Another option potentially worth exploring is to use the <code>llm_validator</code> function to make a call out to the LLM when exceptions happen and prompt it to coerce the value into something in the <code>Enum</code>. This could hike up your costs a bit but I imagine using a cheap model like GPT-3.5-Turbo could do the job just fine, and would likely you give an addtional robustness in quality results.</p>
</section>
<section id="conclusion" class="level2">
<h2 class="anchored" data-anchor-id="conclusion">Conclusion</h2>
<p>That’s it.</p>
<p>If you found this helpful and/or have suggestions on how to improve the use of <code>Enum</code>s in Instructor, lmk in the comments below or on <a href="https://x.com/waydegilliam" target="_blank">X</a>. Until then, time to enjoy some football and see if Brazil can make it into the semis.</p>


</section>

 ]]></description>
  <category>LLMs</category>
  <category>pydantic</category>
  <category>Instructor</category>
  <guid>https://ohmeow.com/posts/2024-07-06-llms-and-enums.html</guid>
  <pubDate>Sat, 06 Jul 2024 07:00:00 GMT</pubDate>
  <media:content url="https://ohmeow.com/posts/images/blog-20240706/header.png" medium="image" type="image/png" height="82" width="144"/>
</item>
<item>
  <title>LLM Workshop #1 - How to take a course that never ends</title>
  <dc:creator>Wayde Gilliam</dc:creator>
  <link>https://ohmeow.com/posts/2024-07-03-llm-workshop-intro.html</link>
  <description><![CDATA[ 




<section id="mastering-llms-a-conference-for-developers-data-scientists" class="level2">
<h2 class="anchored" data-anchor-id="mastering-llms-a-conference-for-developers-data-scientists">Mastering LLMs: A Conference For Developers &amp; Data Scientists</h2>
<div>
<p><img src="https://ohmeow.com/posts/images/blog-20240727/hamel-eval-flow.png" alt="LLM Workshop" style="float:right;border-radius: 15px;height:250px;width:auto;"></p>
<p>These days, it goes by many names, but officially the “workshop” is known simply as <a href="https://maven.com/parlance-labs/fine-tuning" target="_blank">“Mastering LLMs: A Conference For Developers &amp; Data Scientists”</a>.</p>
<p>Initially envisioned as a four-week course, it quickly evolved into something much more dynamic — a conference brimming with talks, office hours, and a wealth of insights shared on their Discord. Participants also received a generous amount of credits from various companies in the field to experiment on their own.</p>
<p>Although the event has technically concluded, I’m remain only 95% convinced that it’s truly over (a new “30 minute” 90 minute session could pop-up in my calendar at any moment).</p>
<p>At it’s core, the event is about equipping participants with the necessary tools and techniques to create a comprehensive pipeline for building generative NLP solutions, from dataset curation to deployment. Its spans 4 core workshops, 20 conference sessions, 6 office hours, and a bunch of async discussions via discord. If that sounds like a lot of content, good … because it is! My friend Sanyam summed my feelings in week 3 with this message I got from him on Discord …</p>
<blockquote class="blockquote">
<p>Are you feeling overwhelemed by the course as well? I feel this is fastai by at 1000x speed … but for real world, energy. It’s impossible for me to just keep up with the lectures, barely getting time to play with examples or run some code.</p>
</blockquote>
<p>So yah, to start, I want to share my thoughts on the major lessons learned and help folks figure out how to navigate and succeed in course/workshop/whatever of this scale. This is an opinionated take from someone who’s been around awhile, but I hope an experienced take worth consideration.</p>
</div>
</section>
<section id="how-to-take-this-course" class="level2">
<h2 class="anchored" data-anchor-id="how-to-take-this-course">How to take this course</h2>
<p>Here I want to share 4 tips to getting the most of this course.</p>
<div class="callout callout-style-default callout-tip 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">
Tip 1: Focus Your Learning
</div>
</div>
<div class="callout-body-container callout-body">
<p>My advice is to <strong>definitely watch the main conference workshops … TWICE</strong>.</p>
<p>This is how I do the fastai courses as well. I watch the lecture more as an active participant the first time, watching it live if possible, asking (and answering question), jotting down thoughts or other parts of the lecture I want to dive deeper into later. On my second watch, I usually have a “printed” version of the session notes/slides on my iPad that I annotate as I got through it again a bit slower. I usually do this 2nd watch a few days after to give my brain time to rest and reflect.</p>
<p>From there I suggest <strong>following the same approach with any conference talks you’re interested in … but only doing that 2nd watch for those you care about</strong>. Honestly, I still haven’t watched all of them myself and have been content to really spend time with those most close to the things I’m working with IRL and/or I want to learn (e.g., I’ve watched Ankur Goyal’s talk on using BrainTrust about 3-4 times because I like the tool and I want to explore it as something I use in both my personal and professional life).</p>
<p>As <strong>for the office hours, I’ve tried to attend as many as I could and ask a lot of questions</strong>. I don’t watch these a 2nd time and I don’t do a lot of detailed note taking except where something really lands as important or useful to me personally (like an answer to one of the really great questions that come up in these).</p>
<p>Time is precious. One of the keys to succeeding in this course and walking away without a mental breakdown is to manage it by spending your time on the things that matter to you.</p>
</div>
</div>
<div class="callout callout-style-default callout-tip 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">
Tip 2: The Discord Is The Alpha
</div>
</div>
<div class="callout-body-container callout-body">
<p>The like $3,500 in free credits is great, but for me, the real alpha of this course … and the real bang for your buck … is in the Discord. <strong>Spend a lot of time there!</strong></p>
<p>You are literally able to interact with other practitioners and course instructors who charge serveral hundered dollars an hour as consultants for the same kind of expertise and guidance you get for your one-time payment of $500. For me, this puts the value of the course into the tens of thousands easily, making my call to signup easily one of the best decision I’ve made in 2024.</p>
<p>Again, there is A LOT of content in the discord so my recommendation is to <strong>focus on the channels dedicated to things you care about</strong> vs.&nbsp;trying to read it all. Some of my favorites include:</p>
<ul>
<li><p>Workshops (all of them)</p></li>
<li><p>Debugging Help / training-runs (lots of learning from folks like Zach Mueller and others via real fine-tuning attempts; very helpful)</p></li>
<li><p>Debugging Help / axolotl</p></li>
<li><p>Talks / kylecorbitt_prompt_to_model</p></li>
<li><p>Talks / ankurgoyal_textsql_llms</p></li>
<li><p>Talks / jason_improving_rag</p></li>
<li><p>Talks / clavie_beyond_rag_basics (deserved way more than 30 minutes, 😁)</p></li>
<li><p>Talks / pawel-function-calling</p></li>
<li><p>Talks / whitaker_napkin_math</p></li>
<li><p>Office Hours / charles-modal</p></li>
<li><p>Office Hours / replicate</p></li>
</ul>
<p>Again, time is precious. Since my interests were with evals, structured outputs, RAG, and deployment … the above were the channels I spent most of my time in. Believe it or not, there are a few channels that remain unexplored for the time being (so much great stuff).</p>
</div>
</div>
<div class="callout callout-style-default callout-tip 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">
Tip 3: How time works in this course
</div>
</div>
<div class="callout-body-container callout-body">
<p>Time works different in the workshop. For example, a “30 minute” session is really about 75 minutes, a “45 minute” session about 90 minutes, and any of the “2-hour” workshop will likely go an additonal hour.</p>
<p>Now that this course is “over”, this may not be that big of a deal. But, when I was blocking out time in my calendar these were the heuristics I followed. Think on this when that next calendar invite pops up or you end up taking some similar course in the future.</p>
</div>
</div>
<div class="callout callout-style-default callout-tip 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">
Tip 4: Build something
</div>
</div>
<div class="callout-body-container callout-body">
<p>If you can do only one thing … build something and blog it!</p>
<p>This is really the golden rule of course like the LLM Workshop and fast.ai. If you really want to gain some mastery in the subject, you have to build something and explain it to others.</p>
<p>A great example of this in practice can be found by following <a href="https://mlops.systems/" target="_blank">Alex Strick van Linschoten’s</a> blog posts regarding his course project. Exceptional content and an example of what it looks like to succeed in a course like this. Its a win-win for Alex and the community at large.</p>
<p>This is the direction I’ll be going in future posts in this series.</p>
</div>
</div>
</section>
<section id="key-takeaways" class="level2">
<h2 class="anchored" data-anchor-id="key-takeaways">Key Takeaways</h2>
<p>I’ve learned a lot to say the least. Below are some of the key takeways I’ve taken away from the course that I hope will aid your navigation and success with it as well.</p>
<section id="trust-fucking-no-one-tfno" class="level3">
<h3 class="anchored" data-anchor-id="trust-fucking-no-one-tfno">Trust fucking no one (TFNO)</h3>
<div style="clear:both;">
<p><img src="https://ohmeow.com/posts/images/blog-20240603/charles-tfno.png" alt="TFNO" style="float:left;border-radius: 15px;margin:10px;height:150px;width:auto;"></p>
<p><strong>“Trust fucking no one!”</strong> - Charles Frye (also winner of quote of the conference)</p>
<p>Indeed, when it comes to fine-tuning … “If you’re not nervous, you don’t understand.”</p>
<p>If you weren’t scared as hell about getting your <a href="https://hamel.dev/blog/posts/prompt/" target="_blank">prompt templates to match up at both training and inference time</a> already, be prepared to be terrified. And if you’re not carefully looking at examples of your fleshed out prompts during both phases, prepare to get F’d.</p>
<blockquote class="blockquote">
<p><img src="https://ohmeow.com/posts/images/blog-20240603/hamel-icon.png" alt="Hamel" style="border-radius:30px;width:auto;height:25px;"> 99% of errors happen with the template</p>
</blockquote>
</div>
</section>
<section id="look-at-your-data" class="level3">
<h3 class="anchored" data-anchor-id="look-at-your-data">Look at your data</h3>
<p>You need to spend time looking at your data to understand what is going on, gain intuiton on how to improve things, and actually make things better. Automated metrics can only take you so far in the generative game and even high-quality LLMs as judges will fail. Look at your data a lot!</p>
</section>
<section id="build-an-evals-first-development-mindset" class="level3">
<h3 class="anchored" data-anchor-id="build-an-evals-first-development-mindset">Build an Evals-First Development Mindset</h3>
<p>Evals are a big part of this course and likely one of the most ignore aspects in building generative solutions where the normal course seems to be for folks to just slap a react app on top of a fastapi backend that makes calls out to gpt-4 with a prompt and RAG mechanism that seems to work. But how can you tell if it is really “working”? How can you tell it is still working and working for others besides yourself? How can you tell changes you make to your model, prompt, RAG, whatever is having a positive or negative effect?</p>
<p>The answer is you can’t without good evals, and good evals are something built up over time and a project in and of themselves. They aren’t static. Having a good system to build and continuously improve on them is one of the most important ways you can ensure you are delivering a quality AI solution.</p>
<p>Also, don’t forget to include human experts where possible!</p>
</section>
<section id="prove-you-need-to-finetune" class="level3">
<h3 class="anchored" data-anchor-id="prove-you-need-to-finetune">Prove You Need to Finetune</h3>
<blockquote class="blockquote">
<p><img src="https://ohmeow.com/posts/images/blog-20240603/hamel-icon.png" alt="Hamel" style="border-radius:30px;width:auto;height:25px;"> Try not to finetune first … you need to prove to yoruefl that you should finetune [using] some minimal evaluation system and you hit a wall and can’t make progress by just prompting</p>
</blockquote>
<p>Good use cases for finetuning:</p>
<ol type="1">
<li>Owning your own model</li>
<li>Data privacy</li>
<li>Domain specific things that models like GPT and Claude haven’t been trained on</li>
</ol>
<p>The narrower the domain/problem … the better.</p>
</section>
<section id="dont-try-and-build-a-general-purpose-chatbot" class="level3">
<h3 class="anchored" data-anchor-id="dont-try-and-build-a-general-purpose-chatbot">Don’t Try and Build a General Purpose Chatbot</h3>
<p>Being asked to build a chatbot is a smell because the surface area is very large and unscoped, making it difficult to make progress on. We simply do not have the time, money, data, and resources companies like OpenAI and Anthropic have to make a chatbot that can perform as well as theirs in general … and no one wants to use an AltaVista like chatbot when you got Google.</p>
<p>I’m watching this happen in real-time at work and its not pretty.</p>
</section>
<section id="use-your-eval-pipeline-to-curate-training-datasets" class="level3">
<h3 class="anchored" data-anchor-id="use-your-eval-pipeline-to-curate-training-datasets">Use your Eval Pipeline to Curate Training Datasets</h3>
<p>In the real-world, we can’t just start with pre-processed dataset from Hugging Face. In the real-world, we’ll often have to find creative and out of the box ways to curate our own dataset to evaluating our AI systems. Having a good evals framework is how you get this done, especially at the beginning where you probably don’t have access to many, if any, human experts providing examples for you to use. Starting with a good LLM from OpenAI or Anthropic for example, along with a growing set of scoring functions and some time of your own for review, is a great way to curate an initial training dataset you can build on going forward.</p>
<p>Breakdown use cases into specific examples, log the traces, and use them in your finetunes.</p>
<p><strong>What LLMs should I use in generating synthetic data?</strong></p>
<blockquote class="blockquote">
<p><img src="https://ohmeow.com/posts/images/blog-20240603/hamel-icon.png" alt="Hamel" style="border-radius:30px;width:auto;height:25px;"> I like mistral large … use the most powerful model you can”</p>
</blockquote>
</section>
<section id="evallogging-tools-i-like-so-far" class="level3">
<h3 class="anchored" data-anchor-id="evallogging-tools-i-like-so-far">Eval/Logging Tools I like (so far)</h3>
<p>I’m going to give BrainTrust and LangSmith a go. I’m most familiar with the later, but I really liked the UX and explict-ness of running evals with BrainTrust.</p>
</section>
<section id="minimize-friction" class="level3">
<h3 class="anchored" data-anchor-id="minimize-friction">Minimize Friction</h3>
<p>Just like analysis paralysis, there’s an eval paralysis where you might be so consumed on having a fully fleshed out eval pipeline or the feeling you have to pick out the right tooling that you never really get started. Don’t let that happen. Start with simple assertions, use the high-quality LLMs, use notebooks … do whatever you can to get a quality dataset you can get going with quickly</p>
</section>
<section id="get-up-and-running-quick" class="level3">
<h3 class="anchored" data-anchor-id="get-up-and-running-quick">Get Up and Running Quick</h3>
<p>No one wants to deploy a training job with 100k samples for fine-tuning a Llama3 70B only to find out that it fails after a day or so of running because you misspelled your HuggingFace username. Here’s my approach to quickly iterate and verify your finetuning strategy will work from beginning to end (learned from my time with the fast.ai course btw)</p>
<blockquote class="blockquote">
<p><img src="https://ohmeow.com/posts/images/blog-20240603/wayde-icon.png" alt="Wayde" style="border-radius:10px;width:auto;height:25px;"> Use a subset of my dataset to train a model. Verify my inputs/targets look right, training works end-to-end, that my metrics are being logged to wanb correctly, and that my artifacts can be used and optionally uploaded to HF. I make my sample really small … like maybe 300-500 examples so I can iterate fast here. Once my setup is golden and everything is checked into github, login into Jarvis, grab yourself some big GPUS, clone your repo, install any libraries you need to, and train on your full dataset. Pour yourself a glass of a good scotch or whiskey.</p>
</blockquote>
<p>Try to get it down to 15-30 mins max to verify your training works from start to finish. If you are using axolotl, take set <code>max_steps</code> to something small like 500.</p>
<p><strong>How much data do you need?</strong></p>
<p>I’ve heard as little as 50-100 examples can get you far.</p>
</section>
<section id="prefer-cloud-over-local-training" class="level3">
<h3 class="anchored" data-anchor-id="prefer-cloud-over-local-training">Prefer Cloud over Local Training</h3>
<p>I had a hell of a time getting CUDA installed and getting things to run on my 2x3090s. I don’t regret it, in fact, I get some sick satisfaction out of it. There’s nothing like launching a training job on my two blower GPUs as my wife sits down to watch an episode of Bridgerton on the TV downstairs (under which sits my DL rig).</p>
<p>However, I see lots of students struggling so hard on trying to get things working locally that they become beaten down before getting to the real meat of things. So my 2 cents for most folks in genera …</p>
<blockquote class="blockquote">
<p><img src="https://ohmeow.com/posts/images/blog-20240603/wayde-icon.png" alt="Wayde" style="border-radius:10px;width:auto;height:25px;"> Its probably better to use a cloud provider like <a href="https://jarvislabs.ai/" target="_blank">jarvis</a> or <a href="https://modal.com/" target="_blank">modal</a> rather than battling with your local rig. Of course, I didn’t follow my own advice because I’m OCD about things like this and can’t let things go until I understand the whys, hows, and resolutions for problems like this.</p>
</blockquote>
<p>I’ve had excellent experience working with both of these platforms, along with superb support and help from folks like Vishnu (founder at Jarvis), and Charles (AI engineer at Modal Labs and speaker at every AI conference).</p>
<p>Also, use Linux. I see so many folks trying to get things working on Windows or their slick M3 Macbook pro and that is just a pathway to misery that will make you question whether you want to even be in the ML field. Don’t do it. Linux FTW</p>
</section>
<section id="prefer-the-base-model-over-the-instruct-version-when-fine-tuning" class="level3">
<h3 class="anchored" data-anchor-id="prefer-the-base-model-over-the-instruct-version-when-fine-tuning">Prefer the Base model over the Instruct Version When Fine-tuning</h3>
<p>Most LLMs come in two flavors, base and instruct. The former focuses simply on next-word prediction tasks whereas the later is focused on conversation. In general, the recommendation in the course is to use the base version to build on top of as it gives you complete control of the prompt template without having to worry about following the “instruct” template of whatever model architecture you choose to the tee. Also, as these instruct tempaltes vary widely from one LLM to another, its seems using the base model make it easier to run fine-tunes against a nubmer of LLMs without a lot of code gymnastics.</p>
<p>Insturction models have been finetuned for conversation … something you want to chat with.</p>
<p>Start with the basse model where possible … with the smallest model possible (e.g, the 7/8B parameter range)</p>
</section>
<section id="finetuning-examples-should-mimic-what-your-llm-will-see-in-production" class="level3">
<h3 class="anchored" data-anchor-id="finetuning-examples-should-mimic-what-your-llm-will-see-in-production">Finetuning Examples Should Mimic what your LLM will see in production</h3>
<p>If RAG is being used with your properitery LLMs, include it in your training examples for use in finetuning.</p>
</section>
<section id="for-structured-output-use-instructor-or-outlines" class="level3">
<h3 class="anchored" data-anchor-id="for-structured-output-use-instructor-or-outlines">For Structured Output, Use Instructor or Outlines</h3>
<blockquote class="blockquote">
<p><img src="https://ohmeow.com/posts/images/blog-20240603/hamel-icon.png" alt="Hamel" style="border-radius:30px;width:auto;height:25px;"> For open models you should use outlines. for closed models APIs you should use instructor.</p>
</blockquote>
<blockquote class="blockquote">
<p><img src="https://ohmeow.com/posts/images/blog-20240603/hamel-icon.png" alt="Hamel" style="border-radius:30px;width:auto;height:25px;"> Instructor uses prompting and retries to achieve the desired output (and with openai it will prompt intelligently via the function schema definitions). Outlines clamp down the model predictions to only alllow permissible tokens according to your grammar. Outlines is going to have much stronger guarantees that it will work. No retries are even necessary. If outlines is compatible with your model (you have access to the forward pass because you own the model) you should use outlines</p>
</blockquote>
</section>
</section>
<section id="next-steps" class="level2">
<h2 class="anchored" data-anchor-id="next-steps">Next Steps</h2>
<p>Build something.</p>
<p>Following <a href="https://github.com/parlance-labs/ftcourse" target="_blank">Hamel’s course project repo</a> as a guide, I’m going to explore improving a ML pipeline I built for work that allows users to upload a collection of survey comments, interview answers, etc… and have a variety of NLP analysis performed on the documents collectively and individually (eg., translation, sentiment, summarization, NER, and thematic analysis). The data and responses are styled in a way familiar to faculty, staff, and students in higher ed.</p>
<p>The current system makes a call out to gpt-4 for every document and for every collection of related documents to perform each task. It can get pricey and can take a long time depending on the number of documents being processed. I did this because I couldn’t get reliable results from asking the LLM to perform a number of tasks, whether the document/s where short or long.</p>
<p>For this course project, I’m going to start from the beginning and try to improve things by:</p>
<ol type="1">
<li><p>Curating a dataset from both generated data and local traces I have from the existing pipeline</p></li>
<li><p>Follow and “eval first” development structure, so I can evaluate the proprietary LLMs (e.g., gpt-4, gpt-4o, gpt-3.5-turbo, etc..) I’m using right now.</p></li>
<li><p>Use tool calling and more complex pydantic models to reduce the number of calls I need to make and lower costs.</p></li>
<li><p>Finetune a variety of smaller models on a curated datset to see if I can improve the quality of my predictions while also lowering costs and latency even more.</p></li>
</ol>
<p>If folks have any suggestions or ideas to improve this approach, please let me know in the comments or on twitter. I’d especially love to hear from people who have gone down a similar path and what worked (or didn’t) for them.</p>


</section>

 ]]></description>
  <category>NLP</category>
  <category>LLMS</category>
  <category>datasets</category>
  <category>learning</category>
  <category>projects</category>
  <guid>https://ohmeow.com/posts/2024-07-03-llm-workshop-intro.html</guid>
  <pubDate>Wed, 03 Jul 2024 07:00:00 GMT</pubDate>
  <media:content url="https://ohmeow.com/posts/images/blog-20240603/header.png" medium="image" type="image/png" height="68" width="144"/>
</item>
<item>
  <title>A Journey Through Fastbook (AJTFB) - Chapter 9: Tabular Modeling</title>
  <dc:creator>Wayde Gilliam</dc:creator>
  <link>https://ohmeow.com/posts/2022-04-25-ajtfb-chapter-9.html</link>
  <description><![CDATA[ 




<p>Other posts in this series:<br>
<a href="../posts/2020-11-06-ajtfb-chapter-1.html">A Journey Through Fastbook (AJTFB) - Chapter 1</a><br>
<a href="../posts/2020-11-16-ajtfb-chapter-2.html">A Journey Through Fastbook (AJTFB) - Chapter 2</a><br>
<a href="../posts/2020-11-22-ajtfb-chapter-3.html">A Journey Through Fastbook (AJTFB) - Chapter 3</a><br>
<a href="../posts/2021-05-23-ajtfb-chapter-4.html">A Journey Through Fastbook (AJTFB) - Chapter 4</a><br>
<a href="../posts/2021-06-03-ajtfb-chapter-5.html">A Journey Through Fastbook (AJTFB) - Chapter 5</a><br>
<a href="../posts/2021-06-10-ajtfb-chapter-6-multilabel.html">A Journey Through Fastbook (AJTFB) - Chapter 6a</a><br>
<a href="../posts/2022-02-09-ajtfb-chapter-6-regression.html">A Journey Through Fastbook (AJTFB) - Chapter 6b</a><br>
<a href="../posts/2022-03-28-ajtfb-chapter-7.html">A Journey Through Fastbook (AJTFB) - Chapter 7</a><br>
<a href="../posts/2022-03-31-ajtfb-chapter-8.html">A Journey Through Fastbook (AJTFB) - Chapter 8</a></p>
<section id="tabular-modeling" class="level2">
<h2 class="anchored" data-anchor-id="tabular-modeling">Tabular Modeling</h2>
<p><strong>What is it?</strong></p>
<p>“Tabular modeling takes data in the form of a table (like a spreadsheet or CSV). The objective is to predict the value of one column based on the values in the other columns.” Tabular data is also called <strong>“structured data”</strong> while <strong>“unstructured data”</strong> represents things like text, images, audio, etc…</p>
<p><strong>Why is it important?</strong></p>
<p>Though it is reported that <a href="https://www.cio.com/article/220347/ai-unleashes-the-power-of-unstructured-data.html">80-90% of data is unstructured</a> (think images, text, audio), ironically, it appears that the vast majority of “real world” machine learning is concerened with tabular/structured data.</p>
<blockquote class="twitter-tweet blockquote" data-theme="dark">
<p lang="en" dir="ltr">
If you are just starting out with Data Science you should know that still the vast majority of DS problems in the industry concern structured/tabular data. This is what you should focus on in order to make a professional inroad. <br><br>1/3
</p>
— Bojan Tunguz (<span class="citation" data-cites="tunguz">@tunguz</span>) <a href="https://twitter.com/tunguz/status/1496480602409017351?ref_src=twsrc%5Etfw">February 23, 2022</a>
</blockquote>
<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
<div class="callout callout-style-default 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">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>And here’s the good news … “recent studies have shown that the vast majority of datasets can be be modeled with just two methods.”</p>
</div>
</div>
<p><strong>What are they?</strong></p>
<ol type="1">
<li><p>For structured data, <strong>ensembles of decision trees</strong> (e.g., random forests and gradient boosting machines like XGBoost).</p></li>
<li><p>For unstructured data, <strong>multilayered neural networks learned with SGD.</strong></p></li>
</ol>
<div class="callout callout-style-default 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">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>“… ensembles of decision trees <strong>tend to train faster</strong>, are often <strong>easier to interpret</strong>, <strong>do not require special GPU hardware</strong> for inference at scale, and <strong>often require less hyperparameter tuning</strong>.</p>
</div>
</div>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>Since a “critical step of <strong>interpreting</strong> a model of tabular data is significantly easier for decesion tree ensembles … <strong><em>ensembles of decision trees are our first approach for analyzing a new tabular dataset</em></strong>”</p>
</div>
</div>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>Neural networks will considered when “there are some high-cardinality categorical variables” or there are columns with unstructured data. A example of a high “<strong>cardinality</strong>” (e.g., the number of discrete levels representing the categories) would be something like zip code.</p>
</div>
</div>
<p>See pages 282-284 for more discussion on the pros/cons of decision trees and neural networks for tabular data.</p>
</section>
<section id="categorical-embeddings" class="level2">
<h2 class="anchored" data-anchor-id="categorical-embeddings">Categorical Embeddings</h2>
<p><strong>Continuous v. Categorical</strong></p>
<p><strong>Continuous variables</strong> “contain a real numbers that be fed into a model directly and are meaningful in and out of themselves. Examples include”age” and “price”.</p>
<p><strong>Categorical variables</strong> “contain a number of discrete levels, such as ‘movie ID,’ for which addition and multiplication don’t have any meaning <em>(even if they’re stored as numbers)</em>. Other examples include dates, columns indicating”sex”, “gender”, “department”, etc…</p>
<p><strong>How do we represent “categorical” data?</strong></p>
<p>We learned this in chapter 8, we represent such data via <strong>entity embeddings</strong>.</p>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>Entity embeddings allow for a more complex and learnt numerical representation of a thing. This representation is likely task/data specific to one degree or another such that “Sunday” may have one representation in a task predicting how many hours people work on a day, and another for a task attempting to predict the number of trades that will be executed on each day of the week.</p>
</div>
</div>
<div class="callout callout-style-default 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">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>“… by mapping similar values close to each other in the embedding space it reveals the intrinsic properties of the categorical variable. [It] is especially <strong>useful for datasets with lots of high cardinality features.</strong>. See pp.278-282 for examples of this in relation to the <a href="https://www.kaggle.com/c/rossmann-store-sales">Rossmann sales competition on kaggle</a>.</p>
</div>
</div>
<p>Because “an embedding layer is exactly equivalent to placing an ordinary linear layer after every one-hot-encoded input layer … <strong>the embedding transforms the categorical variables into inputs that are both continuous and meaningful</strong>.”</p>
<p><img src="https://raw.githubusercontent.com/fastai/fastbook/035016fb0cc826542aef77864f36df88a5055d06/images/att_00018.png" class="img-fluid"></p>
<p>In other words …</p>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>“… we provide the model fundamentally categorical data about discrete entities … and the model learns an embedding for these entities that defines a continuous notion of distance between them.”</p>
</div>
</div>
<div class="callout callout-style-default 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">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>Given all this, “we can combine our continous embedding values with truly continuous input data [by just concatentating] the variables and feed[ing] the concatenation into our final dense layers. For an example of this, see the <a href="https://arxiv.org/abs/1606.07792">“Wide &amp; Deep Learning for Recommender Systems” paper</a>. See the below from page 282 on what that approach looks like.</p>
</div>
</div>
<p><img src="https://raw.githubusercontent.com/fastai/fastbook/035016fb0cc826542aef77864f36df88a5055d06/images/att_00019.png" class="img-fluid"></p>
</section>
<section id="imports" class="level2">
<h2 class="anchored" data-anchor-id="imports">Imports</h2>
<div id="cell-8" class="cell">
<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="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> kaggle <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> api</span>
<span id="cb1-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> dtreeviz.trees <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="cb1-3"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> fastai.tabular.<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="cb1-4"><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> Image, display_svg, SVG</span>
<span id="cb1-5"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> pandas.api.types <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> is_string_dtype, is_numeric_dtype, is_categorical_dtype</span>
<span id="cb1-6"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> sklearn.ensemble <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> RandomForestRegressor</span>
<span id="cb1-7"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> sklearn.tree <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> DecisionTreeRegressor, export_graphviz</span>
<span id="cb1-8"></span>
<span id="cb1-9">pd.options.display.max_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;">20</span></span>
<span id="cb1-10">pd.options.display.max_columns <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>
</section>
<section id="data-preparation" class="level2">
<h2 class="anchored" data-anchor-id="data-preparation">Data preparation</h2>
<section id="step-1-get-the-data" class="level3">
<h3 class="anchored" data-anchor-id="step-1-get-the-data">Step 1: Get the data</h3>
<p>We’ll be getting the data from kaggle. If you’re running on colab, check out <a href="https://www.kaggle.com/general/74235">these instructions</a> for getting setup with the kaggle API</p>
<div id="cell-11" class="cell" data-outputid="641575d1-4402-4e67-f9df-064d9ea562f9">
<div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb2-1">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;">"bluebook"</span>)</span>
<span id="cb2-2">path</span></code></pre></div>
<div class="cell-output cell-output-display" data-execution_count="5">
<pre><code>Path('bluebook')</code></pre>
</div>
</div>
<div id="cell-12" class="cell" data-outputid="fb60470f-323a-40b5-bae7-def10409d8e0">
<div class="sourceCode cell-code" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb4-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> path.exists():</span>
<span id="cb4-2">    path.mkdir()</span>
<span id="cb4-3">    api.competition_download_cli(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"bluebook-for-bulldozers"</span>, path<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>path)</span>
<span id="cb4-4">    file_extract(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;">"bluebook-for-bulldozers.zip"</span>)</span>
<span id="cb4-5"></span>
<span id="cb4-6">path.ls(file_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;">"text"</span>)</span></code></pre></div>
<div class="cell-output cell-output-stdout">
<pre><code>Downloading bluebook-for-bulldozers.zip to bluebook</code></pre>
</div>
<div class="cell-output cell-output-stderr">
<pre><code>100%|██████████| 48.4M/48.4M [00:00&lt;00:00, 112MB/s] </code></pre>
</div>
<div class="cell-output cell-output-stdout">
<pre><code></code></pre>
</div>
<div class="cell-output cell-output-display" data-execution_count="6">
<pre><code>(#7) [Path('bluebook/Machine_Appendix.csv'),Path('bluebook/Test.csv'),Path('bluebook/ValidSolution.csv'),Path('bluebook/median_benchmark.csv'),Path('bluebook/TrainAndValid.csv'),Path('bluebook/Valid.csv'),Path('bluebook/random_forest_benchmark_test.csv')]</code></pre>
</div>
</div>
</section>
<section id="step-2-eda" class="level3">
<h3 class="anchored" data-anchor-id="step-2-eda">Step 2: EDA</h3>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>“In any sort of data science work, it’s important to <em>look at your data directly</em> to make sure you <strong>understand the format, how it’s stored, what types of values it holds, etc.</strong>”</p>
</div>
</div>
<div class="callout callout-style-default callout-tip 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">
Tip
</div>
</div>
<div class="callout-body-container callout-body">
<p>“… it’s a good idea to also specify <code>low_memory=False</code> unless Pandas acutally runs out of memory.” The default = <code>True</code> (will look only at the first few rows of data to infer column datatypes).</p>
</div>
</div>
<div id="cell-14" class="cell" data-outputid="cda899b1-94e5-4ec5-bffd-46adf1344dcc">
<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">train_df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> pd.read_csv(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;">"TrainAndValid.csv"</span>, low_memory<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="cb9-2">test_df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> pd.read_csv(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;">"Test.csv"</span>, low_memory<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="cb9-3"></span>
<span id="cb9-4">train_df.columns</span></code></pre></div>
<div class="cell-output cell-output-display" data-execution_count="7">
<pre><code>Index(['SalesID', 'SalePrice', 'MachineID', 'ModelID', 'datasource',
       'auctioneerID', 'YearMade', 'MachineHoursCurrentMeter', 'UsageBand',
       'saledate', 'fiModelDesc', 'fiBaseModel', 'fiSecondaryDesc',
       'fiModelSeries', 'fiModelDescriptor', 'ProductSize',
       'fiProductClassDesc', 'state', 'ProductGroup', 'ProductGroupDesc',
       'Drive_System', 'Enclosure', 'Forks', 'Pad_Type', 'Ride_Control',
       'Stick', 'Transmission', 'Turbocharged', 'Blade_Extension',
       'Blade_Width', 'Enclosure_Type', 'Engine_Horsepower', 'Hydraulics',
       'Pushblock', 'Ripper', 'Scarifier', 'Tip_Control', 'Tire_Size',
       'Coupler', 'Coupler_System', 'Grouser_Tracks', 'Hydraulics_Flow',
       'Track_Type', 'Undercarriage_Pad_Width', 'Stick_Length', 'Thumb',
       'Pattern_Changer', 'Grouser_Type', 'Backhoe_Mounting', 'Blade_Type',
       'Travel_Controls', 'Differential_Type', 'Steering_Controls'],
      dtype='object')</code></pre>
</div>
</div>
<p><code>describe()</code> is a method that gives you some basic stats for each column.</p>
<div id="cell-16" class="cell" data-outputid="51276d8c-1dff-439c-8ab9-114b844833ec">
<div class="sourceCode cell-code" id="cb11" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb11-1">train_df.describe().T</span></code></pre></div>
<div class="cell-output cell-output-display" data-execution_count="8">
<div>


<table class="dataframe caption-top table table-sm table-striped small" data-quarto-postprocess="true" data-border="1">
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th">count</th>
<th data-quarto-table-cell-role="th">mean</th>
<th data-quarto-table-cell-role="th">std</th>
<th data-quarto-table-cell-role="th">min</th>
<th data-quarto-table-cell-role="th">25%</th>
<th data-quarto-table-cell-role="th">50%</th>
<th data-quarto-table-cell-role="th">75%</th>
<th data-quarto-table-cell-role="th">max</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td data-quarto-table-cell-role="th">SalesID</td>
<td>412698.0</td>
<td>2.011161e+06</td>
<td>1.080068e+06</td>
<td>1139246.0</td>
<td>1421897.75</td>
<td>1645852.5</td>
<td>2261012.50</td>
<td>6333349.0</td>
</tr>
<tr class="even">
<td data-quarto-table-cell-role="th">SalePrice</td>
<td>412698.0</td>
<td>3.121518e+04</td>
<td>2.314174e+04</td>
<td>4750.0</td>
<td>14500.00</td>
<td>24000.0</td>
<td>40000.00</td>
<td>142000.0</td>
</tr>
<tr class="odd">
<td data-quarto-table-cell-role="th">MachineID</td>
<td>412698.0</td>
<td>1.230061e+06</td>
<td>4.539533e+05</td>
<td>0.0</td>
<td>1088593.25</td>
<td>1284397.0</td>
<td>1478079.25</td>
<td>2486330.0</td>
</tr>
<tr class="even">
<td data-quarto-table-cell-role="th">ModelID</td>
<td>412698.0</td>
<td>6.947202e+03</td>
<td>6.280825e+03</td>
<td>28.0</td>
<td>3261.00</td>
<td>4605.0</td>
<td>8899.00</td>
<td>37198.0</td>
</tr>
<tr class="odd">
<td data-quarto-table-cell-role="th">datasource</td>
<td>412698.0</td>
<td>1.351694e+02</td>
<td>9.646749e+00</td>
<td>121.0</td>
<td>132.00</td>
<td>132.0</td>
<td>136.00</td>
<td>173.0</td>
</tr>
<tr class="even">
<td data-quarto-table-cell-role="th">auctioneerID</td>
<td>392562.0</td>
<td>6.585268e+00</td>
<td>1.715841e+01</td>
<td>0.0</td>
<td>1.00</td>
<td>2.0</td>
<td>4.00</td>
<td>99.0</td>
</tr>
<tr class="odd">
<td data-quarto-table-cell-role="th">YearMade</td>
<td>412698.0</td>
<td>1.899050e+03</td>
<td>2.921902e+02</td>
<td>1000.0</td>
<td>1985.00</td>
<td>1995.0</td>
<td>2001.00</td>
<td>2014.0</td>
</tr>
<tr class="even">
<td data-quarto-table-cell-role="th">MachineHoursCurrentMeter</td>
<td>147504.0</td>
<td>3.522988e+03</td>
<td>2.716993e+04</td>
<td>0.0</td>
<td>0.00</td>
<td>0.0</td>
<td>3209.00</td>
<td>2483300.0</td>
</tr>
</tbody>
</table>

</div>
</div>
</div>
<p><code>advanced_describe()</code> is a method I created that builds on top of the default <code>describe()</code> method to include stats on missing and unique values (which are both very helpful in terms of cleanup, understanding potential issues, and in determining the size of your embeddings for categorical data). For categorical variables with few discrete levels, this method will also show you what they are.</p>
<div id="cell-18" class="cell" data-outputid="320f820c-ab65-4bd2-b270-c6c60f18803e">
<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">advanced_describe(train_df)</span></code></pre></div>
<div class="cell-output cell-output-display" data-execution_count="9">
<div>


<table class="dataframe caption-top table table-sm table-striped small" data-quarto-postprocess="true" data-border="1">
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th">count</th>
<th data-quarto-table-cell-role="th">mean</th>
<th data-quarto-table-cell-role="th">std</th>
<th data-quarto-table-cell-role="th">min</th>
<th data-quarto-table-cell-role="th">...</th>
<th data-quarto-table-cell-role="th">unique</th>
<th data-quarto-table-cell-role="th">unique%</th>
<th data-quarto-table-cell-role="th">unique_values</th>
<th data-quarto-table-cell-role="th">dtype</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td data-quarto-table-cell-role="th">SalesID</td>
<td>412698</td>
<td>2011161.16364</td>
<td>1080067.724498</td>
<td>1139246.0</td>
<td>...</td>
<td>412698</td>
<td>7786.75</td>
<td>NaN</td>
<td>int64</td>
</tr>
<tr class="even">
<td data-quarto-table-cell-role="th">SalePrice</td>
<td>412698</td>
<td>31215.181414</td>
<td>23141.743695</td>
<td>4750.0</td>
<td>...</td>
<td>954</td>
<td>18.00</td>
<td>NaN</td>
<td>float64</td>
</tr>
<tr class="odd">
<td data-quarto-table-cell-role="th">MachineID</td>
<td>412698</td>
<td>1230061.436646</td>
<td>453953.25795</td>
<td>0.0</td>
<td>...</td>
<td>348808</td>
<td>6581.28</td>
<td>NaN</td>
<td>int64</td>
</tr>
<tr class="even">
<td data-quarto-table-cell-role="th">ModelID</td>
<td>412698</td>
<td>6947.201828</td>
<td>6280.824982</td>
<td>28.0</td>
<td>...</td>
<td>5281</td>
<td>99.64</td>
<td>NaN</td>
<td>int64</td>
</tr>
<tr class="odd">
<td data-quarto-table-cell-role="th">datasource</td>
<td>412698</td>
<td>135.169361</td>
<td>9.646749</td>
<td>121.0</td>
<td>...</td>
<td>6</td>
<td>0.11</td>
<td>[121, 132, 136, 149, 172, 173]</td>
<td>int64</td>
</tr>
<tr class="even">
<td data-quarto-table-cell-role="th">...</td>
<td>...</td>
<td>...</td>
<td>...</td>
<td>...</td>
<td>...</td>
<td>...</td>
<td>...</td>
<td>...</td>
<td>...</td>
</tr>
<tr class="odd">
<td data-quarto-table-cell-role="th">Backhoe_Mounting</td>
<td>80712</td>
<td>NaN</td>
<td>NaN</td>
<td>NaN</td>
<td>...</td>
<td>3</td>
<td>0.06</td>
<td>[nan, None or Unspecified, Yes]</td>
<td>object</td>
</tr>
<tr class="even">
<td data-quarto-table-cell-role="th">Blade_Type</td>
<td>81875</td>
<td>NaN</td>
<td>NaN</td>
<td>NaN</td>
<td>...</td>
<td>11</td>
<td>0.21</td>
<td>[nan, PAT, None or Unspecified, Semi U, VPAT, Straight, Angle, No, U, Landfill, Coal]</td>
<td>object</td>
</tr>
<tr class="odd">
<td data-quarto-table-cell-role="th">Travel_Controls</td>
<td>81877</td>
<td>NaN</td>
<td>NaN</td>
<td>NaN</td>
<td>...</td>
<td>8</td>
<td>0.15</td>
<td>[nan, None or Unspecified, Differential Steer, Lever, Finger Tip, 2 Pedal, Pedal, 1 Speed]</td>
<td>object</td>
</tr>
<tr class="even">
<td data-quarto-table-cell-role="th">Differential_Type</td>
<td>71564</td>
<td>NaN</td>
<td>NaN</td>
<td>NaN</td>
<td>...</td>
<td>5</td>
<td>0.09</td>
<td>[Standard, nan, Limited Slip, No Spin, Locking]</td>
<td>object</td>
</tr>
<tr class="odd">
<td data-quarto-table-cell-role="th">Steering_Controls</td>
<td>71522</td>
<td>NaN</td>
<td>NaN</td>
<td>NaN</td>
<td>...</td>
<td>6</td>
<td>0.11</td>
<td>[Conventional, nan, Command Control, Four Wheel Standard, Wheel, No]</td>
<td>object</td>
</tr>
</tbody>
</table>

<p>53 rows × 14 columns</p>
</div>
</div>
</div>
</section>
<section id="step-3-preprocessing" class="level3">
<h3 class="anchored" data-anchor-id="step-3-preprocessing">Step 3: Preprocessing</h3>
<section id="handling-ordinal-columns" class="level4">
<h4 class="anchored" data-anchor-id="handling-ordinal-columns">Handling Ordinal columns</h4>
<div class="callout callout-style-default callout-tip 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">
Tip
</div>
</div>
<div class="callout-body-container callout-body">
<p>“… a good next step is to handle <em>ordinal columns</em> … columns containing strings or similar, **but where those strings have a natural ordering.”</p>
</div>
</div>
<div id="cell-21" class="cell" data-outputid="c17e6a8d-86cd-410c-dc5e-eb871db375f6">
<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">train_df.ProductSize.unique()</span></code></pre></div>
<div class="cell-output cell-output-display" data-execution_count="10">
<pre><code>array([nan, 'Medium', 'Small', 'Large / Medium', 'Mini', 'Large',
       'Compact'], dtype=object)</code></pre>
</div>
</div>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>“tell Pandas about a suitable ordering of these levels”</p>
</div>
</div>
<div id="cell-23" class="cell" data-outputid="c4f459bb-7ea8-4bbd-d4c3-40c744cea5f2">
<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">sizes <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Large"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Large / Medium"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Medium"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Small"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Mini"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Compact"</span>]</span>
<span id="cb15-2">train_df.ProductSize <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> train_df.ProductSize.astype(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"category"</span>)</span>
<span id="cb15-3">train_df.ProductSize <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> train_df.ProductSize.cat.set_categories(</span>
<span id="cb15-4">    sizes, ordered<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="cb15-5">)  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># note: "inplace=True" is depreciated as of 1.30</span></span>
<span id="cb15-6">train_df.ProductSize.unique()</span></code></pre></div>
<div class="cell-output cell-output-display" data-execution_count="11">
<pre><code>[NaN, 'Medium', 'Small', 'Large / Medium', 'Mini', 'Large', 'Compact']
Categories (6, object): ['Large' &lt; 'Large / Medium' &lt; 'Medium' &lt; 'Small' &lt; 'Mini' &lt; 'Compact']</code></pre>
</div>
</div>
</section>
<section id="handling-your-dependent-variables" class="level4">
<h4 class="anchored" data-anchor-id="handling-your-dependent-variables">Handling Your Dependent Variable(s)</h4>
<div class="callout callout-style-default callout-tip 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">
Tip
</div>
</div>
<div class="callout-body-container callout-body">
<p>Update the dependent variable to suit your objective.</p>
</div>
</div>
<p>“You should think carefully about which metric, or set of metrics, actually measures the notion of model quality that matters to you … in this case, Kaggle tells us [our measure is] root mean squared log error (RMLSE)” and because of this we need to make our target the log of the price “so that the <code>m_rmse</code> of that value will give us what we ultimately need.”</p>
<div id="cell-25" class="cell">
<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">dep_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;">"SalePrice"</span></span>
<span id="cb17-2">train_df[dep_var] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.log(train_df[dep_var])</span></code></pre></div>
</div>
</section>
<section id="handling-dates" class="level4">
<h4 class="anchored" data-anchor-id="handling-dates">Handling Dates</h4>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>“… enrich our representation of dates”</p>
</div>
</div>
<p>Dates are “different from most ordinal values in that some dates are qualitatively different from others in a way that is often relevant to the systems we are modeling.” As such, we want the model to know if whether the day is a holiday, or part of the weekend, or in a certain month, etc… is important. To do this, “we **replace every date column with a set of date metadata columns, such as holiday, day of week, and month” = categorical data that might be very useful!</p>
<p>Can use fastai’s <code>add_datepart()</code> function to do this.</p>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>Apply same preprocessing to both your train/evaluation <strong><em>and</em></strong> test sets!</p>
</div>
</div>
<div id="cell-27" class="cell">
<div class="sourceCode cell-code" id="cb18" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb18-1">train_df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> add_datepart(train_df, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"saledate"</span>)</span>
<span id="cb18-2">test_df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> add_datepart(test_df, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"saledate"</span>)</span></code></pre></div>
</div>
<div id="cell-28" class="cell" data-outputid="1b9b7e5a-964b-49e5-a6f3-a0e777b443cc">
<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">[col <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> col <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> train_df.columns <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> col.startswith(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"sale"</span>)]</span></code></pre></div>
<div class="cell-output cell-output-display" data-execution_count="14">
<pre><code>['saleYear',
 'saleMonth',
 'saleWeek',
 'saleDay',
 'saleDayofweek',
 'saleDayofyear',
 'saleIs_month_end',
 'saleIs_month_start',
 'saleIs_quarter_end',
 'saleIs_quarter_start',
 'saleIs_year_end',
 'saleIs_year_start',
 'saleElapsed']</code></pre>
</div>
</div>
</section>
<section id="handling-strings-and-missing-data" class="level4">
<h4 class="anchored" data-anchor-id="handling-strings-and-missing-data">Handling Strings and Missing Data</h4>
<p>For this we can use fastai’s <code>TabularPandas</code> class (allows us to apply <code>TabularProc</code> transforms to the DataFrame it wraps to do things like fill missing values, make columns categorical, etc…).</p>
<p><strong><code>Categorify</code></strong>: “a <code>TabularProc</code> that replaces a column with a numeric categorical column”</p>
<p><strong><code>FillMissing</code></strong>: “a <code>TabularProc</code> that replaces missing values with <strong>the median</strong> of the column, and **creates a new Boolean column that is set to <code>True</code> for any row where the value was missing<code>.  You can change this fill strategy via the</code>fill_strategy` argument.</p>
<div id="cell-31" class="cell">
<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">procs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [Categorify, FillMissing]</span></code></pre></div>
</div>
</section>
</section>
</section>
<section id="creating-our-tabularpandas" class="level2">
<h2 class="anchored" data-anchor-id="creating-our-tabularpandas">Creating our <code>TabularPandas</code></h2>
<section id="step-1-define-our-continuous-and-categorical-columns" class="level3">
<h3 class="anchored" data-anchor-id="step-1-define-our-continuous-and-categorical-columns">Step 1: Define our continuous and categorical columns</h3>
<p>We need to tell <code>TabularPandas</code> what columns are continumous and which are categorical, and we can use fastai’s <code>cont_cat_split</code> to do that like so …</p>
<div id="cell-34" class="cell">
<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">cont, cat <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> cont_cat_split(train_df, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, dep_var<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>dep_var)</span></code></pre></div>
</div>
</section>
<section id="step-2-define-our-training-and-validation-splits" class="level3">
<h3 class="anchored" data-anchor-id="step-2-define-our-training-and-validation-splits">Step 2: Define our training and validation splits</h3>
<p><strong>What is the difference between validation and test sets again?</strong></p>
<p>Recall that a <strong>validation set</strong> “is data we hold back from training in order to ensure that the training process does not overfit on the training data” … while a <strong>test set</strong> “is data that is held back from ourselves in order to ensure that we don’t overfit on the validation data as we export various model architectures and hyperparameters.”</p>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>“define our validation data so that it has the same sort of relationship wot the training data as the test set will have.”</p>
</div>
</div>
<p>Because this is a <strong>time series</strong> problem, we’ll make the validation set include data for the last 6 months of the full training set, and the training set everything before that. See p.291 for more on this!</p>
<div id="cell-36" class="cell">
<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">cond <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (train_df.saleYear <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2011</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|</span> (train_df.saleMonth <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span>)</span>
<span id="cb23-2">train_idxs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.where(cond)[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>]</span>
<span id="cb23-3">valid_idxs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.where(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span>cond)[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>]</span>
<span id="cb23-4"></span>
<span id="cb23-5">splits <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>(train_idxs), <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>(valid_idxs))</span></code></pre></div>
</div>
</section>
<section id="step-3-build-our-tabularpandas-object" class="level3">
<h3 class="anchored" data-anchor-id="step-3-build-our-tabularpandas-object">Step 3: Build our <code>TabularPandas</code> object</h3>
<p>And <strong>finally</strong>, we instantiate our <code>TabularPandas</code> object, passing in our data, procs, splits and dependent variables as such.</p>
<div id="cell-38" class="cell" data-outputid="68e799cc-c846-4edb-cb18-292a38e102fc">
<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">to <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> TabularPandas(train_df, procs, cat, cont, y_names<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>dep_var, splits<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>splits)</span>
<span id="cb24-2"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">type</span>(to)</span></code></pre></div>
<div class="cell-output cell-output-display" data-execution_count="18">
<pre><code>fastai.tabular.core.TabularPandas</code></pre>
</div>
</div>
<div class="callout callout-style-default 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">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>“A <code>TabularPandas</code> behaves a lot like a fastai <code>Datasets</code> object, including <code>train</code> and <code>valid</code> attributes”</p>
</div>
</div>
<div id="cell-40" class="cell" data-outputid="efd7d4bf-dbb1-4878-c86f-ebe5ee8d5b23">
<div class="sourceCode cell-code" id="cb26" 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;">len</span>(to.train), <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(to.valid)</span></code></pre></div>
<div class="cell-output cell-output-display" data-execution_count="19">
<pre><code>(404710, 7988)</code></pre>
</div>
</div>
<div id="cell-41" class="cell" data-outputid="c248d16b-1f89-4e09-a550-0f8e91c039ed">
<div class="sourceCode cell-code" id="cb28" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb28-1">to.show(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>)</span></code></pre></div>
<div class="cell-output cell-output-display">
<table class="dataframe caption-top table table-sm table-striped small" data-quarto-postprocess="true" data-border="1">
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th">UsageBand</th>
<th data-quarto-table-cell-role="th">fiModelDesc</th>
<th data-quarto-table-cell-role="th">fiBaseModel</th>
<th data-quarto-table-cell-role="th">fiSecondaryDesc</th>
<th data-quarto-table-cell-role="th">fiModelSeries</th>
<th data-quarto-table-cell-role="th">fiModelDescriptor</th>
<th data-quarto-table-cell-role="th">ProductSize</th>
<th data-quarto-table-cell-role="th">fiProductClassDesc</th>
<th data-quarto-table-cell-role="th">state</th>
<th data-quarto-table-cell-role="th">ProductGroup</th>
<th data-quarto-table-cell-role="th">ProductGroupDesc</th>
<th data-quarto-table-cell-role="th">Drive_System</th>
<th data-quarto-table-cell-role="th">Enclosure</th>
<th data-quarto-table-cell-role="th">Forks</th>
<th data-quarto-table-cell-role="th">Pad_Type</th>
<th data-quarto-table-cell-role="th">Ride_Control</th>
<th data-quarto-table-cell-role="th">Stick</th>
<th data-quarto-table-cell-role="th">Transmission</th>
<th data-quarto-table-cell-role="th">Turbocharged</th>
<th data-quarto-table-cell-role="th">Blade_Extension</th>
<th data-quarto-table-cell-role="th">Blade_Width</th>
<th data-quarto-table-cell-role="th">Enclosure_Type</th>
<th data-quarto-table-cell-role="th">Engine_Horsepower</th>
<th data-quarto-table-cell-role="th">Hydraulics</th>
<th data-quarto-table-cell-role="th">Pushblock</th>
<th data-quarto-table-cell-role="th">Ripper</th>
<th data-quarto-table-cell-role="th">Scarifier</th>
<th data-quarto-table-cell-role="th">Tip_Control</th>
<th data-quarto-table-cell-role="th">Tire_Size</th>
<th data-quarto-table-cell-role="th">Coupler</th>
<th data-quarto-table-cell-role="th">Coupler_System</th>
<th data-quarto-table-cell-role="th">Grouser_Tracks</th>
<th data-quarto-table-cell-role="th">Hydraulics_Flow</th>
<th data-quarto-table-cell-role="th">Track_Type</th>
<th data-quarto-table-cell-role="th">Undercarriage_Pad_Width</th>
<th data-quarto-table-cell-role="th">Stick_Length</th>
<th data-quarto-table-cell-role="th">Thumb</th>
<th data-quarto-table-cell-role="th">Pattern_Changer</th>
<th data-quarto-table-cell-role="th">Grouser_Type</th>
<th data-quarto-table-cell-role="th">Backhoe_Mounting</th>
<th data-quarto-table-cell-role="th">Blade_Type</th>
<th data-quarto-table-cell-role="th">Travel_Controls</th>
<th data-quarto-table-cell-role="th">Differential_Type</th>
<th data-quarto-table-cell-role="th">Steering_Controls</th>
<th data-quarto-table-cell-role="th">saleIs_month_end</th>
<th data-quarto-table-cell-role="th">saleIs_month_start</th>
<th data-quarto-table-cell-role="th">saleIs_quarter_end</th>
<th data-quarto-table-cell-role="th">saleIs_quarter_start</th>
<th data-quarto-table-cell-role="th">saleIs_year_end</th>
<th data-quarto-table-cell-role="th">saleIs_year_start</th>
<th data-quarto-table-cell-role="th">auctioneerID_na</th>
<th data-quarto-table-cell-role="th">MachineHoursCurrentMeter_na</th>
<th data-quarto-table-cell-role="th">SalesID</th>
<th data-quarto-table-cell-role="th">MachineID</th>
<th data-quarto-table-cell-role="th">ModelID</th>
<th data-quarto-table-cell-role="th">datasource</th>
<th data-quarto-table-cell-role="th">auctioneerID</th>
<th data-quarto-table-cell-role="th">YearMade</th>
<th data-quarto-table-cell-role="th">MachineHoursCurrentMeter</th>
<th data-quarto-table-cell-role="th">saleYear</th>
<th data-quarto-table-cell-role="th">saleMonth</th>
<th data-quarto-table-cell-role="th">saleWeek</th>
<th data-quarto-table-cell-role="th">saleDay</th>
<th data-quarto-table-cell-role="th">saleDayofweek</th>
<th data-quarto-table-cell-role="th">saleDayofyear</th>
<th data-quarto-table-cell-role="th">saleElapsed</th>
<th data-quarto-table-cell-role="th">SalePrice</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td data-quarto-table-cell-role="th">0</td>
<td>Low</td>
<td>521D</td>
<td>521</td>
<td>D</td>
<td>#na#</td>
<td>#na#</td>
<td>#na#</td>
<td>Wheel Loader - 110.0 to 120.0 Horsepower</td>
<td>Alabama</td>
<td>WL</td>
<td>Wheel Loader</td>
<td>#na#</td>
<td>EROPS w AC</td>
<td>None or Unspecified</td>
<td>#na#</td>
<td>None or Unspecified</td>
<td>#na#</td>
<td>#na#</td>
<td>#na#</td>
<td>#na#</td>
<td>#na#</td>
<td>#na#</td>
<td>#na#</td>
<td>2 Valve</td>
<td>#na#</td>
<td>#na#</td>
<td>#na#</td>
<td>#na#</td>
<td>None or Unspecified</td>
<td>None or Unspecified</td>
<td>#na#</td>
<td>#na#</td>
<td>#na#</td>
<td>#na#</td>
<td>#na#</td>
<td>#na#</td>
<td>#na#</td>
<td>#na#</td>
<td>#na#</td>
<td>#na#</td>
<td>#na#</td>
<td>#na#</td>
<td>Standard</td>
<td>Conventional</td>
<td>False</td>
<td>False</td>
<td>False</td>
<td>False</td>
<td>False</td>
<td>False</td>
<td>False</td>
<td>False</td>
<td>1139246</td>
<td>999089</td>
<td>3157</td>
<td>121</td>
<td>3.0</td>
<td>2004</td>
<td>68.0</td>
<td>2006</td>
<td>11</td>
<td>46</td>
<td>16</td>
<td>3</td>
<td>320</td>
<td>1.163635e+09</td>
<td>11.097410</td>
</tr>
<tr class="even">
<td data-quarto-table-cell-role="th">1</td>
<td>Low</td>
<td>950FII</td>
<td>950</td>
<td>F</td>
<td>II</td>
<td>#na#</td>
<td>Medium</td>
<td>Wheel Loader - 150.0 to 175.0 Horsepower</td>
<td>North Carolina</td>
<td>WL</td>
<td>Wheel Loader</td>
<td>#na#</td>
<td>EROPS w AC</td>
<td>None or Unspecified</td>
<td>#na#</td>
<td>None or Unspecified</td>
<td>#na#</td>
<td>#na#</td>
<td>#na#</td>
<td>#na#</td>
<td>#na#</td>
<td>#na#</td>
<td>#na#</td>
<td>2 Valve</td>
<td>#na#</td>
<td>#na#</td>
<td>#na#</td>
<td>#na#</td>
<td>23.5</td>
<td>None or Unspecified</td>
<td>#na#</td>
<td>#na#</td>
<td>#na#</td>
<td>#na#</td>
<td>#na#</td>
<td>#na#</td>
<td>#na#</td>
<td>#na#</td>
<td>#na#</td>
<td>#na#</td>
<td>#na#</td>
<td>#na#</td>
<td>Standard</td>
<td>Conventional</td>
<td>False</td>
<td>False</td>
<td>False</td>
<td>False</td>
<td>False</td>
<td>False</td>
<td>False</td>
<td>False</td>
<td>1139248</td>
<td>117657</td>
<td>77</td>
<td>121</td>
<td>3.0</td>
<td>1996</td>
<td>4640.0</td>
<td>2004</td>
<td>3</td>
<td>13</td>
<td>26</td>
<td>4</td>
<td>86</td>
<td>1.080259e+09</td>
<td>10.950807</td>
</tr>
<tr class="odd">
<td data-quarto-table-cell-role="th">2</td>
<td>High</td>
<td>226</td>
<td>226</td>
<td>#na#</td>
<td>#na#</td>
<td>#na#</td>
<td>#na#</td>
<td>Skid Steer Loader - 1351.0 to 1601.0 Lb Operating Capacity</td>
<td>New York</td>
<td>SSL</td>
<td>Skid Steer Loaders</td>
<td>#na#</td>
<td>OROPS</td>
<td>None or Unspecified</td>
<td>#na#</td>
<td>#na#</td>
<td>#na#</td>
<td>#na#</td>
<td>#na#</td>
<td>#na#</td>
<td>#na#</td>
<td>#na#</td>
<td>#na#</td>
<td>Auxiliary</td>
<td>#na#</td>
<td>#na#</td>
<td>#na#</td>
<td>#na#</td>
<td>#na#</td>
<td>None or Unspecified</td>
<td>None or Unspecified</td>
<td>None or Unspecified</td>
<td>Standard</td>
<td>#na#</td>
<td>#na#</td>
<td>#na#</td>
<td>#na#</td>
<td>#na#</td>
<td>#na#</td>
<td>#na#</td>
<td>#na#</td>
<td>#na#</td>
<td>#na#</td>
<td>#na#</td>
<td>False</td>
<td>False</td>
<td>False</td>
<td>False</td>
<td>False</td>
<td>False</td>
<td>False</td>
<td>False</td>
<td>1139249</td>
<td>434808</td>
<td>7009</td>
<td>121</td>
<td>3.0</td>
<td>2001</td>
<td>2838.0</td>
<td>2004</td>
<td>2</td>
<td>9</td>
<td>26</td>
<td>3</td>
<td>57</td>
<td>1.077754e+09</td>
<td>9.210340</td>
</tr>
</tbody>
</table>
</div>
</div>
<div id="cell-42" class="cell" data-outputid="557886be-c05b-43d7-93fa-4f6211691f86">
<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">to.items.head(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>)</span></code></pre></div>
<div class="cell-output cell-output-display" data-execution_count="21">
<div>


<table class="dataframe caption-top table table-sm table-striped small" data-quarto-postprocess="true" data-border="1">
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th">SalesID</th>
<th data-quarto-table-cell-role="th">SalePrice</th>
<th data-quarto-table-cell-role="th">MachineID</th>
<th data-quarto-table-cell-role="th">ModelID</th>
<th data-quarto-table-cell-role="th">...</th>
<th data-quarto-table-cell-role="th">saleIs_year_start</th>
<th data-quarto-table-cell-role="th">saleElapsed</th>
<th data-quarto-table-cell-role="th">auctioneerID_na</th>
<th data-quarto-table-cell-role="th">MachineHoursCurrentMeter_na</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td data-quarto-table-cell-role="th">0</td>
<td>1139246</td>
<td>11.097410</td>
<td>999089</td>
<td>3157</td>
<td>...</td>
<td>1</td>
<td>1.163635e+09</td>
<td>1</td>
<td>1</td>
</tr>
<tr class="even">
<td data-quarto-table-cell-role="th">1</td>
<td>1139248</td>
<td>10.950807</td>
<td>117657</td>
<td>77</td>
<td>...</td>
<td>1</td>
<td>1.080259e+09</td>
<td>1</td>
<td>1</td>
</tr>
<tr class="odd">
<td data-quarto-table-cell-role="th">2</td>
<td>1139249</td>
<td>9.210340</td>
<td>434808</td>
<td>7009</td>
<td>...</td>
<td>1</td>
<td>1.077754e+09</td>
<td>1</td>
<td>1</td>
</tr>
</tbody>
</table>

<p>3 rows × 67 columns</p>
</div>
</div>
</div>
<div class="callout callout-style-default 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">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>As you can see above, the underlying string values (the levels) have been replaced with a unique number associated to that level.</p>
</div>
</div>
<p>We can see that mapping via the <code>classes</code> attribute:</p>
<div id="cell-44" class="cell" data-outputid="b21f723d-6be7-4325-cbf2-d822440286a2">
<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">to.classes[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ProductSize"</span>]</span></code></pre></div>
<div class="cell-output cell-output-display" data-execution_count="22">
<pre><code>['#na#', 'Large', 'Large / Medium', 'Medium', 'Small', 'Mini', 'Compact']</code></pre>
</div>
</div>
<div class="callout callout-style-default callout-tip 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">
Tip
</div>
</div>
<div class="callout-body-container callout-body">
<p>Save your preprocessed <code>TabularPandas</code> object so you don’t have to process the data again</p>
</div>
</div>
<div id="cell-46" class="cell">
<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"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># save to filesystem</span></span>
<span id="cb32-2">save_pickle(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;">"to.pkl"</span>, to)</span>
<span id="cb32-3"></span>
<span id="cb32-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># load from filesystem</span></span>
<span id="cb32-5">to <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> load_pickle(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;">"to.pkl"</span>)</span></code></pre></div>
</div>
</section>
</section>
<section id="approach-1-decision-trees" class="level2">
<h2 class="anchored" data-anchor-id="approach-1-decision-trees">Approach 1: Decision Trees</h2>
<p>“A <strong>decision tree</strong> asks a series of binary (yes or no) questions about the data. After each question, the data at that part of the tree is split between a Yes and a No branch…. After one or more questions, either a prediction can be made on the basis of all previous answers or another question is required.”</p>
<p>“… for <strong>regression</strong>, we take the target mean of the items in the group”</p>
<div class="callout callout-style-default 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">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>See p.288 for <strong>how we find the right questions to ask</strong>.</p>
</div>
</div>
<section id="step-1-define-independentdependent-variables" class="level3">
<h3 class="anchored" data-anchor-id="step-1-define-independentdependent-variables">Step 1: Define independent/dependent variables</h3>
<p>After this, our data is completely numeric and there are no missing values!</p>
<div id="cell-49" class="cell">
<div class="sourceCode cell-code" id="cb33" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb33-1">train_xs, train_y <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> to.train.xs, to.train.y</span>
<span id="cb33-2">valid_xs, valid_y <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> to.valid.xs, to.valid.y</span></code></pre></div>
</div>
</section>
<section id="step-2-build-our-tree" class="level3">
<h3 class="anchored" data-anchor-id="step-2-build-our-tree">Step 2: Build our tree</h3>
<p><strong><code>max_leaf_nodes=4</code></strong> = “Stop when you have 4 leaf nodes”</p>
<div id="cell-51" class="cell" data-outputid="1b55eadb-cda6-4ae5-ec26-d6608aea7c13">
<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">m <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> DecisionTreeRegressor(max_leaf_nodes<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>
<span id="cb34-2">m.fit(train_xs, train_y)</span></code></pre></div>
<div class="cell-output cell-output-display" data-execution_count="25">
<pre><code>DecisionTreeRegressor(max_leaf_nodes=4)</code></pre>
</div>
</div>
<div id="cell-52" class="cell" data-outputid="1a12e17c-c3ce-44d1-e233-ddbb93bd422b">
<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">draw_tree(m, train_xs, 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;">7</span>, leaves_parallel<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>, 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>)</span></code></pre></div>
<div class="cell-output cell-output-display" data-execution_count="26">
<div>
<figure class="figure">
<p><img src="https://ohmeow.com/posts/2022-04-25-ajtfb-chapter-9_files/figure-html/cell-27-output-1.svg" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
<p><strong>What is in each box above?</strong>:</p>
<ol type="1">
<li>The decision criterion for the best split that was found</li>
<li>“samples”: The # of examples in the group</li>
<li>“value”: The average value of the target for that group</li>
<li>“squared_error”: The MSE for that group</li>
</ol>
<div class="callout callout-style-default 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">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>“The top node represents the <em>initial model</em> before any splits have been done, when all the data is in one group. This is the simplest possible model. It is the result of asking zero questions and will always predict the value to be the average value of the whole dataset.”</p>
</div>
</div>
<p>A “<strong>leaf node</strong>” is a node “with no answers coming out of them, because there are no more questions to be answered.”</p>
<p>See p.293 for more on intrepreting the diagram above.</p>
<div id="cell-54" class="cell" data-outputid="da40c901-ba0d-432b-9ec7-138e2e808b82">
<div class="sourceCode cell-code" id="cb37" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb37-1">samp_idx <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.random.permutation(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(train_y))[:<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">500</span>]</span>
<span id="cb37-2"></span>
<span id="cb37-3">dtreeviz(</span>
<span id="cb37-4">    m,</span>
<span id="cb37-5">    train_xs.iloc[samp_idx],</span>
<span id="cb37-6">    train_y.iloc[samp_idx],</span>
<span id="cb37-7">    train_xs.columns,</span>
<span id="cb37-8">    dep_var,</span>
<span id="cb37-9">    fontname<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"DejaVu Sans"</span>,</span>
<span id="cb37-10">    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;">1.6</span>,</span>
<span id="cb37-11">    label_fontsize<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>,</span>
<span id="cb37-12">    orientation<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"LR"</span>,</span>
<span id="cb37-13">)</span></code></pre></div>
<div class="cell-output cell-output-stderr">
<pre><code>/usr/local/lib/python3.7/dist-packages/sklearn/base.py:451: UserWarning: X does not have valid feature names, but DecisionTreeRegressor was fitted with feature names
  "X does not have valid feature names, but"</code></pre>
</div>
<div class="cell-output cell-output-display" data-execution_count="27">
<div>
<figure class="figure">
<p><img src="https://ohmeow.com/posts/2022-04-25-ajtfb-chapter-9_files/figure-html/cell-28-output-2.svg" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
<p>“This shows a cart of the distribution of the data for each split point”</p>
<div class="callout callout-style-default callout-tip 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">
Tip
</div>
</div>
<div class="callout-body-container callout-body">
<p>Use <code>dtreeviz</code> to find problems with the data.</p>
</div>
</div>
<p>For example, you can see there is a problem with “YearMade” as a bunch of tractors show they are made in the year 1000. The likely explanation is that if they don’t have the info on a tractor, they set it = 1000 to indicate “Unknown”.</p>
<p>We can replace this with something like 1950 to make the visuals more clear …</p>
<div id="cell-56" class="cell">
<div class="sourceCode cell-code" id="cb39" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb39-1">train_xs.loc[train_xs[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"YearMade"</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1900</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"YearMade"</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;">1950</span></span>
<span id="cb39-2">valid_xs.loc[valid_xs[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"YearMade"</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1900</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"YearMade"</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;">1950</span></span></code></pre></div>
</div>
<div id="cell-57" class="cell" data-outputid="1fea987e-9732-470d-ddf8-74ebf010290d">
<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">samp_idx <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.random.permutation(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(train_y))[:<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">500</span>]</span>
<span id="cb40-2"></span>
<span id="cb40-3">dtreeviz(</span>
<span id="cb40-4">    m,</span>
<span id="cb40-5">    train_xs.iloc[samp_idx],</span>
<span id="cb40-6">    train_y.iloc[samp_idx],</span>
<span id="cb40-7">    train_xs.columns,</span>
<span id="cb40-8">    dep_var,</span>
<span id="cb40-9">    fontname<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"DejaVu Sans"</span>,</span>
<span id="cb40-10">    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;">1.6</span>,</span>
<span id="cb40-11">    label_fontsize<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>,</span>
<span id="cb40-12">    orientation<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"LR"</span>,</span>
<span id="cb40-13">)</span></code></pre></div>
<div class="cell-output cell-output-stderr">
<pre><code>/usr/local/lib/python3.7/dist-packages/sklearn/base.py:451: UserWarning: X does not have valid feature names, but DecisionTreeRegressor was fitted with feature names
  "X does not have valid feature names, but"</code></pre>
</div>
<div class="cell-output cell-output-display" data-execution_count="29">
<div>
<figure class="figure">
<p><img src="https://ohmeow.com/posts/2022-04-25-ajtfb-chapter-9_files/figure-html/cell-30-output-2.svg" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
</section>
<section id="step-3-build-other-trees" class="level3">
<h3 class="anchored" data-anchor-id="step-3-build-other-trees">Step 3: Build other trees</h3>
<div id="cell-59" class="cell" data-outputid="e9e667be-db92-4b53-fb51-804642b06654">
<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">m <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> DecisionTreeRegressor()</span>
<span id="cb42-2">m.fit(train_xs, train_y)</span></code></pre></div>
<div class="cell-output cell-output-display" data-execution_count="30">
<pre><code>DecisionTreeRegressor()</code></pre>
</div>
</div>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>Create/Use <strong>the</strong> metric used by the competition (or your work)</p>
</div>
</div>
<div id="cell-61" class="cell">
<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"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> r_mse(preds, targs):</span>
<span id="cb44-2">    <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;">round</span>(math.sqrt(((preds <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> targs) <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>).mean()), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span>)</span>
<span id="cb44-3"></span>
<span id="cb44-4"></span>
<span id="cb44-5"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> m_rmse(m, xs, y):</span>
<span id="cb44-6">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> r_mse(m.predict(xs), y)</span></code></pre></div>
</div>
<div id="cell-62" class="cell" data-outputid="7c3133d6-0afc-4d60-f9f5-7831e189720a">
<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">m_rmse(m, train_xs, train_y)</span></code></pre></div>
<div class="cell-output cell-output-display" data-execution_count="32">
<pre><code>0.0</code></pre>
</div>
</div>
<div id="cell-63" class="cell" data-outputid="d6220317-d7df-4a96-cba7-51716fb4be3c">
<div class="sourceCode cell-code" id="cb47" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb47-1">m_rmse(m, valid_xs, valid_y)</span></code></pre></div>
<div class="cell-output cell-output-display" data-execution_count="33">
<pre><code>0.333111</code></pre>
</div>
</div>
<p><strong>What does the above indicate?</strong></p>
<p>That we might be <strong>overfitting</strong> … badly (because our training set is perfect and our validation set not so much).</p>
<p><strong>Why are we overfitting?</strong></p>
<p>Because “we have nearly as many leaf nodes as data points … <strong>sklearn’s default settings allow it to continue splitting nodes until there is only one item in each leaf node</strong>.” See pp.295-296 for more intuition on why trees overfit.</p>
<div id="cell-65" class="cell" data-outputid="7e94a4bf-9056-412c-f26c-cb7f389722d2">
<div class="sourceCode cell-code" id="cb49" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb49-1">m.get_n_leaves(), <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(train_xs)</span></code></pre></div>
<div class="cell-output cell-output-display" data-execution_count="34">
<pre><code>(324559, 404710)</code></pre>
</div>
</div>
<div id="cell-66" class="cell" data-outputid="4b63badc-fe2f-4a60-fb6c-9e7cb044dfec">
<div class="sourceCode cell-code" id="cb51" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb51-1">m <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> DecisionTreeRegressor(min_samples_leaf<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;">25</span>)</span>
<span id="cb51-2">m.fit(to.train.xs, to.train.y)</span>
<span id="cb51-3"></span>
<span id="cb51-4">m_rmse(m, to.train.xs, to.train.y), m_rmse(m, to.valid.xs, to.valid.y)</span></code></pre></div>
<div class="cell-output cell-output-display" data-execution_count="35">
<pre><code>(0.211677, 0.268059)</code></pre>
</div>
</div>
<p><strong><code>min_samples_leaf=25</code></strong> = “Stop when all leaf nodes have a minimum of 25 samples”</p>
</section>
<section id="a-note-on-categorical-variables" class="level3">
<h3 class="anchored" data-anchor-id="a-note-on-categorical-variables">A note on categorical variables</h3>
<p>Decision trees **don’t have embedding layers - “so how can these untreated categorical variables do anything useful”?</p>
<p>Answer: “It just works!”</p>
<div class="callout callout-style-default 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">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>While it is possible to replace a categorical variable with multiple OHE columns using something like <code>get_dummies</code>, “there is not really any evidence that such an approach improves the end result.”</p>
</div>
</div>
<p>See p.297 for more about why OHE aren’t necessary and why decision tree just work with categorical variables out-of-the-box.</p>
</section>
</section>
<section id="approach-2-random-forests" class="level2">
<h2 class="anchored" data-anchor-id="approach-2-random-forests">Approach 2: Random Forests</h2>
<p>A <strong>random forest</strong> “is a model that averages the predictions of a large number of decision trees, which are generated by randomly varying various parameters that specify what data is used to train the tree (what columns and rows are included in each tree) and other tree parameters”</p>
<p><strong>Why does it work so well?</strong></p>
<p>Because it utlizes <strong>bagging</strong>.</p>
<p><strong>What is “bagging”?</strong></p>
<p>From the “Bagging Predictors” paper … “<strong>Bagging predictors</strong> is a method for generating multiple versions of a predictor and using these to get an aggregated predictor…. The multiple versions are formed by making <strong>bootstrap replicates</strong> (a randomly chosen subset of rows) of the learning set.”</p>
<div class="callout callout-style-default 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">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>“… although each of the models trained on a subset of data will make more errors than a model trained on the full dataset, those errors will not be correlated with each other. **Different models make different errors … the average of those errors, therefore, is zero!”</p>
</div>
</div>
<p>This means that we can improve the performance of a model by training it multiple times with a different random subset of the data each time, and then averaging the predictions.</p>
<div class="callout callout-style-default 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">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p><strong>Ensembling</strong> is a form of bagging</p>
</div>
</div>
<p>See p.298 for more details on how bagging works.</p>
<section id="step-1-define-your-random-forest" class="level3">
<h3 class="anchored" data-anchor-id="step-1-define-your-random-forest">Step 1: Define your Random Forest</h3>
<p>Since we need to define a variety of parameters that indicate the number of trees we want, how subsets of rows should be randomly chosen, how subsets of columns should likewise be randomly chosen, etc., we’ll put the creation behind a function we can call.</p>
<div id="cell-71" class="cell">
<div class="sourceCode cell-code" id="cb53" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb53-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> fit_rf(</span>
<span id="cb53-2">    xs,</span>
<span id="cb53-3">    y,</span>
<span id="cb53-4">    n_estimators<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>
<span id="cb53-5">    max_samples<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_000</span>,</span>
<span id="cb53-6">    max_features<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>
<span id="cb53-7">    min_samples_leaf<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="cb53-8">    <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">**</span>kwargs,</span>
<span id="cb53-9">):</span>
<span id="cb53-10">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> RandomForestRegressor(</span>
<span id="cb53-11">        n_jobs<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="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Tells sklearn to use all our CPUs to build the trees in parallel</span></span>
<span id="cb53-12">        n_estimators<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>n_estimators,  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># The number of trees</span></span>
<span id="cb53-13">        max_samples<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>max_samples,  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># The number of rows to sample for training ea. tree</span></span>
<span id="cb53-14">        max_features<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>max_features,  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># The number of columns to sample at each split</span></span>
<span id="cb53-15">        min_samples_leaf<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>min_samples_leaf,  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Stop when all leaf nodes have at least this number of samples</span></span>
<span id="cb53-16">        oob_score<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="cb53-17">    ).fit(xs, y)</span></code></pre></div>
</div>
<div id="cell-72" class="cell">
<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">m <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> fit_rf(train_xs, train_y)</span></code></pre></div>
</div>
<div id="cell-73" class="cell" data-outputid="7ecd6702-db88-4994-8fea-d084c3eaf0c4">
<div class="sourceCode cell-code" id="cb55" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb55-1">m_rmse(m, train_xs, train_y), m_rmse(m, valid_xs, valid_y)</span></code></pre></div>
<div class="cell-output cell-output-display" data-execution_count="38">
<pre><code>(0.170771, 0.232215)</code></pre>
</div>
</div>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>Random Forests are <em>very</em> sensitive to hyperparameter choices!</p>
</div>
</div>
<p><strong>Recommended hyperparameter values:</strong></p>
<ul>
<li><p><code>n_estimators</code>: “as high a number as you have time to train … more trees = more accurate</p></li>
<li><p><code>max_samples</code>: default (200,000)</p></li>
<li><p><code>max_features</code>: default (“auto”) or 0.5</p></li>
<li><p><code>min_samples_leaf</code>: default (1) or 4</p></li>
</ul>
<div class="callout callout-style-default callout-tip 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">
Tip
</div>
</div>
<div class="callout-body-container callout-body">
<p>Bigger forests using a smalle subset of features tens to be better (see chart below)</p>
</div>
</div>
<p><img src="https://raw.githubusercontent.com/fastai/fastbook/b7f756b49d4eb0d3ce96c0c29be98f4f293cde9f/images/sklearn_features.png" class="img-fluid"></p>
<p><strong>How to get the predictions for a SINGLE tree?</strong></p>
<div id="cell-76" class="cell" data-outputid="4ca93903-b64e-4d8c-de6d-4e5d3e0ff653">
<div class="sourceCode cell-code" id="cb57" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb57-1">tree_preds <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.stack(</span>
<span id="cb57-2">    [t.predict(valid_xs.values) <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> m.estimators_]</span>
<span id="cb57-3">)  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># added .values (see: https://stackoverflow.com/a/69378867)</span></span>
<span id="cb57-4"></span>
<span id="cb57-5">r_mse(tree_preds.mean(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>), valid_y)</span></code></pre></div>
<div class="cell-output cell-output-display" data-execution_count="39">
<pre><code>0.232215</code></pre>
</div>
</div>
<p><strong>How does <code>n_estimators</code> impact model performance?</strong></p>
<p>To answer this, we can increment the number of trees we use in our predictions one at a time like so:</p>
<div id="cell-78" class="cell" data-outputid="ed3cc170-23e7-46e8-b8cd-c8e90cd90ab4">
<div class="sourceCode cell-code" id="cb59" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb59-1">plt.plot([r_mse(tree_preds[: i <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>].mean(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>), valid_y) <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;">40</span>)])</span></code></pre></div>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://ohmeow.com/posts/2022-04-25-ajtfb-chapter-9_files/figure-html/cell-41-output-1.png" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
<div class="callout callout-style-default callout-tip 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">
Tip
</div>
</div>
<div class="callout-body-container callout-body">
<p>Use the above technique to determine a good range of trees to try.</p>
</div>
</div>
</section>
<section id="step-2-determine-why-our-validation-set-is-worse-than-training" class="level3">
<h3 class="anchored" data-anchor-id="step-2-determine-why-our-validation-set-is-worse-than-training">Step 2: Determine why our validation set is worse than training</h3>
<div class="callout callout-style-default callout-tip 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">
Tip
</div>
</div>
<div class="callout-body-container callout-body">
<p>Use the <strong>out-of-bag (OOB) error</strong> to determine if we’re overfitting, or if the validation set covers a different time period, or if it’s a bit of both.</p>
</div>
</div>
<p>“The <strong>OOB error</strong> is <strong>a way of measuring prediction error in the training dataset</strong>” based on rows <em>not</em> used in the training of a particular tree. “This <strong>allows us to see whether the model is overfitting, without needing a separate validation set.</strong>”</p>
<p>“… out-of-bag error is a little like imagining that every tree therefore also has its own validation set” based on the prediction of rows not used in its training.</p>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>“This is particularly beneficial in cases where we have only a small amount of training data” (we don’t necessarily have to remove items to create a validation set).</p>
</div>
</div>
<div class="callout callout-style-default 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">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>If your OOB error is &lt;&lt; than our validation set error, “something else is causing the error”</p>
</div>
</div>
<div class="callout callout-style-default 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">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>“we compoare [OOB predictions] to our training labels”since this is being calculated on trees using the training set.”</p>
</div>
</div>
<div id="cell-81" class="cell" data-outputid="7809748f-1d31-4d1f-f8a1-2124e8398fe0">
<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">r_mse(m.oob_prediction_, train_y)</span></code></pre></div>
<div class="cell-output cell-output-display" data-execution_count="41">
<pre><code>0.210601</code></pre>
</div>
</div>
<hr>
</section>
<section id="model-interpretation" class="level3">
<h3 class="anchored" data-anchor-id="model-interpretation">Model Interpretation</h3>
<section id="how-confident-are-we-in-our-predictions-using-a-particular-row-of-data" class="level4">
<h4 class="anchored" data-anchor-id="how-confident-are-we-in-our-predictions-using-a-particular-row-of-data">How confident are we in our predictions using a particular row of data?</h4>
<p>Answer: “use the standard deviation of predictions across the trees, instead of just the mean. This <strong>tells us the relative confidence of predictions</strong>”</p>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>“…be more cautious of using the reulsts for rows where trees give very different results (higher standard deviations)”</p>
</div>
</div>
<div class="callout callout-style-default callout-tip 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">
Tip
</div>
</div>
<div class="callout-body-container callout-body">
<p>This information is helpful in production where “if you were using this model to decide which items to bid on at auction, a low-confidence prediction might cause you to look more carefully at an item before you made a bid.”</p>
</div>
</div>
<div id="cell-84" class="cell" data-outputid="1b2d96d8-3a9a-49fa-cf29-c5659d790989">
<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">preds <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.stack([t.predict(valid_xs.values) <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> m.estimators_])</span>
<span id="cb62-2">preds.shape  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># =&gt; (# of trees, # of predictions)</span></span></code></pre></div>
<div class="cell-output cell-output-display" data-execution_count="42">
<pre><code>(40, 7988)</code></pre>
</div>
</div>
<div id="cell-85" class="cell">
<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">preds_std <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> preds.std(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># get rid of first dimension (the trees)</span></span></code></pre></div>
</div>
<div id="cell-86" class="cell" data-outputid="47f8ba3f-9ed2-4dba-e893-edc631e482cd">
<div class="sourceCode cell-code" id="cb65" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb65-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># std for first 5 rows of validation set</span></span>
<span id="cb65-2">preds_std[:<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>]</span></code></pre></div>
<div class="cell-output cell-output-display" data-execution_count="44">
<pre><code>array([0.25911739, 0.08550421, 0.11939131, 0.29835108, 0.16490343])</code></pre>
</div>
</div>
</section>
<section id="which-columns-are-the-strongest-predictors-and-which-can-we-ignore" class="level4">
<h4 class="anchored" data-anchor-id="which-columns-are-the-strongest-predictors-and-which-can-we-ignore">Which columns are the strongest predictors (and which can we ignore)?</h4>
<p>“It’s not normally enough to just know that a model can make accurate predictions - <strong>we also want to know how it’s making predictions</strong>”</p>
<p>Answer: “<strong><em>feature importances</em></strong> give us this insight.”</p>
<div id="cell-88" class="cell">
<div class="sourceCode cell-code" id="cb67" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb67-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> rf_feature_importance(m, df):</span>
<span id="cb67-2">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> pd.DataFrame(</span>
<span id="cb67-3">        {<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"cols"</span>: df.columns, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"imp"</span>: m.feature_importances_}</span>
<span id="cb67-4">    ).sort_values(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"imp"</span>, ascending<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="cb67-5"></span>
<span id="cb67-6"></span>
<span id="cb67-7"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> plot_fi(fi_df):</span>
<span id="cb67-8">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> fi_df.plot(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"cols"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"imp"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"barh"</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;">12</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">7</span>), legend<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 id="cell-89" class="cell" data-outputid="476af52e-2026-4e62-c89d-1676f798c9e7">
<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">fi_df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> rf_feature_importance(m, train_xs)</span>
<span id="cb68-2"></span>
<span id="cb68-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Let's look at the 10 most important features</span></span>
<span id="cb68-4">fi_df[:<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span>]</span></code></pre></div>
<div class="cell-output cell-output-display" data-execution_count="46">
<div>


<table class="dataframe caption-top table table-sm table-striped small" data-quarto-postprocess="true" data-border="1">
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th">cols</th>
<th data-quarto-table-cell-role="th">imp</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td data-quarto-table-cell-role="th">57</td>
<td>YearMade</td>
<td>0.186662</td>
</tr>
<tr class="even">
<td data-quarto-table-cell-role="th">6</td>
<td>ProductSize</td>
<td>0.133412</td>
</tr>
<tr class="odd">
<td data-quarto-table-cell-role="th">30</td>
<td>Coupler_System</td>
<td>0.098091</td>
</tr>
<tr class="even">
<td data-quarto-table-cell-role="th">7</td>
<td>fiProductClassDesc</td>
<td>0.071924</td>
</tr>
<tr class="odd">
<td data-quarto-table-cell-role="th">32</td>
<td>Hydraulics_Flow</td>
<td>0.064008</td>
</tr>
<tr class="even">
<td data-quarto-table-cell-role="th">65</td>
<td>saleElapsed</td>
<td>0.050607</td>
</tr>
<tr class="odd">
<td data-quarto-table-cell-role="th">54</td>
<td>ModelID</td>
<td>0.049313</td>
</tr>
<tr class="even">
<td data-quarto-table-cell-role="th">3</td>
<td>fiSecondaryDesc</td>
<td>0.045434</td>
</tr>
<tr class="odd">
<td data-quarto-table-cell-role="th">1</td>
<td>fiModelDesc</td>
<td>0.033899</td>
</tr>
<tr class="even">
<td data-quarto-table-cell-role="th">31</td>
<td>Grouser_Tracks</td>
<td>0.026686</td>
</tr>
</tbody>
</table>

</div>
</div>
</div>
<div id="cell-90" class="cell" data-outputid="6e2a0b8e-993e-40cd-c23f-6f9d7027ca1a">
<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">plot_fi(fi_df[:<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">30</span>])</span></code></pre></div>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://ohmeow.com/posts/2022-04-25-ajtfb-chapter-9_files/figure-html/cell-48-output-1.png" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
<p>See p.304 for how feature importance is calculated.</p>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>By removing variables of low importance we can still get good results <strong>while making our model simpler, more interpretable, and easier to maintain</strong></p>
</div>
</div>
<div id="cell-93" class="cell" data-outputid="bead0599-1d63-4167-e15a-9fc7f7c125aa">
<div class="sourceCode cell-code" id="cb70" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb70-1">cols_to_keep <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> fi_df[fi_df.imp <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.005</span>].cols</span>
<span id="cb70-2"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(cols_to_keep)</span></code></pre></div>
<div class="cell-output cell-output-display" data-execution_count="48">
<pre><code>21</code></pre>
</div>
</div>
<div id="cell-94" class="cell">
<div class="sourceCode cell-code" id="cb72" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb72-1">train_xs_keep <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> train_xs[cols_to_keep]</span>
<span id="cb72-2">valid_xs_keep <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> valid_xs[cols_to_keep]</span></code></pre></div>
</div>
<div id="cell-95" class="cell">
<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">m <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> fit_rf(train_xs_keep, train_y)</span></code></pre></div>
</div>
<div id="cell-96" class="cell" data-outputid="d77b2392-51e6-41cb-eaba-667b4009e38d">
<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">m_rmse(m, train_xs_keep, train_y), m_rmse(m, valid_xs_keep, valid_y)</span></code></pre></div>
<div class="cell-output cell-output-display" data-execution_count="51">
<pre><code>(0.181366, 0.231985)</code></pre>
</div>
</div>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>Compare accuracy of full model with column subset to ensure equitable performance!</p>
</div>
</div>
<p>The accuracy is about the same as before, but the model is much more interpretable …</p>
<div id="cell-98" class="cell" data-outputid="2c93fafb-201d-479b-f008-0d645dd81d68">
<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"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(train_xs.columns), <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(train_xs_keep.columns)</span></code></pre></div>
<div class="cell-output cell-output-display" data-execution_count="52">
<pre><code>(66, 21)</code></pre>
</div>
</div>
<div id="cell-99" class="cell" data-outputid="9b57a252-f1ab-4a96-da36-d1705efb5bb4">
<div class="sourceCode cell-code" id="cb78" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb78-1">plot_fi(rf_feature_importance(m, train_xs_keep[:<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">30</span>]))</span></code></pre></div>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://ohmeow.com/posts/2022-04-25-ajtfb-chapter-9_files/figure-html/cell-54-output-1.png" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
</section>
<section id="which-columns-are-effectively-redundant" class="level4">
<h4 class="anchored" data-anchor-id="which-columns-are-effectively-redundant">Which columns are effectively redundant?</h4>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>Like removing unimportant features, by removing redundant information, we <strong>make our model simpler, more interpretable, and easier to maintain</strong></p>
</div>
</div>
<div id="cell-101" class="cell" data-outputid="4ca7d1ea-a4bc-440d-8482-eeacddd37bbe">
<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">cluster_columns(train_xs_keep)</span></code></pre></div>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://ohmeow.com/posts/2022-04-25-ajtfb-chapter-9_files/figure-html/cell-55-output-1.png" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
<p><strong>How do we determine similarity?</strong></p>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>“… the pairs of columns that are most similar are the ones that were merged together early”</p>
</div>
</div>
<p>“The most similar paris are found by calculating the <em>rank correlation</em>, which means that all the values are replaced with their <em>rank</em> … and then the <em>correlation</em> is calculated.</p>
<p><strong>How do we know if a feature is “redundant” and can be dropped?</strong></p>
<p>Answer: By removing potentially redundant variables <strong>one at a time</strong></p>
<p>“We don’t need [the model] to be very accurate” so we can use a lower <code>max_samples</code> and a higher <code>min_samples_leaf</code>. We just want to see the effect it has by removing certain columns using the <strong>OOB score</strong> (“a number returned by sklearn that ranges between 1.0 for a perfect model and 0.0 for a random model.”</p>
<div id="cell-103" class="cell">
<div class="sourceCode cell-code" id="cb80" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb80-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> get_oob(df, y):</span>
<span id="cb80-2">    m <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> RandomForestRegressor(</span>
<span id="cb80-3">        n_estimators<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>,</span>
<span id="cb80-4">        min_samples_leaf<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;">15</span>,</span>
<span id="cb80-5">        max_samples<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_000</span>,</span>
<span id="cb80-6">        max_features<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>
<span id="cb80-7">        n_jobs<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="cb80-8">        oob_score<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="cb80-9">    )</span>
<span id="cb80-10">    m.fit(df, y)</span>
<span id="cb80-11">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> m.oob_score_</span></code></pre></div>
</div>
<p>Our baseline:</p>
<div id="cell-105" class="cell" data-outputid="21986ec9-6ea9-469c-8ef0-a34e3fc8a6a0">
<div class="sourceCode cell-code" id="cb81" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb81-1">get_oob(train_xs_keep, train_y)</span></code></pre></div>
<div class="cell-output cell-output-display" data-execution_count="56">
<pre><code>0.8723047876078355</code></pre>
</div>
</div>
<p>Try removing redundant features one at a time:</p>
<div id="cell-107" class="cell" data-outputid="2a9fa525-e3f7-4644-f691-2cbebba6eaeb">
<div class="sourceCode cell-code" id="cb83" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb83-1">redundant_cols <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [</span>
<span id="cb83-2">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"saleYear"</span>,</span>
<span id="cb83-3">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"saleElapsed"</span>,</span>
<span id="cb83-4">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ProductGroupDesc"</span>,</span>
<span id="cb83-5">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ProductGroup"</span>,</span>
<span id="cb83-6">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"fiModelDesc"</span>,</span>
<span id="cb83-7">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"fiBaseModel"</span>,</span>
<span id="cb83-8">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Hydraulics_Flow"</span>,</span>
<span id="cb83-9">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Grouser_Tracks"</span>,</span>
<span id="cb83-10">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Coupler_System"</span>,</span>
<span id="cb83-11">]</span>
<span id="cb83-12"></span>
<span id="cb83-13">{c: get_oob(train_xs_keep.drop(c, axis<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>), train_y) <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> redundant_cols}</span></code></pre></div>
<div class="cell-output cell-output-display" data-execution_count="57">
<pre><code>{'Coupler_System': 0.8729675628149272,
 'Grouser_Tracks': 0.8735142839769211,
 'Hydraulics_Flow': 0.8730586366090629,
 'ProductGroup': 0.8731366740450576,
 'ProductGroupDesc': 0.8728712200071638,
 'fiBaseModel': 0.87126582392193,
 'fiModelDesc': 0.8714879359004835,
 'saleElapsed': 0.8681954238416791,
 'saleYear': 0.8713304844511609}</code></pre>
</div>
</div>
<p>Now try dropping multiple variables (<strong>one from each of the tightly aligned pairs</strong> we noticed above), and compare accuracy:</p>
<div id="cell-109" class="cell" data-outputid="3e3eb813-2bd4-48ac-9cea-cfe7d00ff520">
<div class="sourceCode cell-code" id="cb85" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb85-1">cols_to_drop <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"saleYear"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ProductGroupDesc"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"fiBaseModel"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Grouser_Tracks"</span>]</span>
<span id="cb85-2"></span>
<span id="cb85-3">get_oob(train_xs_keep.drop(cols_to_drop, axis<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>), train_y)</span></code></pre></div>
<div class="cell-output cell-output-display" data-execution_count="58">
<pre><code>0.8695950962336326</code></pre>
</div>
</div>
<p>Assuming that its not much worse, create new DataFrames and save …</p>
<div id="cell-111" class="cell">
<div class="sourceCode cell-code" id="cb87" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb87-1">train_xs_final <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> train_xs_keep.drop(cols_to_drop, axis<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="cb87-2">valid_xs_final <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> valid_xs_keep.drop(cols_to_drop, axis<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="cb87-3"></span>
<span id="cb87-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># save to filesystem</span></span>
<span id="cb87-5">save_pickle(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;">"train_xs_final.pkl"</span>, train_xs_final)</span>
<span id="cb87-6">save_pickle(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;">"valid_xs_final.pkl"</span>, valid_xs_final)</span></code></pre></div>
</div>
<p>… then load them back in later</p>
<div id="cell-113" class="cell">
<div class="sourceCode cell-code" id="cb88" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb88-1">train_xs_final <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> load_pickle(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;">"train_xs_final.pkl"</span>)</span>
<span id="cb88-2">valid_xs_final <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> load_pickle(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;">"valid_xs_final.pkl"</span>)</span></code></pre></div>
</div>
<div id="cell-114" class="cell" data-outputid="2c4651da-bc4c-4979-ce22-2726c1fc71d1">
<div class="sourceCode cell-code" id="cb89" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb89-1">m <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> fit_rf(train_xs_final.values, train_y)</span>
<span id="cb89-2">m_rmse(m, train_xs_final.values, train_y), m_rmse(m, valid_xs_final.values, valid_y)</span></code></pre></div>
<div class="cell-output cell-output-display" data-execution_count="61">
<pre><code>(0.183291, 0.232867)</code></pre>
</div>
</div>
</section>
<section id="how-do-find-the-relationship-between-two-predictors-columns" class="level4">
<h4 class="anchored" data-anchor-id="how-do-find-the-relationship-between-two-predictors-columns">How do find the relationship between two predictors (columns)?</h4>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>Do this for the most important predictors!</p>
</div>
</div>
<p>First, <strong>check the count of values per category</strong>:</p>
<div id="cell-117" class="cell" data-outputid="28b45c61-eb81-423d-8338-e78a1f5e1e67">
<div class="sourceCode cell-code" id="cb91" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb91-1">p <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> valid_xs_final[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ProductSize"</span>].value_counts().sort_index().plot.barh()</span>
<span id="cb91-2">c <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> to.classes[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ProductSize"</span>]</span>
<span id="cb91-3">plt.yticks(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(c)), c)</span></code></pre></div>
<div class="cell-output cell-output-display" data-execution_count="62">
<pre><code>([&lt;matplotlib.axis.YTick at 0x7f6564704d10&gt;,
  &lt;matplotlib.axis.YTick at 0x7f6562ce8350&gt;,
  &lt;matplotlib.axis.YTick at 0x7f6562b34d10&gt;,
  &lt;matplotlib.axis.YTick at 0x7f65645b61d0&gt;,
  &lt;matplotlib.axis.YTick at 0x7f656473b310&gt;,
  &lt;matplotlib.axis.YTick at 0x7f656473bd90&gt;,
  &lt;matplotlib.axis.YTick at 0x7f656473b250&gt;],
 [Text(0, 0, '#na#'),
  Text(0, 0, 'Large'),
  Text(0, 0, 'Large / Medium'),
  Text(0, 0, 'Medium'),
  Text(0, 0, 'Small'),
  Text(0, 0, 'Mini'),
  Text(0, 0, 'Compact')])</code></pre>
</div>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://ohmeow.com/posts/2022-04-25-ajtfb-chapter-9_files/figure-html/cell-63-output-2.png" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
<div id="cell-118" class="cell" data-outputid="296463b6-0c9a-44d6-ea9c-0cdee6c9093f">
<div class="sourceCode cell-code" id="cb93" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb93-1">x <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> valid_xs_final[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"YearMade"</span>].hist()</span></code></pre></div>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://ohmeow.com/posts/2022-04-25-ajtfb-chapter-9_files/figure-html/cell-64-output-1.png" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
<p>Second, built a <strong>partial dependence plot</strong></p>
<div class="callout callout-style-default 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">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>“Partial dependence plots answer the question: <strong>if a row varied on nothing other than the feature in question, how would it impact the dependent variable?</strong></p>
</div>
</div>
<p>See pp.309-10 for info on how to do this, but in essence, we are attempting to isolate the effects of changes to a single variable.</p>
<div id="cell-120" class="cell" data-outputid="47f89532-fe3a-42b1-a4b1-0e73d76cdd43">
<div class="sourceCode cell-code" id="cb94" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb94-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> sklearn.inspection <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> PartialDependenceDisplay</span>
<span id="cb94-2"></span>
<span id="cb94-3">fig, ax <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> plt.subplots(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;">12</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>))</span>
<span id="cb94-4">PartialDependenceDisplay.from_estimator(</span>
<span id="cb94-5">    m, valid_xs_final, [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"YearMade"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ProductSize"</span>], grid_resolution<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;">20</span>, ax<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>ax</span>
<span id="cb94-6">)</span></code></pre></div>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://ohmeow.com/posts/2022-04-25-ajtfb-chapter-9_files/figure-html/cell-65-output-1.png" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
<p><strong>Intrepretation</strong></p>
<p>The “YearMade” plot makes sense as it shows a linear relationship with price (“remember that our dependent variable is <em>after</em> taking the logarithm, so this means that in practice there is an exponential increase in price). Again, this is expected given that <strong>depreciation</strong> =”a multiplicative factor over time … varying year made ought to show an exponential relationship to sales price”</p>
<p>The “ProductSize” should raise concerns, “it shows that for the final group, <strong>which we saw is for missing values</strong>, has the lowest price.</p>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>If you see an unusual relationship like this between a variable and the target, you want to understand why there are missing values and what a missing value means!</p>
</div>
</div>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>Missing values can sometimes be useful predictors</p>
</div>
</div>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>Missing values can sometimes indicate data leakage.</p>
</div>
</div>
<p><strong>What is “data leakage”?</strong></p>
<p>“The introduction of information about the target of a data mining problem, which should not be legitimately available to mine from.” The idea is that you’re cheating by introducing something by way of the independent variables that biases your predictions favorably that you won’t be able to utlize at inference time. See p.311-12 for examples.</p>
<p><strong>How to determine if you have data leakage?</strong></p>
<p>From p.321 … “build a model and then …</p>
<ul>
<li>Check whether <strong>the accuracy of the model is too good</strong> to be true.</li>
<li>Look for <strong>important predictors that don’t make sense in pratice</strong>.</li>
<li>Look for <strong>partial dependence plot results that don’t make sense in practice</strong>. (see above)</li>
</ul>
<div class="callout callout-style-default callout-tip 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">
Tip
</div>
</div>
<div class="callout-body-container callout-body">
<p>“… often a good idea to build a model first and then do you data cleaning rather than vice versa … <strong>can help you identify potentially problematic data issues</strong>.</p>
</div>
</div>
</section>
<section id="for-predicting-a-specific-row-of-data-what-were-the-most-important-factors-and-how-did-they-influence-the-prediction" class="level4">
<h4 class="anchored" data-anchor-id="for-predicting-a-specific-row-of-data-what-were-the-most-important-factors-and-how-did-they-influence-the-prediction">For predicting a specific row of data, what were the most important factors and how did they influence the prediction?</h4>
<p>Answer: Use <code>treeinterpreter</code>. Note that:</p>
<p><strong>prediction</strong> = the prediction made by RF</p>
<p><strong>bias</strong> = the prediction based on taking the mean of the dependent variable (the root model for every tree)</p>
<p><strong>contributions</strong> = “tells us the total change in prediction due to <strong>each</strong> of the independent variables.</p>
<p>“Therfore, <strong>the sum of <code>contributions</code> plus <code>bias</code> must equal the <code>prediction</code></strong> for each row!</p>
<div id="cell-123" class="cell">
<div class="sourceCode cell-code" id="cb95" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb95-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> treeinterpreter <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> treeinterpreter</span></code></pre></div>
</div>
<div id="cell-124" class="cell">
<div class="sourceCode cell-code" id="cb96" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb96-1">row <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> valid_xs_final.iloc[:<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>]</span></code></pre></div>
</div>
<div id="cell-125" class="cell">
<div class="sourceCode cell-code" id="cb97" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb97-1">pred, bias, contributions <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> treeinterpreter.predict(m, row.values)</span></code></pre></div>
</div>
<div id="cell-126" class="cell" data-outputid="6361237b-ee29-4c12-cee7-08781dd98602">
<div class="sourceCode cell-code" id="cb98" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb98-1">pred[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>], bias[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>], contributions[<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;">sum</span>()</span></code></pre></div>
<div class="cell-output cell-output-display" data-execution_count="78">
<pre><code>(array([10.00298786]), 10.104457702350853, -0.10146984568626016)</code></pre>
</div>
</div>
<p><strong>What is the best waty to visualize this?</strong></p>
<p>Answer: A waterfull plot will show us “how the positive and negative contributions from all the independent variables sum up to create the final prediction.”</p>
<div id="cell-128" class="cell">
<div class="sourceCode cell-code" id="cb100" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb100-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> waterfall_chart</span></code></pre></div>
</div>
<div id="cell-129" class="cell" data-outputid="f5a06de3-f1cc-48db-b8ce-3c6d1c9b6d6e">
<div class="sourceCode cell-code" id="cb101" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb101-1">waterfall_chart.plot(</span>
<span id="cb101-2">    valid_xs_final.columns,</span>
<span id="cb101-3">    contributions[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>],</span>
<span id="cb101-4">    threshold<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.08</span>,</span>
<span id="cb101-5">    rotation_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;">45</span>,</span>
<span id="cb101-6">    formatting<span 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="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{:,.3f}</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>,</span>
<span id="cb101-7">)</span></code></pre></div>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://ohmeow.com/posts/2022-04-25-ajtfb-chapter-9_files/figure-html/cell-71-output-1.png" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
<p><strong>Where is this information useful?</strong></p>
<p>Answer: In production “rather than during model development. You can <strong>use it to provide useful information to users of your data product about underlying reasoning behind the predictions.</strong>”</p>
<hr>
</section>
</section>
<section id="the-extrapolation-problem" class="level3">
<h3 class="anchored" data-anchor-id="the-extrapolation-problem">The “Extrapolation” problem</h3>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>“Random forests are not able to extrapolate the types of data they have seen … <strong>that’s why we need to make sure our validation set does not contina out-of-domain data</strong>.”</p>
</div>
</div>
<p>See. pp.315-316.</p>
<p><strong>How do determine if our “test set” is distributed in the same way as our “training set”, and if it isn’t, what columns are causing the difference?</strong></p>
<p>Answer: Use a random forest where we “try to predict whether a row is in the validation set or training set.”</p>
<div id="cell-132" class="cell">
<div class="sourceCode cell-code" id="cb102" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb102-1">combined_df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> pd.concat([train_xs_final, valid_xs_final])</span>
<span id="cb102-2">is_valid <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.array([<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;">len</span>(train_xs_final) <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> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(valid_xs_final))</span></code></pre></div>
</div>
<div id="cell-133" class="cell">
<div class="sourceCode cell-code" id="cb103" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb103-1">ood_m <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> fit_rf(combined_df, is_valid)</span></code></pre></div>
</div>
<div id="cell-134" class="cell" data-outputid="79def2fa-7a5a-4647-f69a-1160280b90b1">
<div class="sourceCode cell-code" id="cb104" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb104-1">rf_feature_importance(ood_m, combined_df)[:<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span>]</span></code></pre></div>
<div class="cell-output cell-output-display" data-execution_count="90">

  <div id="df-5528b310-ecd3-4744-8c8c-ef000290f147">
    <div class="colab-df-container">
      <div>


<table class="dataframe caption-top table table-sm table-striped small" data-quarto-postprocess="true" data-border="1">
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th">cols</th>
<th data-quarto-table-cell-role="th">imp</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td data-quarto-table-cell-role="th">5</td>
<td>saleElapsed</td>
<td>0.900343</td>
</tr>
<tr class="even">
<td data-quarto-table-cell-role="th">9</td>
<td>SalesID</td>
<td>0.073015</td>
</tr>
<tr class="odd">
<td data-quarto-table-cell-role="th">14</td>
<td>MachineID</td>
<td>0.023312</td>
</tr>
<tr class="even">
<td data-quarto-table-cell-role="th">0</td>
<td>YearMade</td>
<td>0.001036</td>
</tr>
<tr class="odd">
<td data-quarto-table-cell-role="th">6</td>
<td>ModelID</td>
<td>0.000405</td>
</tr>
<tr class="even">
<td data-quarto-table-cell-role="th">10</td>
<td>Enclosure</td>
<td>0.000402</td>
</tr>
</tbody>
</table>

</div>
      <button class="colab-df-convert" onclick="convertToInteractive('df-5528b310-ecd3-4744-8c8c-ef000290f147')" title="Convert this dataframe to an interactive table." style="display:none;">
        
  <svg xmlns="http://www.w3.org/2000/svg" height="24px" viewbox="0 0 24 24" width="24px">
    <path d="M0 0h24v24H0V0z" fill="none"></path>
    <path d="M18.56 5.44l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94zm-11 1L8.5 8.5l.94-2.06 2.06-.94-2.06-.94L8.5 2.5l-.94 2.06-2.06.94zm10 10l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94z"></path><path d="M17.41 7.96l-1.37-1.37c-.4-.4-.92-.59-1.43-.59-.52 0-1.04.2-1.43.59L10.3 9.45l-7.72 7.72c-.78.78-.78 2.05 0 2.83L4 21.41c.39.39.9.59 1.41.59.51 0 1.02-.2 1.41-.59l7.78-7.78 2.81-2.81c.8-.78.8-2.07 0-2.86zM5.41 20L4 18.59l7.72-7.72 1.47 1.35L5.41 20z"></path>
  </svg>
      </button>
      
  <style>
    .colab-df-container {
      display:flex;
      flex-wrap:wrap;
      gap: 12px;
    }

    .colab-df-convert {
      background-color: #E8F0FE;
      border: none;
      border-radius: 50%;
      cursor: pointer;
      display: none;
      fill: #1967D2;
      height: 32px;
      padding: 0 0 0 0;
      width: 32px;
    }

    .colab-df-convert:hover {
      background-color: #E2EBFA;
      box-shadow: 0px 1px 2px rgba(60, 64, 67, 0.3), 0px 1px 3px 1px rgba(60, 64, 67, 0.15);
      fill: #174EA6;
    }

    [theme=dark] .colab-df-convert {
      background-color: #3B4455;
      fill: #D2E3FC;
    }

    [theme=dark] .colab-df-convert:hover {
      background-color: #434B5C;
      box-shadow: 0px 1px 3px 1px rgba(0, 0, 0, 0.15);
      filter: drop-shadow(0px 1px 2px rgba(0, 0, 0, 0.3));
      fill: #FFFFFF;
    }
  </style>

      <script>
        const buttonEl =
          document.querySelector('#df-5528b310-ecd3-4744-8c8c-ef000290f147 button.colab-df-convert');
        buttonEl.style.display =
          google.colab.kernel.accessAllowed ? 'block' : 'none';

        async function convertToInteractive(key) {
          const element = document.querySelector('#df-5528b310-ecd3-4744-8c8c-ef000290f147');
          const dataTable =
            await google.colab.kernel.invokeFunction('convertToInteractive',
                                                     [key], {});
          if (!dataTable) return;

          const docLinkHtml = 'Like what you see? Visit the ' +
            '<a target="_blank" href=https://colab.research.google.com/notebooks/data_table.ipynb>data table notebook</a>'
            + ' to learn more about interactive tables.';
          element.innerHTML = '';
          dataTable['output_type'] = 'display_data';
          await google.colab.output.renderOutput(dataTable, element);
          const docLink = document.createElement('div');
          docLink.innerHTML = docLinkHtml;
          element.appendChild(docLink);
        }
      </script>
    </div>
  </div>
  
</div>
</div>
<p>“This shows that three columns differ significantly between the training and validation sets: saleElapsed, SalesID, and MachineID’</p>
<p>See p.317 for infering what this is.</p>
<p><strong>What to do with this info?</strong></p>
<p>Answer: Compare the effects of removing each of these columns with the original model</p>
<div id="cell-136" class="cell" data-outputid="38c0472c-6b4b-4770-edb5-81196c927975">
<div class="sourceCode cell-code" id="cb105" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb105-1">m <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> fit_rf(train_xs_final, train_y)</span>
<span id="cb105-2"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"orig:"</span>, m_rmse(m, valid_xs_final, valid_y))</span></code></pre></div>
<div class="cell-output cell-output-stdout">
<pre><code>orig: 0.231632</code></pre>
</div>
</div>
<div id="cell-137" class="cell" data-outputid="7414a984-6835-44ca-90e2-a50076f4b234">
<div class="sourceCode cell-code" id="cb107" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb107-1"><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="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"SalesID"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"saleElapsed"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"MachineID"</span>):</span>
<span id="cb107-2">    m <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> fit_rf(train_xs_final.drop(c, axis<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>), train_y)</span>
<span id="cb107-3">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(c, m_rmse(m, valid_xs_final.drop(c, axis<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>), valid_y))</span></code></pre></div>
<div class="cell-output cell-output-stdout">
<pre><code>SalesID 0.231139
saleElapsed 0.235471
MachineID 0.229936</code></pre>
</div>
</div>
<p>“… looks like we should be able to remove SaleID and MachineID without losing any accuracy”</p>
<div id="cell-139" class="cell">
<div class="sourceCode cell-code" id="cb109" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb109-1">time_vars <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"SalesID"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"MachineID"</span>]</span>
<span id="cb109-2">train_xs_final_time <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> train_xs_final.drop(time_vars, axis<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="cb109-3">valid_xs_final_time <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> valid_xs_final.drop(time_vars, axis<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 id="cell-140" class="cell" data-outputid="bb58e3d6-4c4b-4871-afb9-d3159b9820e9">
<div class="sourceCode cell-code" id="cb110" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb110-1">m <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> fit_rf(train_xs_final_time, train_y)</span>
<span id="cb110-2">m_rmse(m, valid_xs_final_time, valid_y)</span></code></pre></div>
<div class="cell-output cell-output-display" data-execution_count="95">
<pre><code>0.228524</code></pre>
</div>
</div>
<div class="callout callout-style-default 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">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>“Removing these variables has slightly improved the model’s accuracy; but more importantly, <strong>it should make it more resilient over time, and eaiser to maintain and understand</strong>.”</p>
</div>
</div>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>Build a model where the dependent variable is <code>is_valid</code> for ALL datasets!</p>
</div>
</div>
<p>“It can often uncovere subtle <strong><em>domain shift</em></strong> issues that you may otherwise miss.</p>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>“One thing that might help in our case is simply to avoid using old data”</p>
</div>
</div>
<p>“Often, old data shows relationships that just aren’t valid anymore”</p>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>This “shows you shouldn’t always use your entire dataset; sometimes a subset can be better.”</p>
</div>
</div>
<div id="cell-142" class="cell" data-outputid="a17ed45d-0a92-4177-9b68-861b0bcd2e5a">
<div class="sourceCode cell-code" id="cb112" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb112-1">train_xs[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"saleYear"</span>].hist()</span></code></pre></div>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://ohmeow.com/posts/2022-04-25-ajtfb-chapter-9_files/figure-html/cell-79-output-1.png" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
<div id="cell-143" class="cell">
<div class="sourceCode cell-code" id="cb113" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb113-1">recent_sales <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> train_xs[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"saleYear"</span>] <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;">2004</span></span>
<span id="cb113-2"></span>
<span id="cb113-3">train_xs_recent <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> train_xs_final_time[recent_sales]</span>
<span id="cb113-4">train_y <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> train_y[recent_sales]</span></code></pre></div>
</div>
<div id="cell-144" class="cell" data-outputid="4711fa67-4be2-4025-fed5-e2f6034c34c1">
<div class="sourceCode cell-code" id="cb114" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb114-1">m <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> fit_rf(train_xs_recent, train_y)</span>
<span id="cb114-2">m_rmse(m, train_xs_recent, train_y), m_rmse(m, valid_xs_final_time, valid_y)</span></code></pre></div>
<div class="cell-output cell-output-display" data-execution_count="100">
<pre><code>(0.177533, 0.229519)</code></pre>
</div>
</div>
</section>
</section>
<section id="approach-3-neural-networks" class="level2">
<h2 class="anchored" data-anchor-id="approach-3-neural-networks">Approach 3: Neural Networks</h2>
<div class="callout callout-style-default callout-tip 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">
Tip
</div>
</div>
<div class="callout-body-container callout-body">
<p>“We can leverage the work we did to trim unwanted columns in the random forest by using the same set of columns”</p>
</div>
</div>
<div id="cell-146" class="cell">
<div class="sourceCode cell-code" id="cb116" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb116-1">nn_df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> pd.read_csv(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;">"TrainAndValid.csv"</span>, low_memory<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="cb116-2"></span>
<span id="cb116-3">sizes <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Large"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Large / Medium"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Medium"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Small"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Mini"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Compact"</span>]</span>
<span id="cb116-4">nn_df.ProductSize <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> nn_df.ProductSize.astype(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"category"</span>)</span>
<span id="cb116-5">nn_df.ProductSize <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> nn_df.ProductSize.cat.set_categories(</span>
<span id="cb116-6">    sizes, ordered<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="cb116-7">)  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># note: "inplace=True" is depreciated as of 1.30</span></span>
<span id="cb116-8"></span>
<span id="cb116-9">nn_df[dep_var] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.log(nn_df[dep_var])</span>
<span id="cb116-10"></span>
<span id="cb116-11">nn_df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> add_datepart(nn_df, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"saledate"</span>)</span></code></pre></div>
</div>
<div id="cell-147" class="cell">
<div class="sourceCode cell-code" id="cb117" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb117-1">nn_df_final <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> nn_df[<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>(train_xs_final_time.columns) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> [dep_var]]</span></code></pre></div>
</div>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p><strong>Categorical columns</strong> require embeddings.</p>
</div>
</div>
<p>fastai uses the <code>max_card</code> to determine what columns should be treated as categoricals … “Embedding sizes larger that 10,000 should generaly be used only after you’ve tested whether there are better ways to group the variable”</p>
<div id="cell-149" class="cell">
<div class="sourceCode cell-code" id="cb118" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb118-1">nn_cont, nn_cat <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> cont_cat_split(nn_df_final, max_card<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;">9000</span>, dep_var<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>dep_var)</span></code></pre></div>
</div>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>“A categorical variable cannot, by definition, extrapolate outside the range of values that it has seen, **but we want to be able to predict auction sale prices in the future”</p>
</div>
</div>
<p>Therfore, “saleElapsed” needs to be made into a continous variable … which it alread is</p>
<div id="cell-151" class="cell" data-outputid="7bd5362f-4170-47be-9a1f-20a2879280b0">
<div class="sourceCode cell-code" id="cb119" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb119-1">nn_cont</span></code></pre></div>
<div class="cell-output cell-output-display" data-execution_count="128">
<pre><code>['saleElapsed']</code></pre>
</div>
</div>
<p><strong>How to find the cardinality of each categorical?</strong></p>
<div id="cell-153" class="cell" data-outputid="ec5a34f3-0e6f-4cd6-f42d-525607944f52">
<div class="sourceCode cell-code" id="cb121" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb121-1">nn_df_final[nn_cat].nunique()</span></code></pre></div>
<div class="cell-output cell-output-display" data-execution_count="129">
<pre><code>YearMade                73
ProductSize              6
Coupler_System           2
fiProductClassDesc      74
Hydraulics_Flow          3
ModelID               5281
fiSecondaryDesc        177
fiModelDesc           5059
Enclosure                6
Hydraulics              12
ProductGroup             6
fiModelDescriptor      140
Tire_Size               17
Drive_System             4
dtype: int64</code></pre>
</div>
</div>
<p>“… two variables pertaining to the ‘model’ of the equipment, <strong>both with similar very high cardinalities</strong>, suggests that they may contain similar, redundant information.”</p>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>Removing rendundant columns can make your model more efficient! Try and see what the impact is.</p>
</div>
</div>
<div id="cell-155" class="cell" data-outputid="8b2a7fe2-683c-4fae-a26a-fbe0cce5abc0">
<div class="sourceCode cell-code" id="cb123" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb123-1">cols_to_drop <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"fiModelDescriptor"</span>]</span>
<span id="cb123-2">train_xs_recent2 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> train_xs_recent.drop(cols_to_drop, axis<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="cb123-3">valid_xs_recent2 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> valid_xs_final_time.drop(cols_to_drop, axis<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="cb123-4"></span>
<span id="cb123-5">m2 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> fit_rf(train_xs_recent2, train_y)</span>
<span id="cb123-6">m_rmse(m2, train_xs_recent2, train_y), m_rmse(m2, valid_xs_recent2, valid_y)</span></code></pre></div>
<div class="cell-output cell-output-display" data-execution_count="130">
<pre><code>(0.176776, 0.230194)</code></pre>
</div>
</div>
<div id="cell-156" class="cell">
<div class="sourceCode cell-code" id="cb125" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb125-1">nn_cat.remove(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"fiModelDescriptor"</span>)</span></code></pre></div>
</div>
<div id="cell-157" class="cell" data-outputid="75e03a10-ea84-4fc9-ff5c-7a91d534206b">
<div class="sourceCode cell-code" id="cb126" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb126-1"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(nn_cont)</span>
<span id="cb126-2"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(nn_cat)</span></code></pre></div>
<div class="cell-output cell-output-stdout">
<pre><code>['saleElapsed']
['YearMade', 'ProductSize', 'Coupler_System', 'fiProductClassDesc', 'Hydraulics_Flow', 'ModelID', 'fiSecondaryDesc', 'fiModelDesc', 'Enclosure', 'Hydraulics', 'ProductGroup', 'Tire_Size', 'Drive_System']</code></pre>
</div>
</div>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>Neural networks require <strong>normalization</strong> while random forest does not because neural networks care about scaling!</p>
</div>
</div>
<div id="cell-159" class="cell">
<div class="sourceCode cell-code" id="cb128" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb128-1">nn_procs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [Categorify, FillMissing, Normalize]</span>
<span id="cb128-2"></span>
<span id="cb128-3">nn_to <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> TabularPandas(</span>
<span id="cb128-4">    nn_df_final, nn_procs, nn_cat, nn_cont, splits<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>splits, y_names<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>dep_var</span>
<span id="cb128-5">)</span></code></pre></div>
</div>
<div class="callout callout-style-default 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">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>“Tabular models and data don’t generally require much GPU RAM, so we can use larger batch sizes”</p>
</div>
</div>
<div id="cell-161" class="cell">
<div class="sourceCode cell-code" id="cb129" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb129-1">dls <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> nn_to.dataloaders(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;">1024</span>)</span></code></pre></div>
</div>
<div class="callout callout-style-default callout-tip 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">
Tip
</div>
</div>
<div class="callout-body-container callout-body">
<p>“it’s a good idea to set <code>y_range</code> for regression models</p>
</div>
</div>
<div id="cell-163" class="cell" data-outputid="c78a95eb-595e-4bec-9e75-17a445ccca07">
<div class="sourceCode cell-code" id="cb130" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb130-1">y <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> nn_to.train.y</span>
<span id="cb130-2">y.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">min</span>(), y.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">max</span>()</span></code></pre></div>
<div class="cell-output cell-output-display" data-execution_count="135">
<pre><code>(8.465899467468262, 11.863582611083984)</code></pre>
</div>
</div>
<div class="callout callout-style-default callout-tip 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">
Tip
</div>
</div>
<div class="callout-body-container callout-body">
<p>The default number of hidden layers (200,100) work well for small datasets, but should be increased if you are working with a larger dataset (500,250) for example.</p>
</div>
</div>
<div id="cell-165" class="cell">
<div class="sourceCode cell-code" id="cb132" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb132-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> fastai.tabular.<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="cb132-2"></span>
<span id="cb132-3">learn <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tabular_learner(</span>
<span id="cb132-4">    dls, y_range<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="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">12</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;">500</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">250</span>], n_out<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>, loss_func<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>F.mse_loss</span>
<span id="cb132-5">)</span></code></pre></div>
</div>
<div id="cell-166" class="cell" data-outputid="7c1afce9-2281-4b51-9122-bfe53ac40c55">
<div class="sourceCode cell-code" id="cb133" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb133-1">learn.lr_find()</span></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-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-display" data-execution_count="137">
<pre><code>SuggestedLRs(valley=0.00015848931798245758)</code></pre>
</div>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://ohmeow.com/posts/2022-04-25-ajtfb-chapter-9_files/figure-html/cell-94-output-4.png" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
<div class="callout callout-style-default 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">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>There is no need to fine tune since we aren’t starting with a pretrained model.</p>
</div>
</div>
<div id="cell-168" class="cell" data-outputid="eabcde0b-dffb-4ebb-a8db-ebe3e911eaee">
<div class="sourceCode cell-code" id="cb135" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb135-1">learn.fit_one_cycle(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1e-2</span>)</span></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-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-quarto-postprocess="true" 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">time</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>0</td>
<td>0.062468</td>
<td>0.063260</td>
<td>00:15</td>
</tr>
<tr class="even">
<td>1</td>
<td>0.053739</td>
<td>0.074410</td>
<td>00:15</td>
</tr>
<tr class="odd">
<td>2</td>
<td>0.047957</td>
<td>0.055398</td>
<td>00:15</td>
</tr>
<tr class="even">
<td>3</td>
<td>0.042492</td>
<td>0.050278</td>
<td>00:15</td>
</tr>
<tr class="odd">
<td>4</td>
<td>0.039967</td>
<td>0.050096</td>
<td>00:14</td>
</tr>
</tbody>
</table>
</div>
</div>
<div id="cell-169" class="cell" data-outputid="03548118-8497-4b94-ce6c-57eb59a0cba7">
<div class="sourceCode cell-code" id="cb136" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb136-1">preds, targs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> learn.get_preds()</span>
<span id="cb136-2">r_mse(preds, targs)</span></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-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-display" data-execution_count="140">
<pre><code>0.223821</code></pre>
</div>
</div>
<div id="cell-170" class="cell" data-outputid="19103328-e05b-40e1-aecb-c9546a5a0124">
<div class="sourceCode cell-code" id="cb138" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb138-1">learn.save(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"nn"</span>)</span></code></pre></div>
<div class="cell-output cell-output-display" data-execution_count="141">
<pre><code>Path('models/nn.pth')</code></pre>
</div>
</div>
</section>
<section id="approach-4-boosting" class="level2">
<h2 class="anchored" data-anchor-id="approach-4-boosting">Approach 4: Boosting</h2>
<p>Here “we add models instead of averaging them” (as compared to ensembling). See p.323-24 for all the details, but here’s how it works in general:</p>
<ol type="1">
<li>Train small model that underfits</li>
<li>Get predictions for model from #1</li>
<li>Get the “residuals” (‘the error for each point in the training set’) by subtracting the predictions from the targets.</li>
<li>Go back to step 1, “<strong>but instead of using the original targets, use the residuals as the targets</strong> for training.</li>
<li>Continue stesp 1-4 until you need to stop (e.g., max number of trees, you start overfitting, etc…)</li>
</ol>
<p>Steps 3-4 are the bread and butter of things.</p>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>“… each new tree will be attempting to fit the error of all of the previous trees combined. Because we are continually creating new residuals by subtracting the predictions of each new tree from the residulas from the previous tree, the residuals will get smaller and smaller.”</p>
</div>
</div>
<p>Some go as far as saying that such models are all you need :)</p>
<blockquote class="twitter-tweet blockquote" data-theme="dark">
<p lang="en" dir="ltr">
XGBoost Is All You Need<br><br>Deep Neural Networks and Tabular Data: A Survey<a href="https://t.co/Z2KsHP3fvp">https://t.co/Z2KsHP3fvp</a> <a href="https://t.co/uh5NLS1fVP">pic.twitter.com/uh5NLS1fVP</a>
</p>
— Bojan Tunguz (<span class="citation" data-cites="tunguz">@tunguz</span>) <a href="https://twitter.com/tunguz/status/1509197350576672769?ref_src=twsrc%5Etfw">March 30, 2022</a>
</blockquote>
<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
<p><strong>How do you make predictions with an ensemble of boosted trees?</strong></p>
<p>Answer: By calculating the predictions from each tree and then <strong>adding them all together.</strong></p>
<div class="callout callout-style-default 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">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>“… unlike with random forests, with this approach, there is nothing to stop us from overfitting …. in a boosted ensemble, <strong>the more trees you have, the better the training error becomes, and eventually you will see overfitting on the validation set.</strong>”</p>
</div>
</div>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>“Unlike random forests, gradient boosted trees are extremely sensitive to the choices of these hyperparameters.”</p>
</div>
</div>
<p>XGBoost and sklearn’s HistGradientBooting models are legit ML models to try …</p>
<blockquote class="twitter-tweet blockquote" data-theme="dark">
<p lang="en" dir="ltr">
Here are my top used ML algos for tabular data problems:<br><br>1. XGBoost<br>2. HistGradientBoosting<br>3. Logistic regression/ Ridge regression<br>4. LightGBM<br>5. MLP<br>6. A blend of 1. And 5.
</p>
— Bojan Tunguz (<span class="citation" data-cites="tunguz">@tunguz</span>) <a href="https://twitter.com/tunguz/status/1517505710426406914?ref_src=twsrc%5Etfw">April 22, 2022</a>
</blockquote>
<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
</section>
<section id="other-things-to-try" class="level2">
<h2 class="anchored" data-anchor-id="other-things-to-try">Other things to try</h2>
<p><strong>Ensembling</strong> (pp.322-23)</p>
<p>This is a form of “bagging” where <strong>averaging the predictions of models trained using different algorithms</strong>, each of which it is reasonable to expect would produce differnt kinds of errors, would likely product better predictions.</p>
<p><strong>Combining embeddings with other models</strong> (pp.324-25)</p>
<p>“… shows that you can get much of the performance improvement of a neural network without having to use a neural network as inference time” by using the embeddings as inputs (which are just array lookups) to small decision tree ensemble!</p>
</section>
<section id="in-summary" class="level2">
<h2 class="anchored" data-anchor-id="in-summary">In summary</h2>
<div class="callout callout-style-default callout-tip 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">
Tip
</div>
</div>
<div class="callout-body-container callout-body">
<p>Start with a random forest!</p>
</div>
</div>
<p>“This will give you a strong baseline … can then use that model for feature selection and partial dependence analysis to get a better understanding of your data.”</p>
<p><strong>Pros/Cons of each approach:</strong></p>
<p><strong>Random forests</strong>: Pros:</p>
<ul>
<li>Easiest to train</li>
<li>Resiliant to hyperparameter choices</li>
<li>Require little preprocessing</li>
<li>Fast to train</li>
<li>Should not overfit if you have enough trees Cons:</li>
<li>Can be less accurate (esp.&nbsp;if extrapolation is required “such as predicting future time periods.”</li>
</ul>
<p><strong>Gradient boosting machines (GBMs)</strong>: Pros:</p>
<ul>
<li>Often more accurate than random forests Cons:</li>
<li>Sensitive to hyperparmeter choices</li>
<li>Can overfit</li>
</ul>
<p><strong>Neural Networks</strong>: Pros:</p>
<ul>
<li>Can extrapolate well</li>
<li>Can provide good results. Cons:</li>
<li>Take longest time to train</li>
<li>Require extra preprocessing (e.g., normalization)</li>
</ul>
</section>
<section id="resources" class="level2">
<h2 class="anchored" data-anchor-id="resources">Resources</h2>
<ol type="1">
<li><p>https://book.fast.ai - The book’s website; it’s updated regularly with new content and recommendations from everything to GPUs to use, how to run things locally and on the cloud, etc…</p></li>
<li><p><a href="https://www.packtpub.com/product/hands-on-gradient-boosting-with-xgboost-and-scikit-learn/9781839218354">“Hands-On Gradient Boosting with XGBoost and scikit-learn”</a> - Unread personally, but on my bookshelf and recommended by those in the know.</p></li>
<li><p><a href="https://timeseriesai.github.io/tsai/">tsai</a> - A time series/sequences focused library built on PyTorch and fastai by <a href="https://twitter.com/ignaciooguiza">Ignacio Oguiza</a></p></li>
</ol>


</section>

 ]]></description>
  <category>fastai</category>
  <category>fastbook</category>
  <category>tabular</category>
  <category>structured</category>
  <category>decision trees</category>
  <category>random forest</category>
  <category>embeddings</category>
  <category>categorical variables</category>
  <category>boosting</category>
  <category>gdbt</category>
  <category>xgboost</category>
  <guid>https://ohmeow.com/posts/2022-04-25-ajtfb-chapter-9.html</guid>
  <pubDate>Mon, 25 Apr 2022 07:00:00 GMT</pubDate>
  <media:content url="https://ohmeow.com/posts/images/fastbook.jpg" medium="image" type="image/jpeg"/>
</item>
<item>
  <title>A Journey Through Fastbook (AJTFB) - Chapter 8: Collaborative Filtering</title>
  <dc:creator>Wayde Gilliam</dc:creator>
  <link>https://ohmeow.com/posts/2022-03-31-ajtfb-chapter-8.html</link>
  <description><![CDATA[ 




<p>Other posts in this series:</p>
<p><a href="../posts/2020-11-06-ajtfb-chapter-1.html">A Journey Through Fastbook (AJTFB) - Chapter 1</a><br>
<a href="../posts/2020-11-16-ajtfb-chapter-2.html">A Journey Through Fastbook (AJTFB) - Chapter 2</a><br>
<a href="../posts/2020-11-22-ajtfb-chapter-3.html">A Journey Through Fastbook (AJTFB) - Chapter 3</a><br>
<a href="../posts/2021-05-23-ajtfb-chapter-4.html">A Journey Through Fastbook (AJTFB) - Chapter 4</a><br>
<a href="../posts/2021-06-03-ajtfb-chapter-5.html">A Journey Through Fastbook (AJTFB) - Chapter 5</a><br>
<a href="../posts/2021-06-10-ajtfb-chapter-6-multilabel.html">A Journey Through Fastbook (AJTFB) - Chapter 6a</a><br>
<a href="../posts/2022-02-09-ajtfb-chapter-6-regression.html">A Journey Through Fastbook (AJTFB) - Chapter 6b</a><br>
<a href="../posts/2022-03-28-ajtfb-chapter-7.html">A Journey Through Fastbook (AJTFB) - Chapter 7</a><br>
<a href="../posts/2022-04-25-ajtfb-chapter-9.html">A Journey Through Fastbook (AJTFB) - Chapter 9</a></p>
<section id="collaborative-filtering" class="level2">
<h2 class="anchored" data-anchor-id="collaborative-filtering">Collaborative Filtering</h2>
<p><strong>What is it?</strong></p>
<p>Think recommender systems which “look at which products the current user has used or liked, find other users who have used or liked similar products, and then recommend other products that those users have used or liked.”</p>
<p>The key to making collaborative filtering and tabular models, is the idea of <strong>latent factors</strong>.</p>
</section>
<section id="what-are-latent-factors-and-what-is-the-problem-they-solve" class="level2">
<h2 class="anchored" data-anchor-id="what-are-latent-factors-and-what-is-the-problem-they-solve">What are “latent factors” and what is the problem they solve?</h2>
<p>Remember that models can only work with numbers, and while something like “price” can be used to accurately reflect the value of a house, how do we represent numerically concepts like the day of week, the make/model of a car, or the job function of an employee?</p>
<p>The answer is with latent factors.</p>
<p>In a nutshell, latent factors are numbers associated to a thing (e.g., day of week, model of car, job function, etc…) that are <strong>learnt</strong> during model training. At the end this process, we have numbers that provide a representation of the thing we can use and explore in a variety of ways. These factors are called “latent” because we don’t know what they are beforehand.</p>
<div class="callout callout-style-default 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">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>The learnt numbers for “a thing” may vary to one degree or another based on the data used during training and your objective. For example, what “Sunday” means may be represented differently when you are trying to forecast how many bottle of scotch will be sold that day than if you were trying to predict the number of options that will be traded for a certain equity.</p>
</div>
</div>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>Latent factors allows us to learn a numerical representation of a thing (especially those for which a single number would not do it justice)</p>
</div>
</div>
<p>If we had something like this …</p>
<p><img src="https://raw.githubusercontent.com/fastai/fastbook/035016fb0cc826542aef77864f36df88a5055d06/images/att_00040.png" class="img-fluid"></p>
<p>… how could we predict what users would rate movies they have yet to see? Let’s take a look.</p>
<div id="cell-6" class="cell" data-outputid="a623b75c-6bc4-4dd9-f0c6-1d39b12d5586" data-execution_count="3">
<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="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> fastai.collab <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="cb1-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> fastai.tabular.<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="cb1-3"></span>
<span id="cb1-4">path <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> untar_data(URLs.ML_100k)</span></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-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {
        background: #F44336;
    }
</style>
</div>
<div class="cell-output cell-output-display">

    <div>
      <progress value="4931584" class="" max="4924029" style="width:300px; height:20px; vertical-align: middle;"></progress>
      100.15% [4931584/4924029 00:00&lt;00:00]
    </div>
    
</div>
</div>
<div id="cell-7" class="cell" data-outputid="31b36fed-344e-4dfa-93f0-9a62b85554ab" data-execution_count="4">
<div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb2-1">ratings_df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> pd.read_csv(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;">"u.data"</span>, delimiter<span 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;">\t</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>, header<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>, names<span 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="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"movie"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"rating"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"timestamp"</span>])</span>
<span id="cb2-2">ratings_df.head()</span></code></pre></div>
<div class="cell-output cell-output-display" data-execution_count="4">

  <div id="df-c1b3a000-7844-4862-8c52-1d63609e0c57">
    <div class="colab-df-container">
      <div>


<table class="dataframe caption-top table table-sm table-striped small" data-quarto-postprocess="true" data-border="1">
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th">user</th>
<th data-quarto-table-cell-role="th">movie</th>
<th data-quarto-table-cell-role="th">rating</th>
<th data-quarto-table-cell-role="th">timestamp</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td data-quarto-table-cell-role="th">0</td>
<td>196</td>
<td>242</td>
<td>3</td>
<td>881250949</td>
</tr>
<tr class="even">
<td data-quarto-table-cell-role="th">1</td>
<td>186</td>
<td>302</td>
<td>3</td>
<td>891717742</td>
</tr>
<tr class="odd">
<td data-quarto-table-cell-role="th">2</td>
<td>22</td>
<td>377</td>
<td>1</td>
<td>878887116</td>
</tr>
<tr class="even">
<td data-quarto-table-cell-role="th">3</td>
<td>244</td>
<td>51</td>
<td>2</td>
<td>880606923</td>
</tr>
<tr class="odd">
<td data-quarto-table-cell-role="th">4</td>
<td>166</td>
<td>346</td>
<td>1</td>
<td>886397596</td>
</tr>
</tbody>
</table>

</div>
      <button class="colab-df-convert" onclick="convertToInteractive('df-c1b3a000-7844-4862-8c52-1d63609e0c57')" title="Convert this dataframe to an interactive table." style="display:none;">
        
  <svg xmlns="http://www.w3.org/2000/svg" height="24px" viewbox="0 0 24 24" width="24px">
    <path d="M0 0h24v24H0V0z" fill="none"></path>
    <path d="M18.56 5.44l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94zm-11 1L8.5 8.5l.94-2.06 2.06-.94-2.06-.94L8.5 2.5l-.94 2.06-2.06.94zm10 10l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94z"></path><path d="M17.41 7.96l-1.37-1.37c-.4-.4-.92-.59-1.43-.59-.52 0-1.04.2-1.43.59L10.3 9.45l-7.72 7.72c-.78.78-.78 2.05 0 2.83L4 21.41c.39.39.9.59 1.41.59.51 0 1.02-.2 1.41-.59l7.78-7.78 2.81-2.81c.8-.78.8-2.07 0-2.86zM5.41 20L4 18.59l7.72-7.72 1.47 1.35L5.41 20z"></path>
  </svg>
      </button>
      
  <style>
    .colab-df-container {
      display:flex;
      flex-wrap:wrap;
      gap: 12px;
    }

    .colab-df-convert {
      background-color: #E8F0FE;
      border: none;
      border-radius: 50%;
      cursor: pointer;
      display: none;
      fill: #1967D2;
      height: 32px;
      padding: 0 0 0 0;
      width: 32px;
    }

    .colab-df-convert:hover {
      background-color: #E2EBFA;
      box-shadow: 0px 1px 2px rgba(60, 64, 67, 0.3), 0px 1px 3px 1px rgba(60, 64, 67, 0.15);
      fill: #174EA6;
    }

    [theme=dark] .colab-df-convert {
      background-color: #3B4455;
      fill: #D2E3FC;
    }

    [theme=dark] .colab-df-convert:hover {
      background-color: #434B5C;
      box-shadow: 0px 1px 3px 1px rgba(0, 0, 0, 0.15);
      filter: drop-shadow(0px 1px 2px rgba(0, 0, 0, 0.3));
      fill: #FFFFFF;
    }
  </style>

      <script>
        const buttonEl =
          document.querySelector('#df-c1b3a000-7844-4862-8c52-1d63609e0c57 button.colab-df-convert');
        buttonEl.style.display =
          google.colab.kernel.accessAllowed ? 'block' : 'none';

        async function convertToInteractive(key) {
          const element = document.querySelector('#df-c1b3a000-7844-4862-8c52-1d63609e0c57');
          const dataTable =
            await google.colab.kernel.invokeFunction('convertToInteractive',
                                                     [key], {});
          if (!dataTable) return;

          const docLinkHtml = 'Like what you see? Visit the ' +
            '<a target="_blank" href=https://colab.research.google.com/notebooks/data_table.ipynb>data table notebook</a>'
            + ' to learn more about interactive tables.';
          element.innerHTML = '';
          dataTable['output_type'] = 'display_data';
          await google.colab.output.renderOutput(dataTable, element);
          const docLink = document.createElement('div');
          docLink.innerHTML = docLinkHtml;
          element.appendChild(docLink);
        }
      </script>
    </div>
  </div>
  
</div>
</div>
<p>How do we numerically represent user <code>196</code> and movie <code>242</code>? With latent factors we don’t have to know, we can have such a representation learnt using SGD.</p>
<p><strong>How do we set this up?</strong></p>
<ol type="1">
<li><p>“… randomly initialized some parameters [which] will be a set of latent factors for each user and movie.”</p></li>
<li><p>“… to calculate our predictions [take] the <strong>dot product</strong> of each movie with each user.</p></li>
<li><p>“… to calculate our loss … let’s pick mean squared error for now, since that is one reasonable way to represent the accuracy of a prediction”</p></li>
</ol>
<div class="callout callout-style-default 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">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p><strong>dot product</strong> = element-wise multiplication of two vectors summed up.</p>
</div>
</div>
<p>With this in place, “we can optimize our parameters (the latent factors) using stochastic gradient descent, such as to minimize the loss.” In a picture, it looks like this …</p>
<p><img src="https://raw.githubusercontent.com/fastai/fastbook/035016fb0cc826542aef77864f36df88a5055d06/images/att_00041.png" class="img-fluid"></p>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>The parameters we want to optimize <strong><em>are</em></strong> the latent factors!</p>
</div>
</div>
<div id="cell-9" class="cell" data-outputid="9f1c3b53-f3c0-4aa1-8642-595c66806f65" data-execution_count="5">
<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">movies_df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> pd.read_csv(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;">"u.item"</span>, delimiter<span 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>, header<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>, names<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"movie"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"title"</span>], usecols<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="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>), 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>
<span id="cb3-2">movies_df.head()</span></code></pre></div>
<div class="cell-output cell-output-display" data-execution_count="5">

  <div id="df-6bf302d2-df33-49bd-8119-d9f80286a1e0">
    <div class="colab-df-container">
      <div>


<table class="dataframe caption-top table table-sm table-striped small" data-quarto-postprocess="true" data-border="1">
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th">movie</th>
<th data-quarto-table-cell-role="th">title</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td data-quarto-table-cell-role="th">0</td>
<td>1</td>
<td>Toy Story (1995)</td>
</tr>
<tr class="even">
<td data-quarto-table-cell-role="th">1</td>
<td>2</td>
<td>GoldenEye (1995)</td>
</tr>
<tr class="odd">
<td data-quarto-table-cell-role="th">2</td>
<td>3</td>
<td>Four Rooms (1995)</td>
</tr>
<tr class="even">
<td data-quarto-table-cell-role="th">3</td>
<td>4</td>
<td>Get Shorty (1995)</td>
</tr>
<tr class="odd">
<td data-quarto-table-cell-role="th">4</td>
<td>5</td>
<td>Copycat (1995)</td>
</tr>
</tbody>
</table>

</div>
      <button class="colab-df-convert" onclick="convertToInteractive('df-6bf302d2-df33-49bd-8119-d9f80286a1e0')" title="Convert this dataframe to an interactive table." style="display:none;">
        
  <svg xmlns="http://www.w3.org/2000/svg" height="24px" viewbox="0 0 24 24" width="24px">
    <path d="M0 0h24v24H0V0z" fill="none"></path>
    <path d="M18.56 5.44l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94zm-11 1L8.5 8.5l.94-2.06 2.06-.94-2.06-.94L8.5 2.5l-.94 2.06-2.06.94zm10 10l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94z"></path><path d="M17.41 7.96l-1.37-1.37c-.4-.4-.92-.59-1.43-.59-.52 0-1.04.2-1.43.59L10.3 9.45l-7.72 7.72c-.78.78-.78 2.05 0 2.83L4 21.41c.39.39.9.59 1.41.59.51 0 1.02-.2 1.41-.59l7.78-7.78 2.81-2.81c.8-.78.8-2.07 0-2.86zM5.41 20L4 18.59l7.72-7.72 1.47 1.35L5.41 20z"></path>
  </svg>
      </button>
      
  <style>
    .colab-df-container {
      display:flex;
      flex-wrap:wrap;
      gap: 12px;
    }

    .colab-df-convert {
      background-color: #E8F0FE;
      border: none;
      border-radius: 50%;
      cursor: pointer;
      display: none;
      fill: #1967D2;
      height: 32px;
      padding: 0 0 0 0;
      width: 32px;
    }

    .colab-df-convert:hover {
      background-color: #E2EBFA;
      box-shadow: 0px 1px 2px rgba(60, 64, 67, 0.3), 0px 1px 3px 1px rgba(60, 64, 67, 0.15);
      fill: #174EA6;
    }

    [theme=dark] .colab-df-convert {
      background-color: #3B4455;
      fill: #D2E3FC;
    }

    [theme=dark] .colab-df-convert:hover {
      background-color: #434B5C;
      box-shadow: 0px 1px 3px 1px rgba(0, 0, 0, 0.15);
      filter: drop-shadow(0px 1px 2px rgba(0, 0, 0, 0.3));
      fill: #FFFFFF;
    }
  </style>

      <script>
        const buttonEl =
          document.querySelector('#df-6bf302d2-df33-49bd-8119-d9f80286a1e0 button.colab-df-convert');
        buttonEl.style.display =
          google.colab.kernel.accessAllowed ? 'block' : 'none';

        async function convertToInteractive(key) {
          const element = document.querySelector('#df-6bf302d2-df33-49bd-8119-d9f80286a1e0');
          const dataTable =
            await google.colab.kernel.invokeFunction('convertToInteractive',
                                                     [key], {});
          if (!dataTable) return;

          const docLinkHtml = 'Like what you see? Visit the ' +
            '<a target="_blank" href=https://colab.research.google.com/notebooks/data_table.ipynb>data table notebook</a>'
            + ' to learn more about interactive tables.';
          element.innerHTML = '';
          dataTable['output_type'] = 'display_data';
          await google.colab.output.renderOutput(dataTable, element);
          const docLink = document.createElement('div');
          docLink.innerHTML = docLinkHtml;
          element.appendChild(docLink);
        }
      </script>
    </div>
  </div>
  
</div>
</div>
<div id="cell-10" class="cell" data-outputid="9276de48-07c6-482c-8a48-b5cf5f9c09b4" data-execution_count="6">
<div class="sourceCode cell-code" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb4-1">ratings_df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> ratings_df.merge(movies_df)</span>
<span id="cb4-2">ratings_df.head()</span></code></pre></div>
<div class="cell-output cell-output-display" data-execution_count="6">

  <div id="df-c2acc2e3-0500-49b3-8024-c4862062b253">
    <div class="colab-df-container">
      <div>


<table class="dataframe caption-top table table-sm table-striped small" data-quarto-postprocess="true" data-border="1">
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th">user</th>
<th data-quarto-table-cell-role="th">movie</th>
<th data-quarto-table-cell-role="th">rating</th>
<th data-quarto-table-cell-role="th">timestamp</th>
<th data-quarto-table-cell-role="th">title</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td data-quarto-table-cell-role="th">0</td>
<td>196</td>
<td>242</td>
<td>3</td>
<td>881250949</td>
<td>Kolya (1996)</td>
</tr>
<tr class="even">
<td data-quarto-table-cell-role="th">1</td>
<td>63</td>
<td>242</td>
<td>3</td>
<td>875747190</td>
<td>Kolya (1996)</td>
</tr>
<tr class="odd">
<td data-quarto-table-cell-role="th">2</td>
<td>226</td>
<td>242</td>
<td>5</td>
<td>883888671</td>
<td>Kolya (1996)</td>
</tr>
<tr class="even">
<td data-quarto-table-cell-role="th">3</td>
<td>154</td>
<td>242</td>
<td>3</td>
<td>879138235</td>
<td>Kolya (1996)</td>
</tr>
<tr class="odd">
<td data-quarto-table-cell-role="th">4</td>
<td>306</td>
<td>242</td>
<td>5</td>
<td>876503793</td>
<td>Kolya (1996)</td>
</tr>
</tbody>
</table>

</div>
      <button class="colab-df-convert" onclick="convertToInteractive('df-c2acc2e3-0500-49b3-8024-c4862062b253')" title="Convert this dataframe to an interactive table." style="display:none;">
        
  <svg xmlns="http://www.w3.org/2000/svg" height="24px" viewbox="0 0 24 24" width="24px">
    <path d="M0 0h24v24H0V0z" fill="none"></path>
    <path d="M18.56 5.44l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94zm-11 1L8.5 8.5l.94-2.06 2.06-.94-2.06-.94L8.5 2.5l-.94 2.06-2.06.94zm10 10l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94z"></path><path d="M17.41 7.96l-1.37-1.37c-.4-.4-.92-.59-1.43-.59-.52 0-1.04.2-1.43.59L10.3 9.45l-7.72 7.72c-.78.78-.78 2.05 0 2.83L4 21.41c.39.39.9.59 1.41.59.51 0 1.02-.2 1.41-.59l7.78-7.78 2.81-2.81c.8-.78.8-2.07 0-2.86zM5.41 20L4 18.59l7.72-7.72 1.47 1.35L5.41 20z"></path>
  </svg>
      </button>
      
  <style>
    .colab-df-container {
      display:flex;
      flex-wrap:wrap;
      gap: 12px;
    }

    .colab-df-convert {
      background-color: #E8F0FE;
      border: none;
      border-radius: 50%;
      cursor: pointer;
      display: none;
      fill: #1967D2;
      height: 32px;
      padding: 0 0 0 0;
      width: 32px;
    }

    .colab-df-convert:hover {
      background-color: #E2EBFA;
      box-shadow: 0px 1px 2px rgba(60, 64, 67, 0.3), 0px 1px 3px 1px rgba(60, 64, 67, 0.15);
      fill: #174EA6;
    }

    [theme=dark] .colab-df-convert {
      background-color: #3B4455;
      fill: #D2E3FC;
    }

    [theme=dark] .colab-df-convert:hover {
      background-color: #434B5C;
      box-shadow: 0px 1px 3px 1px rgba(0, 0, 0, 0.15);
      filter: drop-shadow(0px 1px 2px rgba(0, 0, 0, 0.3));
      fill: #FFFFFF;
    }
  </style>

      <script>
        const buttonEl =
          document.querySelector('#df-c2acc2e3-0500-49b3-8024-c4862062b253 button.colab-df-convert');
        buttonEl.style.display =
          google.colab.kernel.accessAllowed ? 'block' : 'none';

        async function convertToInteractive(key) {
          const element = document.querySelector('#df-c2acc2e3-0500-49b3-8024-c4862062b253');
          const dataTable =
            await google.colab.kernel.invokeFunction('convertToInteractive',
                                                     [key], {});
          if (!dataTable) return;

          const docLinkHtml = 'Like what you see? Visit the ' +
            '<a target="_blank" href=https://colab.research.google.com/notebooks/data_table.ipynb>data table notebook</a>'
            + ' to learn more about interactive tables.';
          element.innerHTML = '';
          dataTable['output_type'] = 'display_data';
          await google.colab.output.renderOutput(dataTable, element);
          const docLink = document.createElement('div');
          docLink.innerHTML = docLinkHtml;
          element.appendChild(docLink);
        }
      </script>
    </div>
  </div>
  
</div>
</div>
<div id="cell-11" class="cell" data-outputid="6f048f20-1d89-4ae6-ecf8-ccf5920d42f0" data-execution_count="7">
<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">dls <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> CollabDataLoaders.from_df(ratings_df, item_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;">"title"</span>, user_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;">"user"</span>, rating_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;">"rating"</span>)</span>
<span id="cb5-2">dls.show_batch()</span></code></pre></div>
<div class="cell-output cell-output-display">
<table class="dataframe caption-top table table-sm table-striped small" data-quarto-postprocess="true" data-border="1">
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th">user</th>
<th data-quarto-table-cell-role="th">title</th>
<th data-quarto-table-cell-role="th">rating</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td data-quarto-table-cell-role="th">0</td>
<td>647</td>
<td>Men in Black (1997)</td>
<td>2</td>
</tr>
<tr class="even">
<td data-quarto-table-cell-role="th">1</td>
<td>823</td>
<td>Twelve Monkeys (1995)</td>
<td>5</td>
</tr>
<tr class="odd">
<td data-quarto-table-cell-role="th">2</td>
<td>894</td>
<td>Twelve Monkeys (1995)</td>
<td>4</td>
</tr>
<tr class="even">
<td data-quarto-table-cell-role="th">3</td>
<td>278</td>
<td>In &amp; Out (1997)</td>
<td>2</td>
</tr>
<tr class="odd">
<td data-quarto-table-cell-role="th">4</td>
<td>234</td>
<td>Pinocchio (1940)</td>
<td>4</td>
</tr>
<tr class="even">
<td data-quarto-table-cell-role="th">5</td>
<td>823</td>
<td>Phenomenon (1996)</td>
<td>4</td>
</tr>
<tr class="odd">
<td data-quarto-table-cell-role="th">6</td>
<td>268</td>
<td>Nell (1994)</td>
<td>3</td>
</tr>
<tr class="even">
<td data-quarto-table-cell-role="th">7</td>
<td>293</td>
<td>Mrs. Doubtfire (1993)</td>
<td>3</td>
</tr>
<tr class="odd">
<td data-quarto-table-cell-role="th">8</td>
<td>699</td>
<td>Rock, The (1996)</td>
<td>4</td>
</tr>
<tr class="even">
<td data-quarto-table-cell-role="th">9</td>
<td>405</td>
<td>Best of the Best 3: No Turning Back (1995)</td>
<td>1</td>
</tr>
</tbody>
</table>
</div>
</div>
<p><strong>So how do we create these latent factors for our users and movies?</strong></p>
<p>“We can represent our movie and user latent factor tables as simple matrices” that we can index into. But as looking up in an index is not something our models know how to do, we need to use a special PyTorch layer that will do this for us (and more efficiently than using a one-hot-encoded, OHE, vector to do the same).</p>
<p>And that layer is called an <strong>embedding</strong>. It “indexes into a vector using an integer, but has its derivative calcuated in such a way that it is identical to what it would have been if it had done a matric multiplication with a one-hot-encoded vector.”</p>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>An embedding is the “thing that you multiply the one-hot-encoded matrix by (or, using the computational shortcut, inex into directly)”</p>
</div>
</div>
</section>
<section id="collaborative-filtering-from-scratch-dot-product" class="level2">
<h2 class="anchored" data-anchor-id="collaborative-filtering-from-scratch-dot-product">Collaborative Filtering: From Scratch (dot product)</h2>
<p>A <strong>dot product</strong> approach</p>
<div id="cell-14" class="cell" data-outputid="937db369-6bd7-4d0d-8627-db77619f72b9" data-execution_count="8">
<div class="sourceCode cell-code" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb6-1">n_users <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>(dls.classes[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"user"</span>])</span>
<span id="cb6-2">n_movies <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>(dls.classes[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"title"</span>])</span>
<span id="cb6-3">n_factors <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="cb6-4"></span>
<span id="cb6-5"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(n_users, n_movies, n_factors)</span></code></pre></div>
<div class="cell-output cell-output-stdout">
<pre><code>944 1665 5</code></pre>
</div>
</div>
<div id="cell-15" class="cell" data-execution_count="9">
<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"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> DotProduct(Module):</span>
<span id="cb8-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_users, n_movies, n_factors):</span>
<span id="cb8-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="cb8-4">      <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.users_emb <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> Embedding(n_users, n_factors)</span>
<span id="cb8-5">      <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.movies_emb <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> Embedding(n_movies, n_factors)</span>
<span id="cb8-6"></span>
<span id="cb8-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>, inp):</span>
<span id="cb8-8">    users <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>.users_emb(inp[:,<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>])</span>
<span id="cb8-9">    movies <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>.movies_emb(inp[:,<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>])</span>
<span id="cb8-10">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> (users <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> movies).<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>)</span></code></pre></div>
</div>
<div id="cell-16" class="cell" data-outputid="7653f554-3edc-484c-f06e-ed508e3c6506" data-execution_count="10">
<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">model <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> DotProduct(n_users<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>n_users, n_movies<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>n_movies, n_factors<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>n_factors)</span>
<span id="cb9-2">learn <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> Learner(dls, model, loss_func<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>MSELossFlat())</span>
<span id="cb9-3"></span>
<span id="cb9-4">learn.fit_one_cycle(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">5e-3</span>)</span></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-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-quarto-postprocess="true" 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">time</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>0</td>
<td>4.443892</td>
<td>3.739447</td>
<td>00:17</td>
</tr>
<tr class="even">
<td>1</td>
<td>1.088801</td>
<td>1.125219</td>
<td>00:12</td>
</tr>
<tr class="odd">
<td>2</td>
<td>0.960021</td>
<td>0.994215</td>
<td>00:09</td>
</tr>
<tr class="even">
<td>3</td>
<td>0.917181</td>
<td>0.959309</td>
<td>00:09</td>
</tr>
<tr class="odd">
<td>4</td>
<td>0.903602</td>
<td>0.957268</td>
<td>00:09</td>
</tr>
</tbody>
</table>
</div>
</div>
<section id="tip-1-constrain-your-range-of-predictions-using-sigmoid_range" class="level3">
<h3 class="anchored" data-anchor-id="tip-1-constrain-your-range-of-predictions-using-sigmoid_range">Tip 1: Constrain your range of predictions using <code>sigmoid_range</code></h3>
<p>“… to make this model a little bit better … force those predictions to be between 0 and 5. <strong>One thing we discovered empirically is that it’s better to have the range go a little bit over 5</strong>, so we use (0, 5.5)”</p>
<div id="cell-18" class="cell" data-execution_count="11">
<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"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> DotProduct(Module):</span>
<span id="cb10-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_users, n_movies, n_factors, y_range<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="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">5.5</span>)):</span>
<span id="cb10-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="cb10-4">      <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.users_emb <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> Embedding(n_users, n_factors)</span>
<span id="cb10-5">      <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.movies_emb <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> Embedding(n_movies, n_factors)</span>
<span id="cb10-6">      <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.y_range <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> y_range</span>
<span id="cb10-7"></span>
<span id="cb10-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>
<span id="cb10-9">    users <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>.users_emb(inp[:,<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>])</span>
<span id="cb10-10">    movies <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>.movies_emb(inp[:,<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>])</span>
<span id="cb10-11">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> sigmoid_range((users <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> movies).<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>), <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>.y_range)</span></code></pre></div>
</div>
<div id="cell-19" class="cell" data-outputid="ea8ca27d-545e-48bd-906c-a2cf3988f9dc" data-execution_count="12">
<div class="sourceCode cell-code" id="cb11" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb11-1">model <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> DotProduct(n_users<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>n_users, n_movies<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>n_movies, n_factors<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="cb11-2">learn <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> Learner(dls, model, loss_func<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>MSELossFlat())</span>
<span id="cb11-3"></span>
<span id="cb11-4">learn.fit_one_cycle(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">5e-3</span>)</span></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-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-quarto-postprocess="true" 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">time</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>0</td>
<td>1.012296</td>
<td>0.994128</td>
<td>00:09</td>
</tr>
<tr class="even">
<td>1</td>
<td>0.855805</td>
<td>0.903300</td>
<td>00:09</td>
</tr>
<tr class="odd">
<td>2</td>
<td>0.707656</td>
<td>0.875159</td>
<td>00:09</td>
</tr>
<tr class="even">
<td>3</td>
<td>0.482094</td>
<td>0.879115</td>
<td>00:09</td>
</tr>
<tr class="odd">
<td>4</td>
<td>0.369521</td>
<td>0.884585</td>
<td>00:09</td>
</tr>
</tbody>
</table>
</div>
</div>
</section>
<section id="tip-2-add-a-bias" class="level3">
<h3 class="anchored" data-anchor-id="tip-2-add-a-bias">Tip 2: Add a “bias”</h3>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>A <strong>bias</strong> allows your model to learn an overall representation of a thing, rather than just a bunch of characteristics.</p>
</div>
</div>
<p>“One obvious missing piece is that some users are just more positive or negative in their recommendations than others, and some movies are just plain better or worse than others. But in our dot product representation, we do not have any way to encode either of these things … **because at this point we have only weights; we don’t have biases”</p>
<div id="cell-21" class="cell" data-execution_count="13">
<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"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> DotProduct(Module):</span>
<span id="cb12-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_users, n_movies, n_factors, y_range<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="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">5.5</span>)):</span>
<span id="cb12-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="cb12-4">      <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.users_emb <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> Embedding(n_users, n_factors)</span>
<span id="cb12-5">      <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.users_bias <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> Embedding(n_users, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb12-6"></span>
<span id="cb12-7">      <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.movies_emb <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> Embedding(n_movies, n_factors)</span>
<span id="cb12-8">      <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.movies_bias <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> Embedding(n_movies, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb12-9"></span>
<span id="cb12-10">      <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.y_range <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> y_range</span>
<span id="cb12-11"></span>
<span id="cb12-12">  <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>
<span id="cb12-13">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># embeddings</span></span>
<span id="cb12-14">    users <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>.users_emb(inp[:,<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>])</span>
<span id="cb12-15">    movies <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>.movies_emb(inp[:,<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>])</span>
<span id="cb12-16"></span>
<span id="cb12-17">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># calc our dot product and add in biases </span></span>
<span id="cb12-18">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># (important to include "keepdim=True" =&gt; res.shape = (64,1), else will get rid of dims equal to 1 and you just get (64))</span></span>
<span id="cb12-19">    res <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (users <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> movies).<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="cb12-20">    res <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>.users_bias(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>.movies_bias(inp[:,<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>])</span>
<span id="cb12-21"></span>
<span id="cb12-22">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># return our target constrained prediction</span></span>
<span id="cb12-23">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> sigmoid_range(res, <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>.y_range)</span></code></pre></div>
</div>
<div id="cell-22" class="cell" data-outputid="15b23a24-1404-4788-c7a0-0488ec51fa9a" data-execution_count="14">
<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">model <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> DotProduct(n_users<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>n_users, n_movies<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>n_movies, n_factors<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="cb13-2">learn <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> Learner(dls, model, loss_func<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>MSELossFlat())</span>
<span id="cb13-3"></span>
<span id="cb13-4">learn.fit_one_cycle(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">5e-3</span>)</span></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-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-quarto-postprocess="true" 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">time</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>0</td>
<td>0.925160</td>
<td>0.938387</td>
<td>00:10</td>
</tr>
<tr class="even">
<td>1</td>
<td>0.807021</td>
<td>0.863466</td>
<td>00:11</td>
</tr>
<tr class="odd">
<td>2</td>
<td>0.607999</td>
<td>0.871146</td>
<td>00:10</td>
</tr>
<tr class="even">
<td>3</td>
<td>0.412089</td>
<td>0.897263</td>
<td>00:10</td>
</tr>
<tr class="odd">
<td>4</td>
<td>0.294376</td>
<td>0.905192</td>
<td>00:10</td>
</tr>
</tbody>
</table>
</div>
</div>
</section>
<section id="tip-3-add-weight-decay" class="level3">
<h3 class="anchored" data-anchor-id="tip-3-add-weight-decay">Tip 3: Add “weight decay”</h3>
<p>Adding in bias has made are model more complex and therefore more prone to overfitting (which seems to be happening here).</p>
<div class="callout callout-style-default 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">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p><strong>Overfitting</strong> is where your validation stops improving and actually starts to get worse.</p>
</div>
</div>
<p><strong>What do you do when your model overfits?</strong></p>
<p>We can solve this via data augmentation or by including one or more forms of <strong>regularization</strong> (e.g., a means to “encourage the weights to be as small as possible”.</p>
<p><strong>What is “weight decay” (aka “L2 regularization”)?</strong></p>
<p>“… consists of adding to your loss function the sum of all the weights squared.”</p>
<p><strong>Why do that?</strong></p>
<p>“Because when we compute the gradients, it will add a contribution to them that will encourage the weights to be as small as possible.”</p>
<p><strong>Why would this prevent overfitting?</strong></p>
<p>“The idea is that the larger the coefficients are, the sharper canyons we will have in the loss function…. <strong>Letting our model learn high parameters might cause it to fit all the data points in the training set with an overcomplex function that has very sharp changes, which will lead to overfitting</strong>.</p>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>“Limiting our weights from growing too much is going to hinder the training of the model <strong><em>but</em></strong> it will yield a state where it generalizes better”</p>
</div>
</div>
<p><strong>How do we add weight decay into are training?</strong></p>
<p>“… <code>wd</code> is a parameter that **controls that sum of squares we add to our loss” as such:</p>
<div id="cell-24" class="cell" data-outputid="f59928fa-8df1-4991-98ff-49a61e96a2db" data-execution_count="15">
<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">model <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> DotProduct(n_users<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>n_users, n_movies<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>n_movies, n_factors<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="cb14-2">learn <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> Learner(dls, model, loss_func<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>MSELossFlat())</span>
<span id="cb14-3"></span>
<span id="cb14-4">learn.fit_one_cycle(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">5e-3</span>, wd<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.1</span>)</span></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-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-quarto-postprocess="true" 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">time</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>0</td>
<td>0.934345</td>
<td>0.946092</td>
<td>00:10</td>
</tr>
<tr class="even">
<td>1</td>
<td>0.862484</td>
<td>0.866700</td>
<td>00:10</td>
</tr>
<tr class="odd">
<td>2</td>
<td>0.715633</td>
<td>0.829172</td>
<td>00:10</td>
</tr>
<tr class="even">
<td>3</td>
<td>0.597503</td>
<td>0.817248</td>
<td>00:10</td>
</tr>
<tr class="odd">
<td>4</td>
<td>0.473108</td>
<td>0.817725</td>
<td>00:10</td>
</tr>
</tbody>
</table>
</div>
</div>
</section>
<section id="creating-our-own-embedding-module" class="level3">
<h3 class="anchored" data-anchor-id="creating-our-own-embedding-module">Creating our own Embedding Module</h3>
<p>pp.265-267 show how to write your own <code>nn.Module</code> that does what <code>Embedding</code> does. Here are some of the important bits to pay attention too …</p>
<p>“… optimizers require that they can get all the parameters of a module from the module’s <code>parameters</code> method, so make sure to tell <code>nn.Module</code> that you want to treat a tensor as a parameters using the <code>nn.Parameter</code> class like so:</p>
<div class="sourceCode" id="cb15" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb15-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> T(Module):</span>
<span id="cb15-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>):</span>
<span id="cb15-3">    <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.a <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> nn.Parameter(torch.ones(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>))</span></code></pre></div>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>“All PyTorch modules use <code>nn.Parameter</code> for any trainable parameters.</p>
</div>
</div>
<div class="sourceCode" id="cb16" 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;">class</span> T(Module):</span>
<span id="cb16-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>):</span>
<span id="cb16-3">    <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.a <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> nn.Liner(<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;">3</span>, bias<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="cb16-4"></span>
<span id="cb16-5">t <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> T()</span>
<span id="cb16-6">t.parameters()   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#=&gt; will show all the weights of your nn.Linear</span></span>
<span id="cb16-7"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">type</span>(t.a.weight) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#=&gt; torch.nn.parameter.Parameter</span></span></code></pre></div>
<p>Now, given a method like this …</p>
<div class="sourceCode" id="cb17" 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> create_params(size):</span>
<span id="cb17-2">  <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> nn.Parameter(torch.zeros(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>size).normal_(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.01</span>))</span></code></pre></div>
<p>… we can create randomly initialized parameters, included parameters for our latent factors and biases like this:</p>
<div class="sourceCode" id="cb18" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb18-1"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.users_emb <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> create_params([n_users, n_factors])</span>
<span id="cb18-2"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.users_bias <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> create_params([n_users])</span></code></pre></div>
</section>
</section>
<section id="interpreting-embeddings-and-biases" class="level2">
<h2 class="anchored" data-anchor-id="interpreting-embeddings-and-biases">Interpreting Embeddings and Biases</h2>
<div class="callout callout-style-default 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">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>“… interesting to see what parameters it has discovered … easiest to interpret are the biases”</p>
</div>
</div>
<div id="cell-27" class="cell" data-outputid="53fd4723-3c65-497c-8695-d3b6d93bdf33" data-execution_count="16">
<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">movie_bias <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> learn.model.movies_bias.weight.squeeze() <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># =&gt; squeeze will get rid of all the single dimensions</span></span>
<span id="cb19-2">idxs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> movie_bias.argsort()[:<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>]                       <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># =&gt; "argsort()" returns the indices sorted by value</span></span>
<span id="cb19-3">[dls.classes[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"title"</span>][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> idxs]               <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># =&gt; look up the movie title in dls.classes</span></span></code></pre></div>
<div class="cell-output cell-output-display" data-execution_count="16">
<pre><code>['Children of the Corn: The Gathering (1996)',
 'Big Bully (1996)',
 'Showgirls (1995)',
 'Lawnmower Man 2: Beyond Cyberspace (1996)',
 'Free Willy 3: The Rescue (1997)']</code></pre>
</div>
</div>
<p>“Think about what this means …. It tells us not just whether a movie is of a kind that people tend not to enjoy watching, but that people tend to not like watching it even if it is of a kind that they would otherwise enjoy!”</p>
<p>To get the movies by highest bias:</p>
<div id="cell-29" class="cell" data-outputid="fbc198bd-cbd6-4835-a631-386661c1c2bb" data-execution_count="17">
<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">idxs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> movie_bias.argsort(descending<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="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>]</span>
<span id="cb21-2">[dls.classes[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"title"</span>][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> idxs]</span></code></pre></div>
<div class="cell-output cell-output-display" data-execution_count="17">
<pre><code>['Titanic (1997)',
 "Schindler's List (1993)",
 'As Good As It Gets (1997)',
 'L.A. Confidential (1997)',
 'Shawshank Redemption, The (1994)']</code></pre>
</div>
</div>
<div class="callout callout-style-default 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">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>To visualize embeddings with many factors, you “can pull out the most important underlying directions” using a dimensionality reduction model like <strong>principal components analysis</strong> (PCA).</p>
</div>
</div>
<p>See p.268 and these three StatQuest videos for more on how PCA works (btw, StatQuest is one of my top data science references so consider subscribing to his channel). <a href="https://www.youtube.com/watch?v=HMOI_lkzW08&amp;t=13s">Video 1</a>, <a href="https://www.youtube.com/watch?v=FgakZw6K1QQ">Video 2</a>, and <a href="https://www.youtube.com/watch?v=oRvgq966yZg">Video 3</a></p>
</section>
<section id="collaborative-filtering-using-fastai.collab" class="level2">
<h2 class="anchored" data-anchor-id="collaborative-filtering-using-fastai.collab">Collaborative Filtering: Using <code>fastai.collab</code></h2>
<div id="cell-32" class="cell" data-outputid="ad3802a4-1ebd-4e6f-e782-fc03371cf3dd" data-execution_count="18">
<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">learn <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> collab_learner(dls, n_factors<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>, y_range<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="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">5.5</span>))</span>
<span id="cb23-2">learn.fit_one_cycle(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">5e-3</span>, wd<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.1</span>)</span></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-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-quarto-postprocess="true" 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">time</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>0</td>
<td>0.950606</td>
<td>0.930099</td>
<td>00:10</td>
</tr>
<tr class="even">
<td>1</td>
<td>0.834664</td>
<td>0.870282</td>
<td>00:10</td>
</tr>
<tr class="odd">
<td>2</td>
<td>0.723968</td>
<td>0.833274</td>
<td>00:10</td>
</tr>
<tr class="even">
<td>3</td>
<td>0.573679</td>
<td>0.819824</td>
<td>00:10</td>
</tr>
<tr class="odd">
<td>4</td>
<td>0.489258</td>
<td>0.820394</td>
<td>00:10</td>
</tr>
</tbody>
</table>
</div>
</div>
<div id="cell-33" class="cell" data-outputid="a1f0b69e-a702-4a17-845b-ce8c42511ccc" data-execution_count="19">
<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">learn.model</span></code></pre></div>
<div class="cell-output cell-output-display" data-execution_count="19">
<pre><code>EmbeddingDotBias(
  (u_weight): Embedding(944, 50)
  (i_weight): Embedding(1665, 50)
  (u_bias): Embedding(944, 1)
  (i_bias): Embedding(1665, 1)
)</code></pre>
</div>
</div>
<div id="cell-34" class="cell" data-outputid="3dbd8c91-358a-4016-a869-9eda35a10e3a" data-execution_count="20">
<div class="sourceCode cell-code" id="cb26" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb26-1">movie_bias <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> learn.model.i_bias.weight.squeeze() </span>
<span id="cb26-2">idxs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> movie_bias.argsort()[:<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>]                   </span>
<span id="cb26-3">[dls.classes[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"title"</span>][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> idxs]              </span></code></pre></div>
<div class="cell-output cell-output-display" data-execution_count="20">
<pre><code>['Children of the Corn: The Gathering (1996)',
 'Showgirls (1995)',
 'Barb Wire (1996)',
 'Island of Dr. Moreau, The (1996)',
 'Cable Guy, The (1996)']</code></pre>
</div>
</div>
</section>
<section id="embedding-distance" class="level2">
<h2 class="anchored" data-anchor-id="embedding-distance">Embedding Distance</h2>
<p>“Another thing we can do with these learned embeddings is to look at distance.”</p>
<p><strong>Why do this?</strong></p>
<p>“If there were two movies that were nearly identical, their embedding vectors would also have to be nearly identical …. There is a more general idea here: movie similairty can be defined by the similarity of users who like those movies. And that directly means that the distance between two movies’ embedding vectors can define that similarity”</p>
<div id="cell-36" class="cell" data-outputid="2661298b-57cc-4196-94ba-037115d57a3a" data-execution_count="21">
<div class="sourceCode cell-code" id="cb28" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb28-1">movie_factors <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> learn.model.i_weight.weight</span>
<span id="cb28-2">idx <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> dls.classes[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"title"</span>].o2i[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Silence of the Lambs, The (1991)"</span>]</span>
<span id="cb28-3">dists <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> nn.CosineSimilarity(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>)(movie_factors, movie_factors[idx][<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>])</span>
<span id="cb28-4">targ_idx <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> dists.argsort(descending<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="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]</span>
<span id="cb28-5">dls.classes[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"title"</span>][targ_idx]</span></code></pre></div>
<div class="cell-output cell-output-display" data-execution_count="21">
<pre><code>'Dial M for Murder (1954)'</code></pre>
</div>
</div>
</section>
<section id="bootstrapping" class="level2">
<h2 class="anchored" data-anchor-id="bootstrapping">Bootstrapping</h2>
<p>The <strong>bootstrapping problem</strong> asks how we can make recommendations when we have a new user for which no data exists or a new product/movie for which no reviews have been made?</p>
<p>The recommended approach “is to <strong>use a tabular model based on user metadata to construct your initial embedding vector.</strong> When a new user signs up, think about what questions you could ask to help you understand their tastes. Then you can create a model in which <strong>the dependent variable is a user’s embedding vector</strong>, and <strong>the independent variables are the results of the questions that you ask them, along with their signup metadata</strong>.”</p>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>Be aware of the “problem of <strong>representation bias</strong>” (e.g., where a few very active users end up skewing the results).</p>
</div>
</div>
<p>See p.271 for more information on how collaborative models may contribute to positive feedback loops and how humans can mitigate by being part of the process.</p>
</section>
<section id="collaborative-filtering-from-scratch-nn" class="level2">
<h2 class="anchored" data-anchor-id="collaborative-filtering-from-scratch-nn">Collaborative Filtering: From Scratch (NN)</h2>
<p>A <strong>neural network</strong> approach requires we “take the results of the embedding lookup and concatenate those activations together. This gives us a matrix we can then pass through linear layers and nonlinearities…”</p>
<div class="callout callout-style-default 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">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>Because “we’ll be concatenating the embedding matrices, rather than taking their dot product, <strong>the two embedding matrices can have different sizes (different numbers of latent factors)</strong>”</p>
</div>
</div>
<p><strong>How do we determine the number of latent factors a “thing” should have?</strong></p>
<p>Use <code>get_emb_sz</code> to return “the recommended sizes for embedding matrices for your data, **based on a heuristic that fast.ai has found tends to work well in practice”</p>
<div id="cell-39" class="cell" data-outputid="91767a50-ee06-401a-f137-59511a3f9aaf" data-execution_count="22">
<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">embs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> get_emb_sz(dls)</span>
<span id="cb30-2">embs</span></code></pre></div>
<div class="cell-output cell-output-display" data-execution_count="22">
<pre><code>[(944, 74), (1665, 102)]</code></pre>
</div>
</div>
<div id="cell-40" class="cell" data-execution_count="23">
<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"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> CollabNN(Module):</span>
<span id="cb32-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>, user_sz, item_sz, y_range<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="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>), n_act<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;">100</span>):</span>
<span id="cb32-3">    <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.user_factors <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> Embedding(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>user_sz)</span>
<span id="cb32-4">    <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.item_factors <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> Embedding(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>item_sz)</span>
<span id="cb32-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> nn.Sequential(</span>
<span id="cb32-6">      nn.Linear(user_sz[<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> item_sz[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>], n_act),</span>
<span id="cb32-7">      nn.ReLU(),</span>
<span id="cb32-8">      nn.Linear(n_act, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb32-9">    )</span>
<span id="cb32-10">    <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.y_range <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> y_range</span>
<span id="cb32-11"></span>
<span id="cb32-12">  <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>
<span id="cb32-13">    embs <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>.user_factors(x[:,<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>]), <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.item_factors(x[:,<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>])</span>
<span id="cb32-14">    x <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>.layers(torch.cat(embs, 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>
<span id="cb32-15">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> sigmoid_range(x, <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>.y_range)</span></code></pre></div>
</div>
<div id="cell-41" class="cell" data-outputid="21ff26d5-8b5a-4c64-fb8f-b34ed6e0c8d9" data-execution_count="24">
<div class="sourceCode cell-code" id="cb33" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb33-1">model <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> CollabNN(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>embs)</span>
<span id="cb33-2">learn <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> Learner(dls, model, loss_func<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>MSELossFlat())</span>
<span id="cb33-3">learn.fit_one_cycle(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">5e-3</span>, wd<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.1</span>)</span></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-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-quarto-postprocess="true" 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">time</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>0</td>
<td>10.594646</td>
<td>10.379806</td>
<td>00:11</td>
</tr>
<tr class="even">
<td>1</td>
<td>10.368298</td>
<td>10.379800</td>
<td>00:10</td>
</tr>
<tr class="odd">
<td>2</td>
<td>10.565783</td>
<td>10.379800</td>
<td>00:10</td>
</tr>
<tr class="even">
<td>3</td>
<td>10.439667</td>
<td>10.379800</td>
<td>00:10</td>
</tr>
<tr class="odd">
<td>4</td>
<td>10.356900</td>
<td>10.379800</td>
<td>00:10</td>
</tr>
</tbody>
</table>
</div>
</div>
<p>If we use the <code>collab_learner</code>, will will calculate our embedding sizes for us and also give us the option of defining how many more layers we want to tack on via the <code>layers</code> parameter. All we have to do is tell it to <code>use_nn=True</code> to use a NN rather than the default dot-product model.</p>
<div id="cell-43" class="cell" data-execution_count="25">
<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">learn <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> collab_learner(dls, use_nn<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>, y_range<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="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</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;">100</span>,<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">50</span>])</span></code></pre></div>
</div>
<div id="cell-44" class="cell" data-outputid="ec5fa2fe-bb33-486d-a81c-ca1920f034db" data-execution_count="26">
<div class="sourceCode cell-code" id="cb35" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb35-1">learn.model</span></code></pre></div>
<div class="cell-output cell-output-display" data-execution_count="26">
<pre><code>EmbeddingNN(
  (embeds): ModuleList(
    (0): Embedding(944, 74)
    (1): Embedding(1665, 102)
  )
  (emb_drop): Dropout(p=0.0, inplace=False)
  (bn_cont): BatchNorm1d(0, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (layers): Sequential(
    (0): LinBnDrop(
      (0): Linear(in_features=176, out_features=100, bias=False)
      (1): ReLU(inplace=True)
      (2): BatchNorm1d(100, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    )
    (1): LinBnDrop(
      (0): Linear(in_features=100, out_features=50, bias=False)
      (1): ReLU(inplace=True)
      (2): BatchNorm1d(50, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    )
    (2): LinBnDrop(
      (0): Linear(in_features=50, out_features=1, bias=True)
    )
    (3): SigmoidRange(low=0, high=0.5)
  )
)</code></pre>
</div>
</div>
<div id="cell-45" class="cell" data-outputid="b03e1805-c8b7-4080-ae11-edce84b9d874" data-execution_count="27">
<div class="sourceCode cell-code" id="cb37" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb37-1">learn.fit_one_cycle(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">5e-3</span>, wd<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.1</span>)</span></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-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-quarto-postprocess="true" 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">time</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>0</td>
<td>10.274985</td>
<td>10.379872</td>
<td>00:12</td>
</tr>
<tr class="even">
<td>1</td>
<td>10.555515</td>
<td>10.379800</td>
<td>00:12</td>
</tr>
<tr class="odd">
<td>2</td>
<td>10.436097</td>
<td>10.379800</td>
<td>00:12</td>
</tr>
<tr class="even">
<td>3</td>
<td>10.481320</td>
<td>10.379800</td>
<td>00:12</td>
</tr>
<tr class="odd">
<td>4</td>
<td>10.400410</td>
<td>10.379800</td>
<td>00:12</td>
</tr>
</tbody>
</table>
</div>
</div>
<p><strong>Why use a neural network (NN)?</strong></p>
<p>Because “we can now directly incorporate other user and movie information, date and time information, or any other information that may be relevant to the recommendation.”</p>
<p>We’ll see this when we look at <code>TabularModel</code> (of which <code>EmbeddingNN</code> is a subclass with no continuous data [<code>n_cont=0</code>] and an <code>out_sz=1</code>.</p>
</section>
<section id="kwargs-and-delegates" class="level2">
<h2 class="anchored" data-anchor-id="kwargs-and-delegates"><code>kwargs</code> and <code>@delegates</code></h2>
<p>Some helpful notes for both are included on pp.273-274. In short …</p>
<p><code>**kwargs</code>:</p>
<ol type="1">
<li><code>**kwargs</code> as a <strong>parameter</strong> = “put any additional keyword arguments into a dict called <code>kwargs</code>”</li>
<li><code>**kwargs</code> passed as an <strong>argument</strong> = “insert all key/value pairs in the <code>kwargs</code> dict as named arguments here.”</li>
</ol>
<p><code>@delegates</code>:</p>
<p>“… fastai resolves [the issue of using <code>**kwargs</code> to avoid having to write out all the arguments of the base class] by providing a special <code>@delegates</code> decorator, which automatically <strong>changes the signature of the class or function</strong> … to insert all of its keyword arguments into the signature.”</p>
</section>
<section id="resources" class="level2">
<h2 class="anchored" data-anchor-id="resources">Resources</h2>
<ol type="1">
<li>https://book.fast.ai - The book’s website; it’s updated regularly with new content and recommendations from everything to GPUs to use, how to run things locally and on the cloud, etc…</li>
</ol>


</section>

 ]]></description>
  <category>fastai</category>
  <category>fastbook</category>
  <category>collaborative filtering</category>
  <category>latent factors</category>
  <category>embeddings</category>
  <category>recommender systems</category>
  <category>recsys</category>
  <guid>https://ohmeow.com/posts/2022-03-31-ajtfb-chapter-8.html</guid>
  <pubDate>Thu, 31 Mar 2022 07:00:00 GMT</pubDate>
  <media:content url="https://ohmeow.com/posts/images/fastbook.jpg" medium="image" type="image/jpeg"/>
</item>
<item>
  <title>A Journey Through Fastbook (AJTFB) - Chapter 7: Advanced techniques for training image classification models</title>
  <dc:creator>Wayde Gilliam</dc:creator>
  <link>https://ohmeow.com/posts/2022-03-28-ajtfb-chapter-7.html</link>
  <description><![CDATA[ 




<p>Other posts in this series:</p>
<p><a href="../posts/2020-11-06-ajtfb-chapter-1.html">A Journey Through Fastbook (AJTFB) - Chapter 1</a><br>
<a href="../posts/2020-11-16-ajtfb-chapter-2.html">A Journey Through Fastbook (AJTFB) - Chapter 2</a><br>
<a href="../posts/2020-11-22-ajtfb-chapter-3.html">A Journey Through Fastbook (AJTFB) - Chapter 3</a><br>
<a href="../posts/2021-05-23-ajtfb-chapter-4.html">A Journey Through Fastbook (AJTFB) - Chapter 4</a><br>
<a href="../posts/2021-06-03-ajtfb-chapter-5.html">A Journey Through Fastbook (AJTFB) - Chapter 5</a><br>
<a href="../posts/2021-06-10-ajtfb-chapter-6-multilabel.html">A Journey Through Fastbook (AJTFB) - Chapter 6a</a><br>
<a href="../posts/2022-02-09-ajtfb-chapter-6-regression.html">A Journey Through Fastbook (AJTFB) - Chapter 6b</a><br>
<a href="../posts/2022-03-31-ajtfb-chapter-8.html">A Journey Through Fastbook (AJTFB) - Chapter 8</a><br>
<a href="../posts/2022-04-25-ajtfb-chapter-9.html">A Journey Through Fastbook (AJTFB) - Chapter 9</a></p>
<section id="imagenette" class="level2">
<h2 class="anchored" data-anchor-id="imagenette">Imagenette</h2>
<p>The <strong>Imagenette</strong> is a subset of the <strong>ImageNet</strong> dataset that “contains a subset of 10 very different categories from the orginal ImageNet dataset, making for quicker training when we want to experiment”</p>
<div class="callout callout-style-default callout-tip 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">
Tip
</div>
</div>
<div class="callout-body-container callout-body">
<p>Start with small datasets and models for initial experimentation and prototyping. Both will allow you to iterate over your experiments more quickly and verify your code works from beginning to end without having to wait hours for your training/validation loops to finish. “You should aim to have an iteration speed of no more than a couple of minutes …. <em>If it’s taking longer to do an experiment, think about how you could cut down your dataset, or simply your model, to improve your experimentation speed.</em>”</p>
</div>
</div>
<div id="cell-5" class="cell">
<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="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="cb1-2">path <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> untar_data(URLs.IMAGENETTE)</span></code></pre></div>
</div>
</section>
<section id="tip-1-use-the-presizing-trick" class="level2">
<h2 class="anchored" data-anchor-id="tip-1-use-the-presizing-trick">Tip 1: Use the “presizing trick”</h2>
<p>See chapter 5, pp.189-191. The idea here is to first crop the image <strong>so that further augmentations can be applied without creating empty space</strong> (via <code>item_tfms</code>), with further augmentations being applied on the GPU on batches of images for speed (via <code>batch_tfms</code>).</p>
<p>On the training set, the initial crop area is chosen randomly with the size set to cover the entire width/height of the image with random crop and other augmentations done on the GPU.</p>
<p>On the validation set, a center square is always used in the first step and only a resize is applied on the GPU to get the image width/height equal to the final size needed.</p>
<div id="cell-7" class="cell">
<div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb2-1">dblock <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> DataBlock(</span>
<span id="cb2-2">    blocks<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>(ImageBlock(), CategoryBlock()),</span>
<span id="cb2-3">    get_items <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> get_image_files,</span>
<span id="cb2-4">    get_y <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> parent_label,</span>
<span id="cb2-5">    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;">460</span>),</span>
<span id="cb2-6">    batch_tfms <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> aug_transforms(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;">224</span>, min_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.75</span>)</span>
<span id="cb2-7">)</span>
<span id="cb2-8"></span>
<span id="cb2-9">dls <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> dblock.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;">64</span>)</span></code></pre></div>
</div>
</section>
<section id="tip-2-create-a-baseline" class="level2">
<h2 class="anchored" data-anchor-id="tip-2-create-a-baseline">Tip 2: Create a “baseline”</h2>
<div class="callout callout-style-default 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">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>we are <strong><em>not</em></strong> using a pretrained model here, we are training one from scratch.</p>
</div>
</div>
<div id="cell-9" class="cell" data-outputid="21e8d6b8-156d-41b6-81bf-da6be73f8166">
<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">model <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> xresnet50()</span>
<span id="cb3-2">learn <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> Learner(dls, model, loss_func<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>CrossEntropyLossFlat(), metrics<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>accuracy)</span>
<span id="cb3-3">learn.fit_one_cycle(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">3e-3</span>)</span></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-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-quarto-postprocess="true" 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">accuracy</th>
<th data-quarto-table-cell-role="th">time</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>0</td>
<td>1.654316</td>
<td>4.794844</td>
<td>0.320015</td>
<td>05:21</td>
</tr>
<tr class="even">
<td>1</td>
<td>1.217274</td>
<td>1.211676</td>
<td>0.612024</td>
<td>05:19</td>
</tr>
<tr class="odd">
<td>2</td>
<td>0.964628</td>
<td>1.417025</td>
<td>0.617252</td>
<td>05:06</td>
</tr>
<tr class="even">
<td>3</td>
<td>0.736836</td>
<td>0.677910</td>
<td>0.787155</td>
<td>05:12</td>
</tr>
<tr class="odd">
<td>4</td>
<td>0.596578</td>
<td>0.539180</td>
<td>0.833831</td>
<td>05:05</td>
</tr>
</tbody>
</table>
</div>
</div>
</section>
<section id="tip-3-normalize-your-data" class="level2">
<h2 class="anchored" data-anchor-id="tip-3-normalize-your-data">Tip 3: Normalize your data</h2>
<div class="callout callout-style-default callout-tip 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">
Tip
</div>
</div>
<div class="callout-body-container callout-body">
<p>“When training a model, it helps if your input data is <em>normalized</em> - this is, <strong>has a mean of 0 and a standard deviation of 1</strong>.””</p>
</div>
</div>
<p>For images we do this over each channel (the 1 dimension) but averaging over all axes with the exception of the channel axis. In fastai, we can utilize the <strong><code>Normalize</code></strong> transform to apply this a batch at a time.</p>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>If we don’t tell this transform what mean/std to use, “fastai will automatically calculate them from a single batch of your data”</p>
</div>
</div>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>If we are using ImageNet images, we can use <code>imagenet_stats</code> instead of calculating the mean/std ourselves).</p>
</div>
</div>
<div id="cell-11" class="cell" data-outputid="630e0453-3ac1-476f-dfa1-e6ce0c0759c3">
<div class="sourceCode cell-code" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb4-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># an example of normalization calculated on a batch of images</span></span>
<span id="cb4-2"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># (because we aren't using normalization yet, you'll see the mean and standard deviation are not very close to</span></span>
<span id="cb4-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># 0 and 1 respectively)</span></span>
<span id="cb4-4">x, y <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> dls.one_batch()</span>
<span id="cb4-5"></span>
<span id="cb4-6">x.mean(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="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>]), x.std(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="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 class="cell-output cell-output-display" data-execution_count="7">
<pre><code>(TensorImage([0.4518, 0.4554, 0.4344], device='cuda:0'),
 TensorImage([0.2868, 0.2783, 0.2998], device='cuda:0'))</code></pre>
</div>
</div>
<div id="cell-12" class="cell">
<div class="sourceCode cell-code" id="cb6" 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_dls(batch_size, image_size):</span>
<span id="cb6-2">  dblock <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> DataBlock(</span>
<span id="cb6-3">      blocks<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>(ImageBlock(), CategoryBlock()),</span>
<span id="cb6-4">      get_items <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> get_image_files,</span>
<span id="cb6-5">      get_y <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> parent_label,</span>
<span id="cb6-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;">460</span>),</span>
<span id="cb6-7">      batch_tfms <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>aug_transforms(size<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>image_size, min_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.75</span>), Normalize.from_stats(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>imagenet_stats)]</span>
<span id="cb6-8">  )</span>
<span id="cb6-9"></span>
<span id="cb6-10">  dls <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> dblock.dataloaders(path, bs<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>batch_size)</span>
<span id="cb6-11">  <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> dls</span></code></pre></div>
</div>
<div id="cell-13" class="cell" data-outputid="a5ef96de-aff0-47d5-9412-8bb2088ef77a">
<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">dls <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> get_dls(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">64</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">224</span>)</span>
<span id="cb7-2"></span>
<span id="cb7-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># an example of normalization calculated on a batch of images</span></span>
<span id="cb7-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># (because we are using normalization now, the mean and standard deviation are very close to 0 and 1 respectively)</span></span>
<span id="cb7-5">x, y <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> dls.one_batch()</span>
<span id="cb7-6"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(x.mean(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="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>]), x.std(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="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>
<span id="cb7-7"></span>
<span id="cb7-8"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># does this normalization improve our model? Let's see ...</span></span>
<span id="cb7-9">model <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> xresnet50()</span>
<span id="cb7-10">learn <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> Learner(dls, model, loss_func<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>CrossEntropyLossFlat(), metrics<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>accuracy)</span>
<span id="cb7-11">learn.fit_one_cycle(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">3e-3</span>)</span></code></pre></div>
<div class="cell-output cell-output-stdout">
<pre><code>TensorImage([-0.0816, -0.0114,  0.0695], device='cuda:0') TensorImage([1.1806, 1.1762, 1.2825], device='cuda:0')</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-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-quarto-postprocess="true" 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">accuracy</th>
<th data-quarto-table-cell-role="th">time</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>0</td>
<td>1.701530</td>
<td>1.856552</td>
<td>0.468633</td>
<td>05:07</td>
</tr>
<tr class="even">
<td>1</td>
<td>1.280709</td>
<td>1.384676</td>
<td>0.573562</td>
<td>05:05</td>
</tr>
<tr class="odd">
<td>2</td>
<td>1.007325</td>
<td>1.073023</td>
<td>0.656460</td>
<td>05:06</td>
</tr>
<tr class="even">
<td>3</td>
<td>0.762624</td>
<td>0.666320</td>
<td>0.784541</td>
<td>05:06</td>
</tr>
<tr class="odd">
<td>4</td>
<td>0.606407</td>
<td>0.573812</td>
<td>0.823376</td>
<td>05:02</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>“… when you distribute a model, you need to also distribute the statistics used for normalization, since anyone using it for inference or transfer learning will need to use the same statistics …. <strong>If you’re using a model that someone else has trained, make sure you find out what normalization statistics they used and match them.</strong>”</p>
</div>
</div>
</section>
<section id="tip-4-use-progressive-resizing" class="level2">
<h2 class="anchored" data-anchor-id="tip-4-use-progressive-resizing">Tip 4: Use “progressive resizing”</h2>
<p>“… start training using small images, and end training using large images. <strong>Spending most of the epochs training with small images helps training complete faster</strong>.”</p>
<div class="callout callout-style-default 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">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>Think of this as a form of <strong><em>transfer learning</em></strong></p>
</div>
</div>
<p>“… <strong>the kinds of features that are learned by convolutional neural networks are not in any way specific to the size of the image</strong> …. So, when we change the image size in the middle of training, it doesn’t mean that we have to find totally different parameters for our model.”</p>
<div class="callout callout-style-default 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">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>“Progressive resizing has an additional benefit: it is another form of data augmentation. Therefore, you should expect to see better generalization”</p>
</div>
</div>
<div id="cell-16" class="cell" data-outputid="06f07856-897c-41b1-9ac1-c0579d7457c2">
<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">dls <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> get_dls(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">128</span>,<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">128</span>)</span>
<span id="cb9-2">learn <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> Learner(dls, xresnet50(), loss_func<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>CrossEntropyLossFlat(), metrics<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>accuracy)</span>
<span id="cb9-3">learn.fit_one_cycle(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">3e-3</span>)</span>
<span id="cb9-4"></span>
<span id="cb9-5"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># simply replace the `Learner.dls` with new `DataLoaders` and continue traning.</span></span>
<span id="cb9-6">learn.dls <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> get_dls(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">64</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">224</span>)</span>
<span id="cb9-7">learn.fine_tune(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1e-3</span>)</span></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-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-quarto-postprocess="true" 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">accuracy</th>
<th data-quarto-table-cell-role="th">time</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>0</td>
<td>1.848093</td>
<td>1.582196</td>
<td>0.526512</td>
<td>03:02</td>
</tr>
<tr class="even">
<td>1</td>
<td>1.297791</td>
<td>1.205059</td>
<td>0.616878</td>
<td>03:01</td>
</tr>
<tr class="odd">
<td>2</td>
<td>0.985249</td>
<td>1.022758</td>
<td>0.690067</td>
<td>02:55</td>
</tr>
<tr class="even">
<td>3</td>
<td>0.762485</td>
<td>0.688779</td>
<td>0.787155</td>
<td>02:53</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-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-quarto-postprocess="true" 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">accuracy</th>
<th data-quarto-table-cell-role="th">time</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>0</td>
<td>0.845315</td>
<td>1.171858</td>
<td>0.650112</td>
<td>05:08</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-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-quarto-postprocess="true" 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">accuracy</th>
<th data-quarto-table-cell-role="th">time</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>0</td>
<td>0.635858</td>
<td>0.834369</td>
<td>0.751307</td>
<td>05:06</td>
</tr>
<tr class="even">
<td>1</td>
<td>0.664283</td>
<td>0.665261</td>
<td>0.796117</td>
<td>05:10</td>
</tr>
<tr class="odd">
<td>2</td>
<td>0.585543</td>
<td>0.634785</td>
<td>0.796490</td>
<td>05:11</td>
</tr>
<tr class="even">
<td>3</td>
<td>0.478250</td>
<td>0.495538</td>
<td>0.840926</td>
<td>05:02</td>
</tr>
<tr class="odd">
<td>4</td>
<td>0.429075</td>
<td>0.448893</td>
<td>0.855489</td>
<td>05:08</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="callout callout-style-default 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">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>To use the <code>DataLoaders</code> with bigger images, we simply assign it to <code>Learner.dls</code>.</p>
</div>
</div>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>Bigger images will require smaller batch sizes. Also, you will not get a benefit of using images sized larger than the size of your images on disk!</p>
</div>
</div>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>“… for transfer learning, progressive resizing <em>may</em> acutally hurt performance …. This is most likely to happen <strong>if your pretrained model was quite similar to your transfer learning task and the dataset and was trained on similar-sized images</strong>, so the weights don’t need to be changed much. In that case, <strong>training on smaller images may damage the pretrained weights.</strong></p>
</div>
</div>
<p>“On the other hand, if the transfer learning task is going to use <strong>images that are of different sizes, shapes, or styles than those used in the pretraining task</strong>, progressive resizing will probably help”</p>
<div class="callout callout-style-default callout-tip 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">
Tip
</div>
</div>
<div class="callout-body-container callout-body">
<p>If you are unsure, try it!</p>
</div>
</div>
</section>
<section id="tip-5-use-test-time-augmentation-tta" class="level2">
<h2 class="anchored" data-anchor-id="tip-5-use-test-time-augmentation-tta">Tip 5: Use Test Time Augmentation (TTA)</h2>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>TTA is a form of data augmentation applied to the validation set that adds augmented versions of the images. “<strong>During inference or validation</strong>, creating multiple versions of each image using data augmentation, and then taking the average or maximum of the predictions for each augmented version of the image.”</p>
</div>
</div>
<p>“… select a number of areas to crop from the original rectangular image, pass each of them through our model, and take the maximum or average of the predictions. In fact, we can do this not just for different crops, but for different values across all of our test time augmentation parameters”</p>
<p><strong>What is the problem TTA addresses and why use it?</strong></p>
<p>“When we use random cropping, fastai will automatically <strong>use center-cropping for the validation set</strong>” which can be probelmatic, for example, in multi-label tasks where “sometimes there are small objects toward the edges of an image” that might be cropped out entirely or perhaps features on the fringe that are required for any classification task.</p>
<div id="cell-19" class="cell" data-outputid="421d320f-26ce-497b-dd77-2fbecbb3eb27">
<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"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># you can pass any `DataLoaders` to `tta()` (by default it uses your validation `DataLoader`)</span></span>
<span id="cb10-2">preds, targs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> learn.tta()</span>
<span id="cb10-3">accuracy(preds, targs).item()</span></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-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {
        background: #F44336;
    }
</style>
</div>
<div class="cell-output cell-output-display">

    <div>
      <progress value="0" class="" max="5" style="width:300px; height:20px; vertical-align: middle;"></progress>
      
    </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-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-display" data-execution_count="11">
<pre><code>0.861090362071991</code></pre>
</div>
</div>
<p>“TTA gives us a good boost in performance, <strong>with no additional training required.</strong></p>
</section>
<section id="tip-6-use-mixup" class="level2">
<h2 class="anchored" data-anchor-id="tip-6-use-mixup">Tip 6: Use <code>MixUp</code></h2>
<p>“<strong>Mixup</strong> … is a powerful data augmentation technique that can provide dramatically higher accuracy, <strong>especially when you don’t have much data and don’t have a pretrained model that was trained on data similar to your dataset</strong>”</p>
<p>It is a dataset-independent form of data augmentation = can be applied without domain knowledge of the dataset to configure other forms of data augmentation (e.g., flipping and to what degree, etc…)</p>
<p><strong>How does Mixup work?</strong></p>
<ol type="1">
<li>Select another random image</li>
<li>Pick a weight at random</li>
<li>Take a weighted average of the selected image with your image = <strong>Your independent variable</strong></li>
<li>Take a weighted average of the selected image’s labels with your image’s labels = <strong>Your dependent variable</strong></li>
<li>Use #3 to predict #4</li>
</ol>
<p>In pseudocode:</p>
<div class="sourceCode" id="cb12" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb12-1">img2, targ2 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> dataset[randint(<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>(dataset))]</span>
<span id="cb12-2">t <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> random_float(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.0</span>)</span>
<span id="cb12-3">new_img <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> t <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> img1 <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>t) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> img2</span>
<span id="cb12-4">new_targ <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> t <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> targ1 <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>t) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> targ2</span></code></pre></div>
<div class="callout callout-style-default 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">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>“For this to work, our targets need to be one-hot encoded”</p>
</div>
</div>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>“Mixup requires far more epochs”</p>
</div>
</div>
<div class="callout callout-style-default 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">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>“One of the reasons Mixup is so exciting is that it can be applied to types of data other than photos. In fact, some people have even shown good results by **using Mixup on activations inside their models, not just on inputs - this allows Mixup to be used for NLP and other data types too.”</p>
</div>
</div>
<p>See pp.247-249 for a detailed example of how Mixup works and is used in fastai</p>
<div id="cell-22" class="cell" data-outputid="ef31ac42-65b4-4a10-bb63-39d0c19bad8d">
<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">model <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> xresnet50()</span>
<span id="cb13-2">learn <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> Learner(dls, model, loss_func<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>CrossEntropyLossFlat(), metrics<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>accuracy, cbs<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>MixUp)</span>
<span id="cb13-3">learn.fit_one_cycle(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">3e-3</span>)</span></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-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-quarto-postprocess="true" 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">accuracy</th>
<th data-quarto-table-cell-role="th">time</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>0</td>
<td>2.183965</td>
<td>2.523945</td>
<td>0.320762</td>
<td>02:57</td>
</tr>
<tr class="even">
<td>1</td>
<td>1.729223</td>
<td>1.974045</td>
<td>0.461538</td>
<td>03:01</td>
</tr>
<tr class="odd">
<td>2</td>
<td>1.479313</td>
<td>1.131723</td>
<td>0.630695</td>
<td>03:07</td>
</tr>
<tr class="even">
<td>3</td>
<td>1.294975</td>
<td>0.872954</td>
<td>0.724421</td>
<td>03:08</td>
</tr>
<tr class="odd">
<td>4</td>
<td>1.183486</td>
<td>0.731506</td>
<td>0.776699</td>
<td>03:06</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="callout callout-style-default 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">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>“… it’s going to be hard to train, because … the model has to predict two labels per image rather than just one …. Overfitting seems less likely to be a problem.”</p>
</div>
</div>
</section>
<section id="tip-7-use-label-smoothing" class="level2">
<h2 class="anchored" data-anchor-id="tip-7-use-label-smoothing">Tip 7: Use “Label Smoothing”</h2>
<p>“In the theoretical expression of loss, <strong>in classification problems</strong>, our targets are one hot encoded …. That means the model is trained to return 0 for all categories but one, for which it is trained to return 1…. This encourages overfitting and gives you at inference time a model that is not going to give meaningful probabilities: it will always say 1 for the predicted category <strong>even if it’s not too sure</strong>, just because it was trained that way.</p>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>“This can become very harmful if your data is not perfectly labeled.”</p>
</div>
</div>
<p>“In general, your data will never be perfect. Even if the labels were manually produced by humans, they could make mistakes, or have differences of opinions on images that are harder to label”</p>
<p><strong>What is the solution this this?</strong></p>
<p>“… we could replace all our 1s with a number a bit less than 1, and our 0s with a number a bit more than 0, and then train. This is” = <strong>Label smoothing</strong>. “By encouraging your model to be a less confident, label smoothing will make your training more robust, <strong>even if there is mislabeled data. The result will be a model that generalizes better at inference</strong>.”</p>
<p>See pp.249-251 for a detailed explanation and example of how label smoothing operates. <strong>To use it, we just have to change our loss function.</strong></p>
<div id="cell-25" class="cell" data-outputid="4a510d06-b7ea-4a4a-a971-16cbcb0fddbd">
<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">model <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> xresnet50()</span>
<span id="cb14-2">learn <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> Learner(dls, model, loss_func<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>LabelSmoothingCrossEntropy(), metrics<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>accuracy)</span>
<span id="cb14-3">learn.fit_one_cycle(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">3e-3</span>)</span></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-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-quarto-postprocess="true" 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">accuracy</th>
<th data-quarto-table-cell-role="th">time</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>0</td>
<td>2.757509</td>
<td>3.500999</td>
<td>0.253921</td>
<td>03:06</td>
</tr>
<tr class="even">
<td>1</td>
<td>2.257501</td>
<td>2.817133</td>
<td>0.440627</td>
<td>03:00</td>
</tr>
<tr class="odd">
<td>2</td>
<td>1.968483</td>
<td>2.138581</td>
<td>0.617625</td>
<td>02:59</td>
</tr>
<tr class="even">
<td>3</td>
<td>1.781833</td>
<td>1.700527</td>
<td>0.772591</td>
<td>03:05</td>
</tr>
<tr class="odd">
<td>4</td>
<td>1.648491</td>
<td>1.632251</td>
<td>0.798357</td>
<td>03:01</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>“As with Mixup, you won’t generally see significant improvements from label smoothing until you train more epochs.”</p>
</div>
</div>
</section>
<section id="resources" class="level2">
<h2 class="anchored" data-anchor-id="resources">Resources</h2>
<ol type="1">
<li><p>https://book.fast.ai - The book’s website; it’s updated regularly with new content and recommendations from everything to GPUs to use, how to run things locally and on the cloud, etc…</p></li>
<li><p><a href="https://arxiv.org/abs/1812.01187">Bag of Tricks for Image Classification with Convolutional Neural Networks</a> discusses a variety of techniques you can use with CNNs</p></li>
<li><p><a href="https://myrtle.ai/how-to-train-your-resnet-8-bag-of-tricks/">How to Train Your ResNet 8: Bag of Tricks</a> discusses a variety of techniques you can use to training ResNets.</p></li>
<li><p><a href="https://airctic.com/0.12.0/">IceVision</a> is a great resource for all things computer vision and a fastai friendly library. You may want to follow these twitter accounts as well: <a href="https://twitter.com/ai_fast_track"><span class="citation" data-cites="ai_fast_track">@ai_fast_track</span></a> and <a href="https://twitter.com/fra_pochetti"><span class="citation" data-cites="Fra_Pochetti">@Fra_Pochetti</span></a> (creator of IceVision).</p></li>
</ol>


</section>

 ]]></description>
  <category>fastai</category>
  <category>fastbook</category>
  <category>classification</category>
  <category>computer vision</category>
  <category>techniques</category>
  <category>bag of tricks</category>
  <guid>https://ohmeow.com/posts/2022-03-28-ajtfb-chapter-7.html</guid>
  <pubDate>Mon, 28 Mar 2022 07:00:00 GMT</pubDate>
  <media:content url="https://ohmeow.com/posts/images/fastbook.jpg" medium="image" type="image/jpeg"/>
</item>
<item>
  <title>A Journey Through Fastbook (AJTFB) - Chapter 6: Regression</title>
  <dc:creator>Wayde Gilliam</dc:creator>
  <link>https://ohmeow.com/posts/2022-02-09-ajtfb-chapter-6-regression.html</link>
  <description><![CDATA[ 




<p>Other posts in this series:</p>
<p><a href="../posts/2020-11-06-ajtfb-chapter-1.html">A Journey Through Fastbook (AJTFB) - Chapter 1</a><br>
<a href="../posts/2020-11-16-ajtfb-chapter-2.html">A Journey Through Fastbook (AJTFB) - Chapter 2</a><br>
<a href="../posts/2020-11-22-ajtfb-chapter-3.html">A Journey Through Fastbook (AJTFB) - Chapter 3</a><br>
<a href="../posts/2021-05-23-ajtfb-chapter-4.html">A Journey Through Fastbook (AJTFB) - Chapter 4</a><br>
<a href="../posts/2021-06-03-ajtfb-chapter-5.html">A Journey Through Fastbook (AJTFB) - Chapter 5</a><br>
<a href="../posts/2021-06-10-ajtfb-chapter-6-multilabel.html">A Journey Through Fastbook (AJTFB) - Chapter 6a</a><br>
<a href="../posts/2022-03-28-ajtfb-chapter-7.html">A Journey Through Fastbook (AJTFB) - Chapter 7</a><br>
<a href="../posts/2022-03-31-ajtfb-chapter-8.html">A Journey Through Fastbook (AJTFB) - Chapter 8</a><br>
<a href="../posts/2022-04-25-ajtfb-chapter-9.html">A Journey Through Fastbook (AJTFB) - Chapter 9</a></p>
<section id="regression" class="level2">
<h2 class="anchored" data-anchor-id="regression">Regression</h2>
<p>A <strong>regression</strong> task is all about predicting a <a href="https://ohmeow.com/posts/2020/11/06/ajtfb-chapter-1.html#Continuous-datatypes">continous</a> value rather than a particular cateogry.</p>
<p>Here we’ll consider a particular type of regression problem called <strong><em>image regression</em></strong>, where the “independent variable is an image, and the dependent variable is one or more float.” Our model is going to be a <strong><em>key point</em></strong> model that aims to predict a point (e.g., 2 labels … the x and y) on the image, which in our example is the center of a person’s face.</p>
</section>
<section id="defining-your-datablock" class="level2">
<h2 class="anchored" data-anchor-id="defining-your-datablock">Defining your DataBlock</h2>
<p>Again, the <code>DataBlock</code> is a blueprint for everything required to turn your raw data (images and labels) into something that can be fed through a neural network (DataLoaders with a numerical representation of both your images and labels). Below is the one presented in this chapter.</p>
<div id="cell-6" class="cell" data-outputid="ab64508c-3223-4850-feff-a170ce85b14b" data-execution_count="3">
<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="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="cb1-2">path <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> untar_data(URLs.BIWI_HEAD_POSE)</span>
<span id="cb1-3"></span>
<span id="cb1-4">path.ls()</span></code></pre></div>
<div class="cell-output cell-output-display" data-execution_count="3">
<pre><code>(#50) [Path('/root/.fastai/data/biwi_head_pose/02.obj'),Path('/root/.fastai/data/biwi_head_pose/04'),Path('/root/.fastai/data/biwi_head_pose/10'),Path('/root/.fastai/data/biwi_head_pose/17.obj'),Path('/root/.fastai/data/biwi_head_pose/23.obj'),Path('/root/.fastai/data/biwi_head_pose/21.obj'),Path('/root/.fastai/data/biwi_head_pose/24.obj'),Path('/root/.fastai/data/biwi_head_pose/12.obj'),Path('/root/.fastai/data/biwi_head_pose/10.obj'),Path('/root/.fastai/data/biwi_head_pose/01')...]</code></pre>
</div>
</div>
<p>“There are 24 directories numbered from 01 to 24 (they corresond to the different people photographed), and a corresponding <em>.obj</em> file for each (we won’t need them here)</p>
<div class="callout callout-style-default callout-tip 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">
Tip
</div>
</div>
<div class="callout-body-container callout-body">
<p>Always EDA your dataset to make sure you understand how it is organized; this is especially important to ensure you create a good validation set without leakage from the training set.</p>
</div>
</div>
<div class="callout callout-style-default 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">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>“… we should not just use a random splitter [so as] to ensure that our model can generalize to people that it hasn’t seen yet; a splitter function that returns True for just one person, resulting in a validation set containing just that one person.”</p>
</div>
</div>
<div id="cell-8" class="cell" data-outputid="c940e783-ede9-4187-c338-db30b73b8522" data-execution_count="4">
<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">(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;">'01'</span>).ls()</span></code></pre></div>
<div class="cell-output cell-output-display" data-execution_count="4">
<pre><code>(#1000) [Path('/root/.fastai/data/biwi_head_pose/01/frame_00486_rgb.jpg'),Path('/root/.fastai/data/biwi_head_pose/01/frame_00023_pose.txt'),Path('/root/.fastai/data/biwi_head_pose/01/frame_00122_rgb.jpg'),Path('/root/.fastai/data/biwi_head_pose/01/frame_00165_rgb.jpg'),Path('/root/.fastai/data/biwi_head_pose/01/frame_00167_pose.txt'),Path('/root/.fastai/data/biwi_head_pose/01/frame_00384_rgb.jpg'),Path('/root/.fastai/data/biwi_head_pose/01/frame_00287_rgb.jpg'),Path('/root/.fastai/data/biwi_head_pose/01/frame_00075_rgb.jpg'),Path('/root/.fastai/data/biwi_head_pose/01/frame_00186_pose.txt'),Path('/root/.fastai/data/biwi_head_pose/01/frame_00444_rgb.jpg')...]</code></pre>
</div>
</div>
<p>Looks like each person has multiple images, and for each image there is a text file telling us where the point is. We can write a function to get the .txt file for any given image as such</p>
<div id="cell-10" class="cell" data-outputid="2a91c68a-2169-4845-af30-f82d7419a8ce" data-execution_count="5">
<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">img_files <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> get_image_files(path)</span>
<span id="cb5-2"></span>
<span id="cb5-3"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> img2pose(img_fpath):</span>
<span id="cb5-4">  <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> Path(<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;">str</span>(img_fpath)[:<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;">7</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;">pose.txt"</span>)</span>
<span id="cb5-5"></span>
<span id="cb5-6">img2pose(img_files[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>])</span></code></pre></div>
<div class="cell-output cell-output-display" data-execution_count="5">
<pre><code>Path('/root/.fastai/data/biwi_head_pose/04/frame_00486_pose.txt')</code></pre>
</div>
</div>
<div class="callout callout-style-default callout-tip 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">
Tip
</div>
</div>
<div class="callout-body-container callout-body">
<p>Look at your inputs/targets to verify you’re understanding of them is correct</p>
</div>
</div>
<div id="cell-12" class="cell" data-outputid="530f720c-092d-444e-fc4b-3b0a158519bc" data-execution_count="6">
<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">img <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> PILImage.create(img_files[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>])</span>
<span id="cb7-2"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(img.shape)</span>
<span id="cb7-3">img.to_thumb(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">160</span>)</span></code></pre></div>
<div class="cell-output cell-output-stdout">
<pre><code>(480, 640)</code></pre>
</div>
<div class="cell-output cell-output-display" data-execution_count="6">
<div>
<figure class="figure">
<p><img src="https://ohmeow.com/posts/2022-02-09-ajtfb-chapter-6-regression_files/figure-html/cell-7-output-2.png" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
<p>And the books provides the function to use to extract the x/y (point) which is given as …</p>
<div id="cell-14" class="cell" data-execution_count="7">
<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">cal <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.genfromtxt(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;">'01'</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;">'rgb.cal'</span>, skip_footer<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>
<span id="cb9-2"></span>
<span id="cb9-3"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> get_img_center(img_fpath):</span>
<span id="cb9-4">  ctr <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.genfromtxt(img2pose(img_fpath), skip_header<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="cb9-5">  x <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> ctr[<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> cal[<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;">0</span>]<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>ctr[<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> cal[<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>
<span id="cb9-6">  y <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> ctr[<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> cal[<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>]<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>ctr[<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> cal[<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>
<span id="cb9-7"></span>
<span id="cb9-8">  <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> tensor([x,y])</span></code></pre></div>
</div>
<div id="cell-15" class="cell" data-outputid="8f897fde-abf8-4662-dd76-93c569b7d3bd" data-execution_count="8">
<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">get_img_center(img_files[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>])</span></code></pre></div>
<div class="cell-output cell-output-display" data-execution_count="8">
<pre><code>tensor([416.9190, 250.1563])</code></pre>
</div>
</div>
<p>And with the above info and methods, we can now construct our <code>DataBlock</code></p>
<div id="cell-17" class="cell" data-execution_count="15">
<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">dblock <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> DataBlock(</span>
<span id="cb12-2">    blocks<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>(ImageBlock, PointBlock),</span>
<span id="cb12-3">    get_items<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>get_image_files,</span>
<span id="cb12-4">    get_y<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>get_img_center,</span>
<span id="cb12-5">    splitter<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>FuncSplitter(<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">lambda</span> o: o.parent.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;">'13'</span>),</span>
<span id="cb12-6">    batch_tfms<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>aug_transforms(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;">240</span>,<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">320</span>)), Normalize.from_stats(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>imagenet_stats)]</span>
<span id="cb12-7">)</span></code></pre></div>
</div>
<p><strong>Let’s break down our blueprint</strong>!</p>
<ol type="1">
<li>Define the data types for our inputs and targets via the <code>blocks</code> argument.</li>
</ol>
<p>Here our targets are of type <code>PointBlock</code>. “This is necessary so that fastai knows that the labels represent coordinates … <strong><em>it knows that when doing data augmentation, it should do the same augmentation to these coordinates as it does to the images.</em></strong>”</p>
<ol start="2" type="1">
<li>Define how we’re going to get our images via <code>get_items</code>.</li>
</ol>
<p>Can just use the <code>get_image_files</code> since we will be passing the <code>path</code> into our <code>DataBlock.dataloaders()</code> method</p>
<ol start="3" type="1">
<li>Define how, from the raw data, we’re going to create our labels via <code>get_y</code>.</li>
</ol>
<p>Will simply use the <code>get_img_center</code> we defined above since we will get getting a bunch of paths to images.</p>
<ol start="4" type="1">
<li>Define how we’re going to create our <a href="https://www.fast.ai/2017/11/13/validation-sets/">validation dataset</a> via <code>splitter</code></li>
</ol>
<p>Here we define a custom splitter using <code>FuncSplitter</code>, which gives us complete control in how our validation set is determined. Here it will be all the images associated to person “13”.</p>
<ol start="5" type="1">
<li>Define things we want to do for each item via <code>item_tfms</code></li>
</ol>
<p>Nothing for this example</p>
<ol start="6" type="1">
<li>Define things we want to do for each mini-batch of items via <code>batch_tfms</code></li>
</ol>
<p>For each minibatch of data, we’ll resize each image to 320x240 pixels and apply the default augmentations specified in <code>aug_transforms</code>. We’ll also normalize our images used the ImageNet mean/standard deviations since our pretrained model was trained on ImageNet.</p>
<div class="callout callout-style-default 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">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>If you want to serialize your <code>Learner</code>, do not use lambda functions for defining your DataBlock methods! They can’t be pickled.</p>
</div>
</div>
<div id="cell-19" class="cell" data-outputid="4660a394-32dd-4bba-8cd9-3c12c9849359" data-execution_count="20">
<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">dls <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> dblock.dataloaders(path)</span>
<span id="cb13-2">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;">9</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;">8</span>,<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span>))</span></code></pre></div>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://ohmeow.com/posts/2022-02-09-ajtfb-chapter-6-regression_files/figure-html/cell-11-output-1.png" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
<p>To get a feel for what our <code>item_tfms</code> and <code>batch_tfms</code> are doing, we can <code>show_batch</code> using a single image as we do below.</p>
<div id="cell-21" class="cell" data-outputid="6ff5e5ef-1a07-4f20-d1df-9c32d7ba48d8" data-execution_count="19">
<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">dls.show_batch(unique<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 class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://ohmeow.com/posts/2022-02-09-ajtfb-chapter-6-regression_files/figure-html/cell-12-output-1.png" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
<div class="callout callout-style-default callout-tip 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">
Tip
</div>
</div>
<div class="callout-body-container callout-body">
<p>It is recommended to see what the tensors look like as well</p>
</div>
</div>
<div id="cell-23" class="cell" data-outputid="90fb1bed-6907-4c95-ad98-6741af051f8b" data-execution_count="22">
<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">xb, yb <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> dls.one_batch()</span>
<span id="cb15-2">xb.shape, yb.shape, yb[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>]</span></code></pre></div>
<div class="cell-output cell-output-display" data-execution_count="22">
<pre><code>(torch.Size([64, 3, 240, 320]),
 torch.Size([64, 1, 2]),
 TensorPoint([[0.2772, 0.0728]], device='cuda:0'))</code></pre>
</div>
</div>
</section>
<section id="train-a-model" class="level2">
<h2 class="anchored" data-anchor-id="train-a-model">Train a model</h2>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>“Once you think your data looks right, we generally recommend the next step should be using it to train a simple model” See bottom of p193 for why.</p>
</div>
</div>
<section id="y_range" class="level3">
<h3 class="anchored" data-anchor-id="y_range"><code>y_range</code></h3>
<div class="callout callout-style-default callout-tip 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">
Tip
</div>
</div>
<div class="callout-body-container callout-body">
<p><a href="https://ohmeow.com/posts/2020/11/06/ajtfb-chapter-1.html#What-if-our-target-is-continuous?"><code>y_range</code></a> should be used in regression tasks to narrow down the valid range of our targets.</p>
</div>
</div>
<p>It’s implementation in fastai is:</p>
<div class="sourceCode" id="cb17" 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> sigmoid_range(x, lo, hi): <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> torch.sigmoid(x) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> (hi<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>lo) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> lo</span></code></pre></div>
<p>… and looks like this when plotted:</p>
<div id="cell-26" class="cell" data-outputid="2f39554c-7e33-41b9-8b1f-cdc40f27b15d" data-execution_count="27">
<div class="sourceCode cell-code" id="cb18" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb18-1">plot_function(partial(sigmoid_range,low<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>,high<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;">min</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>, <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;">4</span>)</span></code></pre></div>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://ohmeow.com/posts/2022-02-09-ajtfb-chapter-6-regression_files/figure-html/cell-14-output-1.png" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
<div class="callout callout-style-default 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">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>Since we know “coordinates in fastai and PyTorch are always rescaled between -1 and 1, we can use those values when defining our <code>Learner</code></p>
</div>
</div>
</section>
<section id="define-your-loss-function" class="level3">
<h3 class="anchored" data-anchor-id="define-your-loss-function">Define your loss function</h3>
<p>As we didn’t define a loss function, fastai will pick one for us based on our task. Here is will be <code>MSELoss</code> (mean squared loss).</p>
<p>“… when coordinates are used as the dependent variable, most of the time we’re likely to be trying to predict something as close as possible; that’s basically what <code>MSELoss</code> does”</p>
<div id="cell-29" class="cell" data-outputid="7083a55c-25f5-4bc1-9233-d4265375c555" data-execution_count="28">
<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">dls.loss_func</span></code></pre></div>
<div class="cell-output cell-output-display" data-execution_count="28">
<pre><code>FlattenedLoss of MSELoss()</code></pre>
</div>
</div>
</section>
<section id="metrics" class="level3">
<h3 class="anchored" data-anchor-id="metrics">Metrics</h3>
<div class="callout callout-style-default callout-tip 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">
Tip
</div>
</div>
<div class="callout-body-container callout-body">
<p>“… MSE is already a useful metric for this task (although it’s probably more interpretable after we take the square root”</p>
</div>
</div>
</section>
<section id="define-our-learner-and-start-training" class="level3">
<h3 class="anchored" data-anchor-id="define-our-learner-and-start-training">Define our <code>Learner</code> and start training</h3>
<div id="cell-32" class="cell" data-execution_count="30">
<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">learn <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> cnn_learner(dls, resnet18, y_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;">1</span>,<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>))</span></code></pre></div>
</div>
<div id="cell-33" class="cell" data-outputid="0f2dfff8-bf91-4a1f-d78a-ef0e109c1b8a" data-execution_count="31">
<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">learn.lr_find()</span></code></pre></div>
<div class="cell-output cell-output-display">

</div>
<div class="cell-output cell-output-display" data-execution_count="31">
<pre><code>SuggestedLRs(valley=0.0008317637839354575)</code></pre>
</div>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://ohmeow.com/posts/2022-02-09-ajtfb-chapter-6-regression_files/figure-html/cell-17-output-3.png" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
<div id="cell-34" class="cell" data-outputid="1cbb0e9a-b561-45ca-e8bd-3edc8620b3da" data-execution_count="32">
<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">learn.fit_one_cycle(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2e-2</span>)</span></code></pre></div>
<div class="cell-output cell-output-display">
<table class="dataframe caption-top table table-sm table-striped small" data-quarto-postprocess="true" 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">time</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>0</td>
<td>0.049521</td>
<td>0.008220</td>
<td>02:13</td>
</tr>
<tr class="even">
<td>1</td>
<td>0.007028</td>
<td>0.001976</td>
<td>01:56</td>
</tr>
<tr class="odd">
<td>2</td>
<td>0.003018</td>
<td>0.001024</td>
<td>01:56</td>
</tr>
<tr class="even">
<td>3</td>
<td>0.001997</td>
<td>0.000425</td>
<td>01:56</td>
</tr>
<tr class="odd">
<td>4</td>
<td>0.001606</td>
<td>0.000190</td>
<td>01:56</td>
</tr>
</tbody>
</table>
</div>
</div>
<p>“Generally when we run this we got a loss of around 0.0001, which correspondes to this average coordinate prediction error:”</p>
<div class="sourceCode" id="cb25" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb25-1">math.sqrt(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.0001</span>) </span>
<span id="cb25-2"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># 0.01</span></span></code></pre></div>
<p>This is pretty accurate …</p>
<div id="cell-36" class="cell" data-outputid="634f530e-c6de-4a16-ea62-c7e827c3dd19" data-execution_count="33">
<div class="sourceCode cell-code" id="cb26" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb26-1">learn.show_results(ds_idx<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>, 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;">3</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;">6</span>,<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">8</span>))</span></code></pre></div>
<div class="cell-output cell-output-display">

</div>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://ohmeow.com/posts/2022-02-09-ajtfb-chapter-6-regression_files/figure-html/cell-19-output-2.png" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
</section>
</section>
<section id="summary" class="level2">
<h2 class="anchored" data-anchor-id="summary">Summary</h2>
<p>Pick your loss and metrics according to your task …</p>
<p>For single-label classification: <code>nn.CrossEntropyLoss</code> and accuracy, precision, recall, f1, etc…</p>
<p>For multi-label classification: <code>nn.BCEWithLogitsLoss</code> and accuracy, precision, recall, f1, etc…</p>
<p>For regression: <code>nn.MSELoss</code> and the square root of the validation loss as the metric</p>
</section>
<section id="resources" class="level2">
<h2 class="anchored" data-anchor-id="resources">Resources</h2>
<ol type="1">
<li>https://book.fast.ai - The book’s website; it’s updated regularly with new content and recommendations from everything to GPUs to use, how to run things locally and on the cloud, etc…</li>
</ol>


</section>

 ]]></description>
  <category>fastai</category>
  <category>fastbook</category>
  <category>regression</category>
  <category>computer vision</category>
  <category>key point</category>
  <guid>https://ohmeow.com/posts/2022-02-09-ajtfb-chapter-6-regression.html</guid>
  <pubDate>Wed, 09 Feb 2022 08:00:00 GMT</pubDate>
  <media:content url="https://ohmeow.com/posts/images/fastbook.jpg" medium="image" type="image/jpeg"/>
</item>
<item>
  <title>A Journey Through Fastbook (AJTFB) - Chapter 6: Multilabel Classification</title>
  <dc:creator>Wayde Gilliam</dc:creator>
  <link>https://ohmeow.com/posts/2021-06-10-ajtfb-chapter-6-multilabel.html</link>
  <description><![CDATA[ 




<p>Other posts in this series:</p>
<p><a href="../posts/2020-11-06-ajtfb-chapter-1.html">A Journey Through Fastbook (AJTFB) - Chapter 1</a><br>
<a href="../posts/2020-11-16-ajtfb-chapter-2.html">A Journey Through Fastbook (AJTFB) - Chapter 2</a><br>
<a href="../posts/2020-11-22-ajtfb-chapter-3.html">A Journey Through Fastbook (AJTFB) - Chapter 3</a><br>
<a href="../posts/2021-05-23-ajtfb-chapter-4.html">A Journey Through Fastbook (AJTFB) - Chapter 4</a><br>
<a href="../posts/2021-06-03-ajtfb-chapter-5.html">A Journey Through Fastbook (AJTFB) - Chapter 5</a><br>
<a href="../posts/2022-02-09-ajtfb-chapter-6-regression.html">A Journey Through Fastbook (AJTFB) - Chapter 6b</a><br>
<a href="../posts/2022-03-28-ajtfb-chapter-7.html">A Journey Through Fastbook (AJTFB) - Chapter 7</a><br>
<a href="../posts/2022-03-31-ajtfb-chapter-8.html">A Journey Through Fastbook (AJTFB) - Chapter 8</a><br>
<a href="../posts/2022-04-25-ajtfb-chapter-9.html">A Journey Through Fastbook (AJTFB) - Chapter 9</a></p>
<section id="multiclass-vs-multi-label-classification-again" class="level2">
<h2 class="anchored" data-anchor-id="multiclass-vs-multi-label-classification-again">Multiclass vs Multi-label classification (again)…</h2>
<p>Last post we saw that <strong>multiclass classification</strong> is all about predicting a SINGLE CLASS an object belongs to from a list of two or more classes. It’s the go to task if we’re confident that every image our model sees is going to be one of these classes. <strong>Cross-entropy loss</strong> is our go to loss function as it wants to confidently pick one thing.</p>
<p><strong>Multi-label classification</strong> involves predicting MULTIPLE CLASSES to which an object belongs; it can belong to one, some, all, or even none of those classes. For example, you may be looking at satellite photos from which you need to predict the different kinds of terrain (your classes) each contains.</p>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>Use the multi-label classification approach in your “multiclassification problems” where you want your model to be able to result in None (which is probably a more common real world use case)</p>
</div>
</div>
</section>
<section id="defining-your-datablock" class="level2">
<h2 class="anchored" data-anchor-id="defining-your-datablock">Defining your DataBlock</h2>
<p>Again, the <code>DataBlock</code> is a blueprint for everything required to turn your raw data (images and labels) into something that can be fed through a neural network (DataLoaders with a numerical representation of both your images and labels). Below is the one presented in this chapter.</p>
<div id="cell-6" class="cell" data-outputid="04a73c17-1684-417f-cbcf-013dfdd2e8ed" data-execution_count="3">
<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="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="cb1-2">path <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> untar_data(URLs.PASCAL_2007)</span></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-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {
        background: #F44336;
    }
</style>
</div>
<div class="cell-output cell-output-display">

    <div>
      <progress value="1637801984" class="" max="1637796771" style="width:300px; height:20px; vertical-align: middle;"></progress>
      100.00% [1637801984/1637796771 01:41&lt;00:00]
    </div>
    
</div>
</div>
<p>Instead of working with the filesystem structure to get our images and define our labels, in this example we use a .csv file that we can explore and manipulate further via a pandas <strong>DataFrame</strong>.</p>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>DataFrames are one of those things you’re going to want to get comfortable using. Personally, I love using them if for nothing else, for how ubiquitous they are. You can create them from .csv files, excel files, dictionaries, from a sql database, and so forth. This makes them a fabulous datasource around which to build your DataBlocks!</p>
</div>
</div>
<p>Here are some of my favorite pandas resources: 1. https://chrisalbon.com/ 2. https://pandas.pydata.org/docs/ (yah, the docs are really good!)</p>
<div id="cell-8" class="cell" data-outputid="bd839e9f-add2-4df4-a9c5-e92c6281aaa3" data-execution_count="4">
<div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb2-1">df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> pd.read_csv(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;">'train.csv'</span>)</span>
<span id="cb2-2">df.head()</span></code></pre></div>
<div class="cell-output cell-output-display" data-execution_count="4">

  <div id="df-eec720ad-52d3-4742-b946-af2dd161dc33">
    <div class="colab-df-container">
      <div>


<table class="dataframe caption-top table table-sm table-striped small" data-quarto-postprocess="true" data-border="1">
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th">fname</th>
<th data-quarto-table-cell-role="th">labels</th>
<th data-quarto-table-cell-role="th">is_valid</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td data-quarto-table-cell-role="th">0</td>
<td>000005.jpg</td>
<td>chair</td>
<td>True</td>
</tr>
<tr class="even">
<td data-quarto-table-cell-role="th">1</td>
<td>000007.jpg</td>
<td>car</td>
<td>True</td>
</tr>
<tr class="odd">
<td data-quarto-table-cell-role="th">2</td>
<td>000009.jpg</td>
<td>horse person</td>
<td>True</td>
</tr>
<tr class="even">
<td data-quarto-table-cell-role="th">3</td>
<td>000012.jpg</td>
<td>car</td>
<td>False</td>
</tr>
<tr class="odd">
<td data-quarto-table-cell-role="th">4</td>
<td>000016.jpg</td>
<td>bicycle</td>
<td>True</td>
</tr>
</tbody>
</table>

</div>
      <button class="colab-df-convert" onclick="convertToInteractive('df-eec720ad-52d3-4742-b946-af2dd161dc33')" title="Convert this dataframe to an interactive table." style="display:none;">
        
  <svg xmlns="http://www.w3.org/2000/svg" height="24px" viewbox="0 0 24 24" width="24px">
    <path d="M0 0h24v24H0V0z" fill="none"></path>
    <path d="M18.56 5.44l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94zm-11 1L8.5 8.5l.94-2.06 2.06-.94-2.06-.94L8.5 2.5l-.94 2.06-2.06.94zm10 10l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94z"></path><path d="M17.41 7.96l-1.37-1.37c-.4-.4-.92-.59-1.43-.59-.52 0-1.04.2-1.43.59L10.3 9.45l-7.72 7.72c-.78.78-.78 2.05 0 2.83L4 21.41c.39.39.9.59 1.41.59.51 0 1.02-.2 1.41-.59l7.78-7.78 2.81-2.81c.8-.78.8-2.07 0-2.86zM5.41 20L4 18.59l7.72-7.72 1.47 1.35L5.41 20z"></path>
  </svg>
      </button>
      
  <style>
    .colab-df-container {
      display:flex;
      flex-wrap:wrap;
      gap: 12px;
    }

    .colab-df-convert {
      background-color: #E8F0FE;
      border: none;
      border-radius: 50%;
      cursor: pointer;
      display: none;
      fill: #1967D2;
      height: 32px;
      padding: 0 0 0 0;
      width: 32px;
    }

    .colab-df-convert:hover {
      background-color: #E2EBFA;
      box-shadow: 0px 1px 2px rgba(60, 64, 67, 0.3), 0px 1px 3px 1px rgba(60, 64, 67, 0.15);
      fill: #174EA6;
    }

    [theme=dark] .colab-df-convert {
      background-color: #3B4455;
      fill: #D2E3FC;
    }

    [theme=dark] .colab-df-convert:hover {
      background-color: #434B5C;
      box-shadow: 0px 1px 3px 1px rgba(0, 0, 0, 0.15);
      filter: drop-shadow(0px 1px 2px rgba(0, 0, 0, 0.3));
      fill: #FFFFFF;
    }
  </style>

      <script>
        const buttonEl =
          document.querySelector('#df-eec720ad-52d3-4742-b946-af2dd161dc33 button.colab-df-convert');
        buttonEl.style.display =
          google.colab.kernel.accessAllowed ? 'block' : 'none';

        async function convertToInteractive(key) {
          const element = document.querySelector('#df-eec720ad-52d3-4742-b946-af2dd161dc33');
          const dataTable =
            await google.colab.kernel.invokeFunction('convertToInteractive',
                                                     [key], {});
          if (!dataTable) return;

          const docLinkHtml = 'Like what you see? Visit the ' +
            '<a target="_blank" href=https://colab.research.google.com/notebooks/data_table.ipynb>data table notebook</a>'
            + ' to learn more about interactive tables.';
          element.innerHTML = '';
          dataTable['output_type'] = 'display_data';
          await google.colab.output.renderOutput(dataTable, element);
          const docLink = document.createElement('div');
          docLink.innerHTML = docLinkHtml;
          element.appendChild(docLink);
        }
      </script>
    </div>
  </div>
  
</div>
</div>
<div id="cell-9" class="cell" data-execution_count="5">
<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="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> get_x(r): <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> 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;">'train'</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>r[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'fname'</span>]</span>
<span id="cb3-2"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> get_y(r): <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> r[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'labels'</span>].split(<span class="st" style="color: #20794D;
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> splitter(df):</span>
<span id="cb3-5">  train <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> df.index[<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">~</span>df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'is_valid'</span>]].tolist()</span>
<span id="cb3-6">  valid <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> df.index[df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'is_valid'</span>]].tolist()</span>
<span id="cb3-7">  <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> train, valid</span>
<span id="cb3-8"></span>
<span id="cb3-9">dblock <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> DataBlock(blocks<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>(ImageBlock, MultiCategoryBlock), </span>
<span id="cb3-10">                   get_x<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>get_x, </span>
<span id="cb3-11">                   get_y<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>get_y,</span>
<span id="cb3-12">                   splitter<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>splitter, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># or could just have used ColSplitter()   </span></span>
<span id="cb3-13">                   item_tfms<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>RandomResizedCrop(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">128</span>, min_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.35</span>))</span></code></pre></div>
</div>
<p><strong>Let’s break down our blueprint</strong>!</p>
<ol type="1">
<li>Define the data types for our inputs and targets via the <code>blocks</code> argument.</li>
</ol>
<p>This is defined as a tuple, where we tell our <code>DataBlock</code> that the imputs are images and our targets are multiple potential categories. Above we can see that these labels are space delimited in the “labels” column. The later essentially returns a one-hot encoded list of possible labels, with a 0 indicating that the label wasn’t found for the item and a 1 indicating otherwise (see the <code>DataBlock.summary</code> results below).</p>
<ol start="2" type="1">
<li>Define how we’re going to get our images via <code>get_x</code>.</li>
</ol>
<p>As we’ll be passing in a Dataframe as the raw data source, we don’t need to define a <code>get_items</code> to pull the raw data. We do however, need to instruct the DataBlock as to how to find the images, which we do via the <code>get_x</code> method. That method will get one row of DataFrame (<code>r</code>) at a time.</p>
<ol start="3" type="1">
<li>Define how, from the raw data, we’re going to create our labels via <code>get_y</code>.</li>
</ol>
<p>As already mentioned, the classes are in the “labels” column and delimited by a space, and so, we return a list of labels splitting on ’ ’. Easy peasy.</p>
<ol start="4" type="1">
<li>Define how we’re going to create our <a href="https://www.fast.ai/2017/11/13/validation-sets/">validation dataset</a> via <code>splitter</code></li>
</ol>
<p>Here we define a custom splitter mostly to just show you how to do it. It has to return at least a tuple of train, validation data. We could have just used <code>ColSplitter</code> (<a href="https://docs.fast.ai/data.transforms.html#ColSplitter">see it in the docs here</a>)</p>
<ol start="5" type="1">
<li>Define things we want to do for each item via <code>item_tfms</code></li>
</ol>
<p><code>item_tfms</code> are transforms, or things we want to do, to each input individually! Above we only have one which says, “Randomly crop the image to be 128x128 that captures at least 35% of the image each time you grab an image”. See here for more info on <a href="https://docs.fast.ai/vision.augment.html#RandomResizedCrop"><code>RandomResizedCrop</code></a></p>
<ol start="6" type="1">
<li>Define things we want to do for each mini-batch of items via <code>batch_tfms</code></li>
</ol>
<p>None here, but remember that these are transforms you want applied to a mini-batch of images on the GPU at the same time.</p>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>Do not use lambda functions for defining your DataBlock methods! They can’t be serialized and so you’re lucky to get some errors when you try to save/export your DataLoaders and/or Learner</p>
</div>
</div>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>Verify your <code>DataBlock</code> works as expected, or else troubleshoot it, by running <code>DataBlock.summary(data)</code></p>
</div>
</div>
<div id="cell-11" class="cell" data-outputid="8c879a4f-7a11-485e-c820-71aa35972b81" data-execution_count="6">
<div class="sourceCode cell-code" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb4-1">dblock.summary(df)</span></code></pre></div>
<div class="cell-output cell-output-stdout">
<pre><code>Setting-up type transforms pipelines
Collecting items from            fname          labels  is_valid
0     000005.jpg           chair      True
1     000007.jpg             car      True
2     000009.jpg    horse person      True
3     000012.jpg             car     False
4     000016.jpg         bicycle      True
...          ...             ...       ...
5006  009954.jpg    horse person      True
5007  009955.jpg            boat      True
5008  009958.jpg  person bicycle      True
5009  009959.jpg             car     False
5010  009961.jpg             dog     False

[5011 rows x 3 columns]
Found 5011 items
2 datasets of sizes 2501,2510
Setting up Pipeline: get_x -&gt; PILBase.create
Setting up Pipeline: get_y -&gt; MultiCategorize -- {'vocab': None, 'sort': True, 'add_na': False} -&gt; OneHotEncode -- {'c': None}

Building one sample
  Pipeline: get_x -&gt; PILBase.create
    starting from
      fname       000012.jpg
labels             car
is_valid         False
Name: 3, dtype: object
    applying get_x gives
      /root/.fastai/data/pascal_2007/train/000012.jpg
    applying PILBase.create gives
      PILImage mode=RGB size=500x333
  Pipeline: get_y -&gt; MultiCategorize -- {'vocab': None, 'sort': True, 'add_na': False} -&gt; OneHotEncode -- {'c': None}
    starting from
      fname       000012.jpg
labels             car
is_valid         False
Name: 3, dtype: object
    applying get_y gives
      [car]
    applying MultiCategorize -- {'vocab': None, 'sort': True, 'add_na': False} gives
      TensorMultiCategory([6])
    applying OneHotEncode -- {'c': None} gives
      TensorMultiCategory([0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0.])

Final sample: (PILImage mode=RGB size=500x333, TensorMultiCategory([0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0.]))


Collecting items from            fname          labels  is_valid
0     000005.jpg           chair      True
1     000007.jpg             car      True
2     000009.jpg    horse person      True
3     000012.jpg             car     False
4     000016.jpg         bicycle      True
...          ...             ...       ...
5006  009954.jpg    horse person      True
5007  009955.jpg            boat      True
5008  009958.jpg  person bicycle      True
5009  009959.jpg             car     False
5010  009961.jpg             dog     False

[5011 rows x 3 columns]
Found 5011 items
2 datasets of sizes 2501,2510
Setting up Pipeline: get_x -&gt; PILBase.create
Setting up Pipeline: get_y -&gt; MultiCategorize -- {'vocab': None, 'sort': True, 'add_na': False} -&gt; OneHotEncode -- {'c': None}
Setting up after_item: Pipeline: RandomResizedCrop -- {'size': (128, 128), 'min_scale': 0.35, 'ratio': (0.75, 1.3333333333333333), 'resamples': (2, 0), 'val_xtra': 0.14, 'max_scale': 1.0, 'p': 1.0} -&gt; ToTensor
Setting up before_batch: Pipeline: 
Setting up after_batch: Pipeline: IntToFloatTensor -- {'div': 255.0, 'div_mask': 1}

Building one batch
Applying item_tfms to the first sample:
  Pipeline: RandomResizedCrop -- {'size': (128, 128), 'min_scale': 0.35, 'ratio': (0.75, 1.3333333333333333), 'resamples': (2, 0), 'val_xtra': 0.14, 'max_scale': 1.0, 'p': 1.0} -&gt; ToTensor
    starting from
      (PILImage mode=RGB size=500x333, TensorMultiCategory([0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0.]))
    applying RandomResizedCrop -- {'size': (128, 128), 'min_scale': 0.35, 'ratio': (0.75, 1.3333333333333333), 'resamples': (2, 0), 'val_xtra': 0.14, 'max_scale': 1.0, 'p': 1.0} gives
      (PILImage mode=RGB size=128x128, TensorMultiCategory([0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0.]))
    applying ToTensor gives
      (TensorImage of size 3x128x128, TensorMultiCategory([0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0.]))

Adding the next 3 samples

No before_batch transform to apply

Collating items in a batch

Applying batch_tfms to the batch built
  Pipeline: IntToFloatTensor -- {'div': 255.0, 'div_mask': 1}
    starting from
      (TensorImage of size 4x3x128x128, TensorMultiCategory of size 4x20)
    applying IntToFloatTensor -- {'div': 255.0, 'div_mask': 1} gives
      (TensorImage of size 4x3x128x128, TensorMultiCategory of size 4x20)</code></pre>
</div>
</div>
<p>Now we can create our <code>DataLoaders</code> and take a look at our x’s and y’s, our images and their labels (multiple labeled images have their labels separated by semi-colon)</p>
<div id="cell-13" class="cell" data-outputid="33962bd5-d0bb-4ce5-cf35-8774209ace71" data-execution_count="7">
<div class="sourceCode cell-code" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb6-1">dls <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> dblock.dataloaders(df)</span>
<span id="cb6-2">dls.show_batch()</span></code></pre></div>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://ohmeow.com/posts/2021-06-10-ajtfb-chapter-6-multilabel_files/figure-html/cell-8-output-1.png" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
<p>To get a feel for what our <code>item_tfms</code> (and <code>batch_tfms</code> if we had them) are doing, we can <code>show_batch</code> using a single image as we do below.</p>
<div id="cell-15" class="cell" data-outputid="e4340dd4-17bd-4069-eaf1-cac750f1b25d" data-execution_count="8">
<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">dls.show_batch(unique<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 class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://ohmeow.com/posts/2021-06-10-ajtfb-chapter-6-multilabel_files/figure-html/cell-9-output-1.png" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
<p>The combination of what we’re doing in the <code>item_tfms</code> and <code>batch_tfms</code> is known as <strong>presizing</strong>.</p>
<p>“Presizing is a particular way to do image augmentation that is designed to minimize data destruction while maintaining good performance.” After resizing all the images to a larger dimension that we will train on, we perform all our core augmentations on the GPU. This results in both faster and less destructive transformations of the data.</p>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>See pp190-191 for how these augmentations are applied to the training and validation set!</p>
</div>
</div>
</section>
<section id="train-a-model" class="level2">
<h2 class="anchored" data-anchor-id="train-a-model">Train a model</h2>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>“Once you think your data looks right, we generally recommend the next step should be using it to train a simple model” See bottom of p193 for why.</p>
</div>
</div>
<section id="define-your-loss-function" class="level3">
<h3 class="anchored" data-anchor-id="define-your-loss-function">Define your loss function</h3>
<p>To train a model we need a good loss function that will allow us to optimize the parameters of our model. For multi-label classification tasks where we want to predict a single class/label, to go to is <strong>binary cross-entropy loss</strong></p>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>Cross-entropy loss is the U.S. Marine of loss functions … “the few, the proud, the one hot encoded”</p>
</div>
</div>
<p><strong>Why can’t we just use cross-entropy loss?</strong></p>
<p>Because “the softmax function <em>really</em> wants to pick one class” whereas here want it to pick multiple or even none.</p>
<p>“<strong>softmax</strong> … requires that all predictions sum to 1, and tends to push one activation to be much larger than the others (because of the use of <code>exp</code>) … we may want the sum to be less than 1, if we don’t think <em>any</em> of the categories appear in an image.”</p>
<p>“<strong>nll_loss</strong> … returns the value of just one activation: the single activation corresponding with the single label for an item [which] doesn’t make sense when we have multiple labels”</p>
<div id="cell-19" class="cell" data-outputid="60ed91f6-0720-42c8-ea8f-d935fdc4dd39" data-execution_count="9">
<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">learn <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> cnn_learner(dls, resnet18)</span></code></pre></div>
<div class="cell-output cell-output-stderr">
<pre><code>Downloading: "https://download.pytorch.org/models/resnet18-f37072fd.pth" to /root/.cache/torch/hub/checkpoints/resnet18-f37072fd.pth</code></pre>
</div>
<div class="cell-output cell-output-display">
<script type="application/vnd.jupyter.widget-view+json">
{"model_id":"55479ae22b724c4d8ef810587f44e8bd","version_major":2,"version_minor":0,"quarto_mimetype":"application/vnd.jupyter.widget-view+json"}
</script>
</div>
</div>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>Run a batch through model to see/verify your batches and final activations look right.</p>
</div>
</div>
<div id="cell-21" class="cell" data-outputid="1d15fefd-0e89-4658-83d8-4b31d8f95bb0" data-execution_count="12">
<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">xb, yb <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> to_cpu(dls.train.one_batch())</span>
<span id="cb10-2">res <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> learn.model(xb)</span>
<span id="cb10-3">xb.shape, yb[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>], res.shape, res[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>]</span></code></pre></div>
<div class="cell-output cell-output-display" data-execution_count="12">
<pre><code>(torch.Size([64, 3, 128, 128]),
 TensorMultiCategory([0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 1., 0., 0.,
         0., 0.]),
 torch.Size([64, 20]),
 TensorBase([ 1.4774, -2.1223,  4.1004,  1.5169, -0.5184,  0.1914, -1.0933, -1.4870,
         -1.4855, -0.9137, -2.1899,  2.5738,  2.6155, -1.8979,  0.9340,  1.2691,
         -0.2225,  0.4355, -4.2410, -2.5808], grad_fn=&lt;AliasBackward0&gt;))</code></pre>
</div>
</div>
<p>So now we need a loss function that will scale those activations to be between 1 and 0 and then compare each activation with the value (0 or 1) in each target column.</p>
<div id="cell-23" class="cell" data-outputid="2954758b-3061-4fe1-f2f7-0dc90f04c4a3" data-execution_count="13">
<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"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> bce(inputs, targets):</span>
<span id="cb12-2">  inputs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> inputs.sigmoid()</span>
<span id="cb12-3">  <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>torch.where(targets<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>, inputs, <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>inputs).log().mean()</span>
<span id="cb12-4"></span>
<span id="cb12-5"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(bce(res, yb))</span></code></pre></div>
<div class="cell-output cell-output-stdout">
<pre><code>TensorMultiCategory(1.0537, grad_fn=&lt;AliasBackward0&gt;)</code></pre>
</div>
</div>
<p>So breaking the above down, line by line, for a single input/targets …</p>
<div id="cell-25" class="cell" data-outputid="931fa7c6-fc2e-490f-f948-82b5f0d8ef16" data-execution_count="14">
<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">inps <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> res.sigmoid()</span>
<span id="cb14-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'1. </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>inps[<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;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">'</span>)</span>
<span id="cb14-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'2. </span><span class="sc" 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 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="cb14-4"><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'3. </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>where(yb<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>, inps, <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>inps)[<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;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">'</span>)</span>
<span id="cb14-5"><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'4. </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>where(yb<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>, inps, <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>inps)[<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;">.</span>log()<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="cb14-6"><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'5. </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>where(yb<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>, inps, <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>inps)[<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;">.</span>log()<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>mean()<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="cb14-7"><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'6. </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>torch<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>where(yb<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>, inps, <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>inps)[<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;">.</span>log()<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>mean()<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 class="cell-output cell-output-stdout">
<pre><code>1. TensorBase([0.8142, 0.1070, 0.9837, 0.8201, 0.3732, 0.5477, 0.2510, 0.1844, 0.1846,
        0.2862, 0.1007, 0.9292, 0.9319, 0.1303, 0.7179, 0.7806, 0.4446, 0.6072,
        0.0142, 0.0704], grad_fn=&lt;AliasBackward0&gt;)
2. TensorMultiCategory([0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 1., 0., 0.,
        0., 0.])
3. TensorMultiCategory([0.1858, 0.8930, 0.0163, 0.1799, 0.3732, 0.4523, 0.7490, 0.8156, 0.8154,
        0.7138, 0.8993, 0.0708, 0.0681, 0.8697, 0.7179, 0.7806, 0.5554, 0.3928,
        0.9858, 0.9296], grad_fn=&lt;AliasBackward0&gt;)
4. TensorMultiCategory([-1.6830, -0.1131, -4.1168, -1.7153, -0.9856, -0.7934, -0.2890, -0.2038,
        -0.2041, -0.3372, -0.1061, -2.6473, -2.6861, -0.1397, -0.3314, -0.2477,
        -0.5881, -0.9344, -0.0143, -0.0730], grad_fn=&lt;AliasBackward0&gt;)
5. -0.9104629755020142
6. 0.9104629755020142</code></pre>
</div>
</div>
<p><strong>… what is binary cross-entropy loss doing?</strong></p>
<p>Scale all activations to be between 0 and 1 using the <code>sigmoid</code> function (1). The resulting activations tell us, for each potential label, how confident the model is that the value is a “1”.</p>
<p>Build a tensor with a value for each target (2); if the target = 1 then use the corresponding scaled value above … if the target = 0, then use 1 minus this value (3). <em>Notice how confident correct predictions will be very large, while confident incorrect predictions will be very small.</em> We can think of this value as telling us how right the model was in predicting each label.</p>
<p>Take the <code>log</code> (4) which will will turn correct and more confident predictions (those closer to 1) to a value closer to zero, and wrong and more confident prediction to a value closer to 0. This exactly what we want since the better the model, the smaller the lost, and the <code>log(1) = 0</code> where as the <code>log(0)</code> approaches negative infinity! See the chart below.</p>
<p>Lastly, because the loss has to be a single value, we mean the losses for each label (5), and then turn it into a positive (6).</p>
<div id="cell-27" class="cell" data-outputid="1f30383f-1c88-41eb-d049-30d6169732b2" data-execution_count="15">
<div class="sourceCode cell-code" id="cb16" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb16-1">plot_function(torch.log, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'x (prob correct class)'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'-log(x)'</span>, title<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Negative Log-Likelihood'</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">min</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;">0</span>, <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></code></pre></div>
<div class="cell-output cell-output-stderr">
<pre><code>/usr/local/lib/python3.7/dist-packages/ipykernel_launcher.py:3: UserWarning: Not providing a value for linspace's steps is deprecated and will throw a runtime error in a future release. This warning will appear only once per process. (Triggered internally at  ../aten/src/ATen/native/RangeFactories.cpp:23.)
  This is separate from the ipykernel package so we can avoid doing imports until</code></pre>
</div>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://ohmeow.com/posts/2021-06-10-ajtfb-chapter-6-multilabel_files/figure-html/cell-14-output-2.png" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>Review BCE and Cross Entropy Loss until you can explain it to your significant other :). They are by and far the most common loss functions you’ll come across and many of the problems you encounter in training your models will be because you’re using the wrong one.</p>
</div>
</div>
<p>Fortunately, PyTorch has a function and module we can use:</p>
<div id="cell-29" class="cell" data-outputid="a0ba174e-c1bb-44b6-e41e-2110dea65097" data-execution_count="16">
<div class="sourceCode cell-code" id="cb18" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb18-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># functional form</span></span>
<span id="cb18-2">loss <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> F.binary_cross_entropy_with_logits(res, yb)</span>
<span id="cb18-3"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(loss)</span>
<span id="cb18-4"></span>
<span id="cb18-5"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># modular form (most commonly used)</span></span>
<span id="cb18-6">loss_func <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> nn.BCEWithLogitsLoss()</span>
<span id="cb18-7">loss <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> loss_func(res, yb)</span>
<span id="cb18-8"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(loss)</span>
<span id="cb18-9"></span>
<span id="cb18-10"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># and for shits and giggles</span></span>
<span id="cb18-11"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(bce(res, yb))</span></code></pre></div>
<div class="cell-output cell-output-stdout">
<pre><code>TensorMultiCategory(1.0537, grad_fn=&lt;AliasBackward0&gt;)
TensorMultiCategory(1.0537, grad_fn=&lt;AliasBackward0&gt;)
TensorMultiCategory(1.0537, grad_fn=&lt;AliasBackward0&gt;)</code></pre>
</div>
</div>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>“Normally, for one-hot-encoded targets, you’ll want <code>F.binary_cross_entropy_with_logits</code> (or <code>nn.BCEWithLogitsLoss</code>), which do both sigmoid and binary cross entropy in a single function.</p>
</div>
</div>
<p>If the final activations already have the sigmoid applied to it, then you’d use <code>F.binary_cross_entropy</code> (or <code>nn.BCELoss</code>).</p>
</section>
<section id="define-your-metrics-and-thresholds" class="level3">
<h3 class="anchored" data-anchor-id="define-your-metrics-and-thresholds">Define Your Metrics and Thresholds</h3>
<p>One of the trickier bits with multilabel tasks, is selecting at what threshold (probability) do we want to consider a label 1 or 0. Using accuracy as our metric, we can play around with different values …</p>
<div id="cell-32" class="cell" data-outputid="2650a739-4f4b-4b54-a8e7-ce07de53c3b8" data-execution_count="17">
<div class="sourceCode cell-code" id="cb20" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb20-1">learn <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> cnn_learner(dls, resnet50, metrics<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>partial(accuracy_multi, thresh<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>))</span>
<span id="cb20-2">learn.fine_tune(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>, base_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;">3e-3</span>, freeze_epochs<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 class="cell-output cell-output-stderr">
<pre><code>Downloading: "https://download.pytorch.org/models/resnet50-0676ba61.pth" to /root/.cache/torch/hub/checkpoints/resnet50-0676ba61.pth</code></pre>
</div>
<div class="cell-output cell-output-display">
<script type="application/vnd.jupyter.widget-view+json">
{"model_id":"fb9719a51f4e4427b7f686a4aad439b0","version_major":2,"version_minor":0,"quarto_mimetype":"application/vnd.jupyter.widget-view+json"}
</script>
</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-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-quarto-postprocess="true" 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">accuracy_multi</th>
<th data-quarto-table-cell-role="th">time</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>0</td>
<td>0.939569</td>
<td>0.704923</td>
<td>0.230299</td>
<td>00:41</td>
</tr>
<tr class="even">
<td>1</td>
<td>0.820619</td>
<td>0.558957</td>
<td>0.290279</td>
<td>00:38</td>
</tr>
<tr class="odd">
<td>2</td>
<td>0.602579</td>
<td>0.195408</td>
<td>0.835618</td>
<td>00:38</td>
</tr>
<tr class="even">
<td>3</td>
<td>0.358107</td>
<td>0.122511</td>
<td>0.945438</td>
<td>00:38</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-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-quarto-postprocess="true" 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">accuracy_multi</th>
<th data-quarto-table-cell-role="th">time</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>0</td>
<td>0.131727</td>
<td>0.116799</td>
<td>0.945359</td>
<td>00:41</td>
</tr>
<tr class="even">
<td>1</td>
<td>0.116440</td>
<td>0.109859</td>
<td>0.949861</td>
<td>00:40</td>
</tr>
<tr class="odd">
<td>2</td>
<td>0.097460</td>
<td>0.103571</td>
<td>0.954841</td>
<td>00:40</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>We didn’t have to specify BCE as our loss function above because fastai was smart enough to figure it out from the dataset. This isn’t always the case, in particular when you start building your own or use 3rd party models for training. So Trainer beware!</p>
</div>
</div>
<div id="cell-34" class="cell" data-outputid="1b28deed-7fa8-4468-ca06-365170da12eb" data-execution_count="18">
<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">learn.metrics <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> partial(accuracy_multi, thresh<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>)</span>
<span id="cb22-2"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(learn.validate())</span>
<span id="cb22-3"></span>
<span id="cb22-4">learn.metrics <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> partial(accuracy_multi, thresh<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.9</span>)</span>
<span id="cb22-5"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(learn.validate())</span>
<span id="cb22-6"></span>
<span id="cb22-7">learn.metrics <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> partial(accuracy_multi, thresh<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.75</span>)</span>
<span id="cb22-8"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(learn.validate())</span></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-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><code>[0.10357054322957993, 0.9548406004905701]</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-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><code>[0.10357054322957993, 0.9559162855148315]</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-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><code>[0.10357054322957993, 0.9615935683250427]</code></pre>
</div>
</div>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>“This is much faster if we grab the predictions just once …. Note that by default <code>get_preds</code> applies the output activat function (sigmoid, in this case) for us, so we’ll need to tell <code>accuracy_multi</code> to not apply it”</p>
</div>
</div>
<div id="cell-36" class="cell" data-outputid="2e3f4b24-a66e-4074-cf8e-9212aa920952" data-execution_count="19">
<div class="sourceCode cell-code" id="cb26" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb26-1">preds, targs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> learn.get_preds()</span></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-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {
        background: #F44336;
    }
</style>
</div>
<div class="cell-output cell-output-display">

</div>
</div>
<div id="cell-37" class="cell" data-outputid="559aaf21-9ab1-4172-b75d-61b68b1a9d61" data-execution_count="20">
<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="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(accuracy_multi(preds, targs, thresh<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.9</span>, sigmoid<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 class="cell-output cell-output-stdout">
<pre><code>TensorBase(0.9559)</code></pre>
</div>
</div>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>Find the best threshold by testing over a range of potential thresholds!</p>
</div>
</div>
<div id="cell-39" class="cell" data-outputid="8ce15825-56a3-461a-c549-7baafaf86d96" data-execution_count="21">
<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">thresholds <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> torch.linspace(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.99</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">29</span>)</span>
<span id="cb29-2">accs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [accuracy_multi(preds, targs, thresh<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>th, sigmoid<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="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> th <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> thresholds]</span>
<span id="cb29-3">plt.plot(thresholds, accs)</span></code></pre></div>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://ohmeow.com/posts/2021-06-10-ajtfb-chapter-6-multilabel_files/figure-html/cell-20-output-1.png" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
<div id="cell-40" class="cell" data-outputid="a5f91449-4a7e-4a00-f80e-1cd4c8367657" data-execution_count="22">
<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"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(accuracy_multi(preds, targs, thresh<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.55</span>, sigmoid<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 class="cell-output cell-output-stdout">
<pre><code>TensorBase(0.9640)</code></pre>
</div>
</div>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>“… using the validation set to pick a hyperparameter (the threshold), which is the purpose of the validation set” is perfectly fine here. “As you see in the plot, changing the threshold in this case results in a smooth curve, so we’re clearly not picking an inappropriate outlier”.</p>
</div>
</div>
<p>See p.231 for more discussion on this.</p>
</section>
</section>
<section id="summary" class="level2">
<h2 class="anchored" data-anchor-id="summary">Summary</h2>
<p>You now know how to train both multi-label and muticlass vistion problems, when to use one or another, and what loss function to choose for each. You should consider treating multiclass problems where the predicted class should be “None” as a multi-label problem, especially if this is going to be used in the real-world and not just against some prefabbed dataset.</p>
<p>Also, we’re using accuracy as our metric to optimize the threshold in the example above, <em>but</em> you can use any metric (or combination of metrics you want). For example, a common issue with multi-label tasks is unbalanced datasets where one or more targets are ill represented in number. In that case, it may be more productive to use something like F1 or Recall.</p>
</section>
<section id="resources" class="level2">
<h2 class="anchored" data-anchor-id="resources">Resources</h2>
<ol type="1">
<li>https://book.fast.ai - The book’s website; it’s updated regularly with new content and recommendations from everything to GPUs to use, how to run things locally and on the cloud, etc…</li>
<li>To learn more about pandas check the <a href="https://pandas.pydata.org/docs/">pandas documentation</a> and <a href="https://chrisalbon.com/">chrisalbon.com</a>.</li>
</ol>


</section>

 ]]></description>
  <category>fastai</category>
  <category>fastbook</category>
  <category>multi-label classification</category>
  <category>binary cross entropy</category>
  <category>BCE</category>
  <category>computer vision</category>
  <guid>https://ohmeow.com/posts/2021-06-10-ajtfb-chapter-6-multilabel.html</guid>
  <pubDate>Thu, 10 Jun 2021 07:00:00 GMT</pubDate>
  <media:content url="https://ohmeow.com/posts/images/fastbook.jpg" medium="image" type="image/jpeg"/>
</item>
<item>
  <title>A Journey Through Fastbook (AJTFB) - Chapter 5: Multiclass classification</title>
  <dc:creator>Wayde Gilliam</dc:creator>
  <link>https://ohmeow.com/posts/2021-06-03-ajtfb-chapter-5.html</link>
  <description><![CDATA[ 




<p>Other posts in this series:</p>
<p><a href="../posts/2020-11-06-ajtfb-chapter-1.html">A Journey Through Fastbook (AJTFB) - Chapter 1</a><br>
<a href="../posts/2020-11-16-ajtfb-chapter-2.html">A Journey Through Fastbook (AJTFB) - Chapter 2</a><br>
<a href="../posts/2020-11-22-ajtfb-chapter-3.html">A Journey Through Fastbook (AJTFB) - Chapter 3</a><br>
<a href="../posts/2021-05-23-ajtfb-chapter-4.html">A Journey Through Fastbook (AJTFB) - Chapter 4</a><br>
<a href="../posts/2021-06-10-ajtfb-chapter-6-multilabel.html">A Journey Through Fastbook (AJTFB) - Chapter 6a</a><br>
<a href="../posts/2022-02-09-ajtfb-chapter-6-regression.html">A Journey Through Fastbook (AJTFB) - Chapter 6b</a><br>
<a href="../posts/2022-03-28-ajtfb-chapter-7.html">A Journey Through Fastbook (AJTFB) - Chapter 7</a><br>
<a href="../posts/2022-03-31-ajtfb-chapter-8.html">A Journey Through Fastbook (AJTFB) - Chapter 8</a><br>
<a href="../posts/2022-04-25-ajtfb-chapter-9.html">A Journey Through Fastbook (AJTFB) - Chapter 9</a></p>
<section id="multiclass-vs-multi-label-classification" class="level2">
<h2 class="anchored" data-anchor-id="multiclass-vs-multi-label-classification">Multiclass vs Multi-label classification …</h2>
<p>Yah, it can be confusing!</p>
<p>Anyhow, <strong>multiclass classification</strong> is all about predicting a SINGLE CLASS an object belongs to from a list of two or more classes. It can be a simple as predicting whether an image is a dog or a cat, or as complex as predicting the breed of dog from amongst dozens of potential breeds.</p>
<p><strong>Multi-label classification</strong> (covered in the next chapter) involves predicting MULTIPLE CLASSES to which an object belongs; it can belong to one, some, all, or even none of those classes. For example, you may be looking at satellite photos from which you need to predict the different kinds of terrain (your classes) each contains.</p>
</section>
<section id="defining-your-datablock" class="level2">
<h2 class="anchored" data-anchor-id="defining-your-datablock">Defining your DataBlock</h2>
<p>Again, the <code>DataBlock</code> is a blueprint for everything required to turn your raw data (images and labels) into something that can be fed through a neural network (DataLoaders with a numerical representation of both your images and labels). Below is the one presented in this chapter.</p>
<div id="cell-5" class="cell" data-outputid="b42b53e3-16a2-47a2-bad3-bb95a6738f05">
<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="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="cb1-2">path <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> untar_data(URLs.PETS)</span></code></pre></div>
<div class="cell-output cell-output-display">

</div>
</div>
<div id="cell-6" class="cell">
<div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb2-1">dblock <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> DataBlock(blocks<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>(ImageBlock, CategoryBlock), </span>
<span id="cb2-2">                   get_items<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>get_image_files, </span>
<span id="cb2-3">                   get_y<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>using_attr(RegexLabeller(<span class="vs" style="color: #20794D;
background-color: null;
font-style: inherit;">r'(.+)_\d+.jpg$'</span>), <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'name'</span>),</span>
<span id="cb2-4">                   splitter<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>RandomSplitter(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="cb2-5">                   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;">460</span>), </span>
<span id="cb2-6">                   batch_tfms<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>aug_transforms(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;">224</span>, min_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;">.75</span>))</span></code></pre></div>
</div>
<p><strong>Let’s break down our blueprint</strong>!</p>
<ol type="1">
<li>Define the data types for our inputs and targets via the <code>blocks</code> argument.</li>
</ol>
<p>This is defined as a tuple, where we tell our <code>DataBlock</code> that the imputs are images and our targets are a single category (or class or label).</p>
<ol start="2" type="1">
<li>Define how we’re going to get our raw data via <code>get_items</code>.</li>
</ol>
<p>We use <code>get_image_files</code> because we are getting image files from the filesystem. When we kick off the <code>DataBlock</code> to build our <code>DataLoaders</code>, we’ll pass in the path to our images which will in turn be passed to <code>get_image_files</code> to pull the raw data.</p>
<ol start="3" type="1">
<li>Define how, from the raw data, we’re going to create our labels (e.g., the classes for each image) via <code>get_y</code>.</li>
</ol>
<p>In this case, we don’t need to define a <code>get_x</code> because <code>get_items</code> gets the x’s already. However, since we are working with filenames from which we want to define our labels, we do need this fancy <code>get_y</code> function above. <code>using_attr</code> tells the <code>RegexLabeller</code> what attribute of our data to apply itself too, and since our data is filenames, we tell it to use the <code>.name</code> property of each filename object as the thing the <code>RegexLabeller</code> acts against. That will give us our target class.</p>
<ol start="4" type="1">
<li><p>Define how we’re going to create our <a href="https://www.fast.ai/2017/11/13/validation-sets/">validation dataset</a> via <code>splitter</code></p></li>
<li><p>Define things we want to do for each item via <code>item_tfms</code></p></li>
</ol>
<p><code>item_tfms</code> are transforms, or things we want to do, to each input individually! Above we only have one which says, “Resize each image to 460 max width/height” one by one <em>when we grab it</em>. For individual images to be collated into mini-batches, they have to be the same size … thus we do this here and not below.</p>
<ol start="6" type="1">
<li>Define things we want to do for each mini-batch of items via <code>batch_tfms</code></li>
</ol>
<p><code>batch_tfms</code> are transforms, or things we want to do, <em>to a mini-batch of inputs</em> at once <em>on the GPU</em>. <code>aug_transforms</code> includes a bunch that have proven to be effective in computer vision tasks. With the parameters we’re passing into it above (<code>size=224, min_scale=.75</code>), we’re saying, “Take the mini-batch of images here and randomly crop the 460x460 images to be 224x224 that captures at least 3/4 of the image”. See here for more info on <a href="https://docs.fast.ai/vision.augment.html#RandomResizedCrop"><code>RandomResizedCrop</code></a>.</p>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>If you can describe your <code>DataBlock</code> like I have above, you understand it!</p>
</div>
</div>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>Verify your <code>DataBlock</code> works as expected, or else troubleshoot it, by running <code>DataBlock.summary(data)</code></p>
</div>
</div>
<div id="cell-8" class="cell" data-outputid="3ad230eb-5514-4823-f9ee-60df6e3831ae">
<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">dblock.summary(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;">'images'</span>)</span></code></pre></div>
<div class="cell-output cell-output-stdout">
<pre><code>Setting-up type transforms pipelines
Collecting items from /root/.fastai/data/oxford-iiit-pet/images
Found 7390 items
2 datasets of sizes 5912,1478
Setting up Pipeline: PILBase.create
Setting up Pipeline: partial -&gt; Categorize -- {'vocab': None, 'sort': True, 'add_na': False}

Building one sample
  Pipeline: PILBase.create
    starting from
      /root/.fastai/data/oxford-iiit-pet/images/Bombay_111.jpg
    applying PILBase.create gives
      PILImage mode=RGB size=604x453
  Pipeline: partial -&gt; Categorize -- {'vocab': None, 'sort': True, 'add_na': False}
    starting from
      /root/.fastai/data/oxford-iiit-pet/images/Bombay_111.jpg
    applying partial gives
      Bombay
    applying Categorize -- {'vocab': None, 'sort': True, 'add_na': False} gives
      TensorCategory(3)

Final sample: (PILImage mode=RGB size=604x453, TensorCategory(3))


Collecting items from /root/.fastai/data/oxford-iiit-pet/images
Found 7390 items
2 datasets of sizes 5912,1478
Setting up Pipeline: PILBase.create
Setting up Pipeline: partial -&gt; Categorize -- {'vocab': None, 'sort': True, 'add_na': False}
Setting up after_item: Pipeline: Resize -- {'size': (460, 460), 'method': 'crop', 'pad_mode': 'reflection', 'resamples': (2, 0), 'p': 1.0} -&gt; ToTensor
Setting up before_batch: Pipeline: 
Setting up after_batch: Pipeline: IntToFloatTensor -- {'div': 255.0, 'div_mask': 1} -&gt; Flip -- {'size': None, 'mode': 'bilinear', 'pad_mode': 'reflection', 'mode_mask': 'nearest', 'align_corners': True, 'p': 0.5} -&gt; RandomResizedCropGPU -- {'size': (224, 224), 'min_scale': 0.75, 'ratio': (1, 1), 'mode': 'bilinear', 'valid_scale': 1.0, 'max_scale': 1.0, 'p': 1.0} -&gt; Brightness -- {'max_lighting': 0.2, 'p': 1.0, 'draw': None, 'batch': False}

Building one batch
Applying item_tfms to the first sample:
  Pipeline: Resize -- {'size': (460, 460), 'method': 'crop', 'pad_mode': 'reflection', 'resamples': (2, 0), 'p': 1.0} -&gt; ToTensor
    starting from
      (PILImage mode=RGB size=604x453, TensorCategory(3))
    applying Resize -- {'size': (460, 460), 'method': 'crop', 'pad_mode': 'reflection', 'resamples': (2, 0), 'p': 1.0} gives
      (PILImage mode=RGB size=460x460, TensorCategory(3))
    applying ToTensor gives
      (TensorImage of size 3x460x460, TensorCategory(3))

Adding the next 3 samples

No before_batch transform to apply

Collating items in a batch

Applying batch_tfms to the batch built
  Pipeline: IntToFloatTensor -- {'div': 255.0, 'div_mask': 1} -&gt; Flip -- {'size': None, 'mode': 'bilinear', 'pad_mode': 'reflection', 'mode_mask': 'nearest', 'align_corners': True, 'p': 0.5} -&gt; RandomResizedCropGPU -- {'size': (224, 224), 'min_scale': 0.75, 'ratio': (1, 1), 'mode': 'bilinear', 'valid_scale': 1.0, 'max_scale': 1.0, 'p': 1.0} -&gt; Brightness -- {'max_lighting': 0.2, 'p': 1.0, 'draw': None, 'batch': False}
    starting from
      (TensorImage of size 4x3x460x460, TensorCategory([ 3, 17, 10,  4], device='cuda:0'))
    applying IntToFloatTensor -- {'div': 255.0, 'div_mask': 1} gives
      (TensorImage of size 4x3x460x460, TensorCategory([ 3, 17, 10,  4], device='cuda:0'))
    applying Flip -- {'size': None, 'mode': 'bilinear', 'pad_mode': 'reflection', 'mode_mask': 'nearest', 'align_corners': True, 'p': 0.5} gives
      (TensorImage of size 4x3x460x460, TensorCategory([ 3, 17, 10,  4], device='cuda:0'))
    applying RandomResizedCropGPU -- {'size': (224, 224), 'min_scale': 0.75, 'ratio': (1, 1), 'mode': 'bilinear', 'valid_scale': 1.0, 'max_scale': 1.0, 'p': 1.0} gives
      (TensorImage of size 4x3x224x224, TensorCategory([ 3, 17, 10,  4], device='cuda:0'))
    applying Brightness -- {'max_lighting': 0.2, 'p': 1.0, 'draw': None, 'batch': False} gives
      (TensorImage of size 4x3x224x224, TensorCategory([ 3, 17, 10,  4], device='cuda:0'))</code></pre>
</div>
</div>
<p>Now we can create our <code>DataLoaders</code> and take a look at our x’s and y’s, our pet images and their label/class</p>
<div id="cell-10" class="cell" data-outputid="2f8a96a0-5adb-4df7-9f83-548418317abb">
<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">dls <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> dblock.dataloaders(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;">'images'</span>)</span>
<span id="cb5-2">dls.show_batch()</span></code></pre></div>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://ohmeow.com/posts/2021-06-03-ajtfb-chapter-5_files/figure-html/cell-6-output-1.png" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
<p>To get a feel for what our <code>batch_tfms</code> are doing, we can <code>show_batch</code> using a single image as we do below.</p>
<div id="cell-12" class="cell" data-outputid="041b281b-55bb-4e23-a569-bfdb4803956a">
<div class="sourceCode cell-code" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb6-1">dls.show_batch(unique<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 class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://ohmeow.com/posts/2021-06-03-ajtfb-chapter-5_files/figure-html/cell-7-output-1.png" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
<p>The combination of what we’re doing in the <code>item_tfms</code> and <code>batch_tfms</code> is known as <strong>presizing</strong>.</p>
<p>“Presizing is a particular way to do iamge augmentation taht is designed to minimize data destruction while maintaining good performance.” After resizing all the images to a larger dimension that we will train on, we perform all our core augmentations on the GPU. This results in both faster and less destructive transformations of the data.</p>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>See pp190-191 for how these augmentations are applied to the training and validation set!</p>
</div>
</div>
</section>
<section id="train-a-model" class="level2">
<h2 class="anchored" data-anchor-id="train-a-model">Train a model</h2>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>“Once you think your data looks right, we generally recommend the next step should be using it to train a simple model” See bottom of p193 for why.</p>
</div>
</div>
<section id="define-your-loss-function" class="level4">
<h4 class="anchored" data-anchor-id="define-your-loss-function">Define your loss function</h4>
<p>To train a model we need a good loss function that will allow us to optimize the parameters of our model. For multiclassification tasks where we want to predict a single class/label, to go to is <strong>cross-entropy loss</strong></p>
<p>To understand how this particular loss function operates and its interesting effects, see my prior article <a href="https://ohmeow.com/posts/2020/04/04/understanding-cross-entropy-loss.html">“Loss Functions: Cross Entropy Loss and You!”</a> It’s all about how it works, why use it over something like accuracy, and so forth. Pages 194-203 is the place to look in fastbook for more details on the ins and outs of this loss function.</p>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>Cross-entropy loss is the Highlander of loss functions … “there can only be one”</p>
</div>
</div>
<p>“Intuitively, the softmax function <em>really</em> wants to pick one class … so it’s ideal for training a classifier when we know each piecture has a definite label. (Note taht it may be less ideal during inference, as you might want your model to sometimes tell you it doesn’t recognize any of the classes taht is has seen during training, and not pick a class because it has a slightly bigger activation score. In this case, it might be better to train a model using multiple binary output columns, each using a sigmoid activation.)”</p>
</section>
<section id="train-a-model-1" class="level3">
<h3 class="anchored" data-anchor-id="train-a-model-1">Train a model</h3>
<div id="cell-17" class="cell">
<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">learn <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> cnn_learner(dls, resnet34, metrics<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>error_rate)</span></code></pre></div>
</div>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>Use the Learning Rate Finder to determine a good LR to use during the optimization step!</p>
</div>
</div>
<p>“One of the most importatn things we can do when training a model is to make sure that we have the right learning rate. If our learning rate is too low, it can take many, many epochs to train our model … also that we may have problems with overfitting, ceacuse every time we do a complete pass through the data, we give our model a chance to memorize it”</p>
<p>See p 205-206 for more information on how it works, and also <a href="https://arxiv.org/abs/1506.01186">Leslie Smith’s paper on it here</a>. A must read for fastai developers!!!</p>
<div id="cell-19" class="cell" data-outputid="aab8b884-4698-4cac-ad0b-04554e34a63a">
<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">lr_min, lr_steep <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> learn.lr_find()</span></code></pre></div>
<div class="cell-output cell-output-display">

</div>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://ohmeow.com/posts/2021-06-03-ajtfb-chapter-5_files/figure-html/cell-9-output-2.png" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
<div id="cell-20" class="cell" data-outputid="23034e1d-d8f6-4cc4-99db-92e9eb21ee38">
<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">lr_min, lr_steep</span></code></pre></div>
<div class="cell-output cell-output-display" data-execution_count="16">
<pre><code>(0.010000000149011612, 0.0063095735386013985)</code></pre>
</div>
</div>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>Pick either “one order of magnitude less that where the minimum loss was achieved” (<code>lr_min</code> above, which is actually the true minimum, roughly 1e-1 / 10, 0.01 or else 1e-2) -or- “the last point where the loss was clearly decreasing”</p>
</div>
</div>
<p>These two are likely close to one another, and if you’re not sure which to use, try them both!</p>
<div id="cell-22" class="cell" data-outputid="8d5a7c55-1ab0-47a4-b538-750c13241a0c">
<div class="sourceCode cell-code" id="cb11" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb11-1">learn.fine_tune(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, base_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;">1e-2</span>)</span></code></pre></div>
<div class="cell-output cell-output-display">
<table class="dataframe caption-top table table-sm table-striped small" data-quarto-postprocess="true" 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.988194</td>
<td>0.477657</td>
<td>0.131258</td>
<td>01:05</td>
</tr>
</tbody>
</table>
</div>
<div class="cell-output cell-output-display">
<table class="dataframe caption-top table table-sm table-striped small" data-quarto-postprocess="true" 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.990748</td>
<td>0.932280</td>
<td>0.228687</td>
<td>01:09</td>
</tr>
<tr class="even">
<td>1</td>
<td>0.537608</td>
<td>0.289773</td>
<td>0.089986</td>
<td>01:07</td>
</tr>
</tbody>
</table>
</div>
</div>
<p>Using <code>fine_tune</code> gives us a nice and quick baseline we can look back at going forward. Nevertheless, we can likely improve our model by taking more control over what parameters are trained (updated), when, and by how much using <code>fit_one_cycle</code>.</p>
<p>So let’s start again, by defining our <code>Learner</code> and finding a good LR for training ONLY the last layer’s parameters (the idea being that the pretrained model we’re finetuning, our backbone, is already pretty good at understanding images … while the last layer’s parameters are random because they are specific to our task at hand).</p>
<div id="cell-24" class="cell" data-outputid="ab844e71-19f8-4b32-e0d5-2d4efbb6b729">
<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">learn <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> cnn_learner(dls, resnet34, metrics<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>error_rate)</span>
<span id="cb12-2">lr_min, lr_steep <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> learn.lr_find()</span></code></pre></div>
<div class="cell-output cell-output-display">

</div>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://ohmeow.com/posts/2021-06-03-ajtfb-chapter-5_files/figure-html/cell-12-output-2.png" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
<div id="cell-25" class="cell" data-outputid="17ebf47e-1839-456a-d540-ed33206c6ab5">
<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">learn.fit_one_cycle(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, lr_max<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 class="cell-output cell-output-display">
<table class="dataframe caption-top table table-sm table-striped small" data-quarto-postprocess="true" 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>1.094374</td>
<td>0.674852</td>
<td>0.180650</td>
<td>01:05</td>
</tr>
<tr class="even">
<td>1</td>
<td>0.645389</td>
<td>0.303023</td>
<td>0.096752</td>
<td>01:03</td>
</tr>
</tbody>
</table>
</div>
</div>
<p>NOW … we’re going to “unfreeze” our model, meaning we’re going to make all the parameters trainable. And then we’re going to apply <strong>discriminative learning rates</strong>, or different base LRs to different parts of our models, with the assumption that earlier layers likely only need to change a little while later layers, especially our classification head, have to change more. This is covered thoroughly in another must read paper, <a href="https://arxiv.org/abs/1801.06146">Universal Language Model Fine-tuning for Text Classification</a></p>
<p>Look at the bottom of the cell below’s output to see the number of traininable parameters for our currently frozen model.</p>
<div id="cell-27" class="cell" data-outputid="8e8b5899-103a-4ea9-a6ce-a2bbcc58f6be">
<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">learn.summary()</span></code></pre></div>
<div class="cell-output cell-output-display">

</div>
<div class="cell-output cell-output-display" data-execution_count="21">
<pre><code>Sequential (Input shape: 64)
============================================================================
Layer (type)         Output Shape         Param #    Trainable 
============================================================================
                     64 x 64 x 112 x 112 
Conv2d                                    9408       False     
BatchNorm2d                               128        True      
ReLU                                                           
MaxPool2d                                                      
Conv2d                                    36864      False     
BatchNorm2d                               128        True      
ReLU                                                           
Conv2d                                    36864      False     
BatchNorm2d                               128        True      
Conv2d                                    36864      False     
BatchNorm2d                               128        True      
ReLU                                                           
Conv2d                                    36864      False     
BatchNorm2d                               128        True      
Conv2d                                    36864      False     
BatchNorm2d                               128        True      
ReLU                                                           
Conv2d                                    36864      False     
BatchNorm2d                               128        True      
____________________________________________________________________________
                     64 x 128 x 28 x 28  
Conv2d                                    73728      False     
BatchNorm2d                               256        True      
ReLU                                                           
Conv2d                                    147456     False     
BatchNorm2d                               256        True      
Conv2d                                    8192       False     
BatchNorm2d                               256        True      
Conv2d                                    147456     False     
BatchNorm2d                               256        True      
ReLU                                                           
Conv2d                                    147456     False     
BatchNorm2d                               256        True      
Conv2d                                    147456     False     
BatchNorm2d                               256        True      
ReLU                                                           
Conv2d                                    147456     False     
BatchNorm2d                               256        True      
Conv2d                                    147456     False     
BatchNorm2d                               256        True      
ReLU                                                           
Conv2d                                    147456     False     
BatchNorm2d                               256        True      
____________________________________________________________________________
                     64 x 256 x 14 x 14  
Conv2d                                    294912     False     
BatchNorm2d                               512        True      
ReLU                                                           
Conv2d                                    589824     False     
BatchNorm2d                               512        True      
Conv2d                                    32768      False     
BatchNorm2d                               512        True      
Conv2d                                    589824     False     
BatchNorm2d                               512        True      
ReLU                                                           
Conv2d                                    589824     False     
BatchNorm2d                               512        True      
Conv2d                                    589824     False     
BatchNorm2d                               512        True      
ReLU                                                           
Conv2d                                    589824     False     
BatchNorm2d                               512        True      
Conv2d                                    589824     False     
BatchNorm2d                               512        True      
ReLU                                                           
Conv2d                                    589824     False     
BatchNorm2d                               512        True      
Conv2d                                    589824     False     
BatchNorm2d                               512        True      
ReLU                                                           
Conv2d                                    589824     False     
BatchNorm2d                               512        True      
Conv2d                                    589824     False     
BatchNorm2d                               512        True      
ReLU                                                           
Conv2d                                    589824     False     
BatchNorm2d                               512        True      
____________________________________________________________________________
                     64 x 512 x 7 x 7    
Conv2d                                    1179648    False     
BatchNorm2d                               1024       True      
ReLU                                                           
Conv2d                                    2359296    False     
BatchNorm2d                               1024       True      
Conv2d                                    131072     False     
BatchNorm2d                               1024       True      
Conv2d                                    2359296    False     
BatchNorm2d                               1024       True      
ReLU                                                           
Conv2d                                    2359296    False     
BatchNorm2d                               1024       True      
Conv2d                                    2359296    False     
BatchNorm2d                               1024       True      
ReLU                                                           
Conv2d                                    2359296    False     
BatchNorm2d                               1024       True      
____________________________________________________________________________
                     []                  
AdaptiveAvgPool2d                                              
AdaptiveMaxPool2d                                              
Flatten                                                        
BatchNorm1d                               2048       True      
Dropout                                                        
____________________________________________________________________________
                     64 x 512            
Linear                                    524288     True      
ReLU                                                           
BatchNorm1d                               1024       True      
Dropout                                                        
____________________________________________________________________________
                     64 x 37             
Linear                                    18944      True      
____________________________________________________________________________

Total params: 21,830,976
Total trainable params: 563,328
Total non-trainable params: 21,267,648

Optimizer used: &lt;function Adam at 0x7fe0e7fb57a0&gt;
Loss function: FlattenedLoss of CrossEntropyLoss()

Model frozen up to parameter group #2

Callbacks:
  - TrainEvalCallback
  - Recorder
  - ProgressCallback</code></pre>
</div>
</div>
<p>Let’s unfreeze and look at the same …</p>
<div id="cell-29" class="cell" data-outputid="7982fa17-545a-4549-866e-52e36ac1aa81">
<div class="sourceCode cell-code" id="cb16" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb16-1">learn.unfreeze()</span>
<span id="cb16-2">learn.summary()</span></code></pre></div>
<div class="cell-output cell-output-display">

</div>
<div class="cell-output cell-output-display" data-execution_count="22">
<pre><code>Sequential (Input shape: 64)
============================================================================
Layer (type)         Output Shape         Param #    Trainable 
============================================================================
                     64 x 64 x 112 x 112 
Conv2d                                    9408       True      
BatchNorm2d                               128        True      
ReLU                                                           
MaxPool2d                                                      
Conv2d                                    36864      True      
BatchNorm2d                               128        True      
ReLU                                                           
Conv2d                                    36864      True      
BatchNorm2d                               128        True      
Conv2d                                    36864      True      
BatchNorm2d                               128        True      
ReLU                                                           
Conv2d                                    36864      True      
BatchNorm2d                               128        True      
Conv2d                                    36864      True      
BatchNorm2d                               128        True      
ReLU                                                           
Conv2d                                    36864      True      
BatchNorm2d                               128        True      
____________________________________________________________________________
                     64 x 128 x 28 x 28  
Conv2d                                    73728      True      
BatchNorm2d                               256        True      
ReLU                                                           
Conv2d                                    147456     True      
BatchNorm2d                               256        True      
Conv2d                                    8192       True      
BatchNorm2d                               256        True      
Conv2d                                    147456     True      
BatchNorm2d                               256        True      
ReLU                                                           
Conv2d                                    147456     True      
BatchNorm2d                               256        True      
Conv2d                                    147456     True      
BatchNorm2d                               256        True      
ReLU                                                           
Conv2d                                    147456     True      
BatchNorm2d                               256        True      
Conv2d                                    147456     True      
BatchNorm2d                               256        True      
ReLU                                                           
Conv2d                                    147456     True      
BatchNorm2d                               256        True      
____________________________________________________________________________
                     64 x 256 x 14 x 14  
Conv2d                                    294912     True      
BatchNorm2d                               512        True      
ReLU                                                           
Conv2d                                    589824     True      
BatchNorm2d                               512        True      
Conv2d                                    32768      True      
BatchNorm2d                               512        True      
Conv2d                                    589824     True      
BatchNorm2d                               512        True      
ReLU                                                           
Conv2d                                    589824     True      
BatchNorm2d                               512        True      
Conv2d                                    589824     True      
BatchNorm2d                               512        True      
ReLU                                                           
Conv2d                                    589824     True      
BatchNorm2d                               512        True      
Conv2d                                    589824     True      
BatchNorm2d                               512        True      
ReLU                                                           
Conv2d                                    589824     True      
BatchNorm2d                               512        True      
Conv2d                                    589824     True      
BatchNorm2d                               512        True      
ReLU                                                           
Conv2d                                    589824     True      
BatchNorm2d                               512        True      
Conv2d                                    589824     True      
BatchNorm2d                               512        True      
ReLU                                                           
Conv2d                                    589824     True      
BatchNorm2d                               512        True      
____________________________________________________________________________
                     64 x 512 x 7 x 7    
Conv2d                                    1179648    True      
BatchNorm2d                               1024       True      
ReLU                                                           
Conv2d                                    2359296    True      
BatchNorm2d                               1024       True      
Conv2d                                    131072     True      
BatchNorm2d                               1024       True      
Conv2d                                    2359296    True      
BatchNorm2d                               1024       True      
ReLU                                                           
Conv2d                                    2359296    True      
BatchNorm2d                               1024       True      
Conv2d                                    2359296    True      
BatchNorm2d                               1024       True      
ReLU                                                           
Conv2d                                    2359296    True      
BatchNorm2d                               1024       True      
____________________________________________________________________________
                     []                  
AdaptiveAvgPool2d                                              
AdaptiveMaxPool2d                                              
Flatten                                                        
BatchNorm1d                               2048       True      
Dropout                                                        
____________________________________________________________________________
                     64 x 512            
Linear                                    524288     True      
ReLU                                                           
BatchNorm1d                               1024       True      
Dropout                                                        
____________________________________________________________________________
                     64 x 37             
Linear                                    18944      True      
____________________________________________________________________________

Total params: 21,830,976
Total trainable params: 21,830,976
Total non-trainable params: 0

Optimizer used: &lt;function Adam at 0x7fe0e7fb57a0&gt;
Loss function: FlattenedLoss of CrossEntropyLoss()

Model unfrozen

Callbacks:
  - TrainEvalCallback
  - Recorder
  - ProgressCallback</code></pre>
</div>
</div>
<p>… and as you can see, we’re training everything!</p>
<p>Because what parameters were training has changed, we also need to run the LR finder again to get some guidance on how to set our LRs.</p>
<div id="cell-31" class="cell" data-outputid="81b4cc3b-f970-4fcd-da16-68529d2056b8">
<div class="sourceCode cell-code" id="cb18" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb18-1">lr_min, lr_steep <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> learn.lr_find()</span></code></pre></div>
<div class="cell-output cell-output-display">

</div>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://ohmeow.com/posts/2021-06-03-ajtfb-chapter-5_files/figure-html/cell-16-output-2.png" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
<p>So lets see how many <strong>parameter/layer groups</strong> we have</p>
<div id="cell-33" class="cell" data-outputid="4eb06849-c367-4b97-9551-5920e1bd98b5">
<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"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(learn.opt.param_groups)</span></code></pre></div>
<div class="cell-output cell-output-display" data-execution_count="24">
<pre><code>3</code></pre>
</div>
</div>
<p>What we can now do is say, train the first layer group with an LR of 1e-6 … the last with an LR of 1e-4, and “the layers in between will have learning rates that are multiplicatively equidistnat throughout that range.” Since we only have 3, the middle group will be trained with a starting LR of 1e-5</p>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>We usually choose the first number a bit back from where things start to go bad … and the last number 1-2 magnitudes lower than the base LR of the frozen model</p>
</div>
</div>
<div id="cell-35" class="cell" data-outputid="ee76a303-850b-4bf2-a93c-3a6dced77e49">
<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">learn.fit_one_cycle(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">12</span>, lr_max<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>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1e-6</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1e-4</span>))</span></code></pre></div>
<div class="cell-output cell-output-display">
<table class="dataframe caption-top table table-sm table-striped small" data-quarto-postprocess="true" 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.394857</td>
<td>0.291812</td>
<td>0.091340</td>
<td>01:06</td>
</tr>
<tr class="even">
<td>1</td>
<td>0.359788</td>
<td>0.266810</td>
<td>0.084574</td>
<td>01:05</td>
</tr>
<tr class="odd">
<td>2</td>
<td>0.315511</td>
<td>0.248843</td>
<td>0.078484</td>
<td>01:05</td>
</tr>
<tr class="even">
<td>3</td>
<td>0.308508</td>
<td>0.245649</td>
<td>0.081191</td>
<td>01:06</td>
</tr>
<tr class="odd">
<td>4</td>
<td>0.272639</td>
<td>0.231762</td>
<td>0.077131</td>
<td>01:06</td>
</tr>
<tr class="even">
<td>5</td>
<td>0.231295</td>
<td>0.222235</td>
<td>0.075778</td>
<td>01:06</td>
</tr>
<tr class="odd">
<td>6</td>
<td>0.216695</td>
<td>0.223222</td>
<td>0.077808</td>
<td>01:06</td>
</tr>
<tr class="even">
<td>7</td>
<td>0.207144</td>
<td>0.226977</td>
<td>0.075778</td>
<td>01:07</td>
</tr>
<tr class="odd">
<td>8</td>
<td>0.191794</td>
<td>0.223768</td>
<td>0.075778</td>
<td>01:07</td>
</tr>
<tr class="even">
<td>9</td>
<td>0.193688</td>
<td>0.222243</td>
<td>0.076455</td>
<td>01:07</td>
</tr>
<tr class="odd">
<td>10</td>
<td>0.185064</td>
<td>0.219272</td>
<td>0.076455</td>
<td>01:07</td>
</tr>
<tr class="even">
<td>11</td>
<td>0.177980</td>
<td>0.221938</td>
<td>0.073072</td>
<td>01:07</td>
</tr>
</tbody>
</table>
</div>
</div>
<div id="cell-36" class="cell" data-outputid="1b3ab3ce-6f8c-4ad2-d331-33e8a1eea872">
<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">learn.recorder.plot_loss()</span></code></pre></div>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://ohmeow.com/posts/2021-06-03-ajtfb-chapter-5_files/figure-html/cell-19-output-1.png" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>Overfitting does not mean your model isn’t improving!</p>
</div>
</div>
<p>“You will often see that the accuracy continues improving, even as the validation loss gets worse. <strong><em>In the end, what matters is your accuracy [or your chosen metric], not the loss.</em></strong> The loss is just the function we’ve given the computer to help us to optimize”</p>
<p><strong>How to choose the number of epochs?</strong></p>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>“Your first approach to training should be to simply pick a number of epochs that will train in the amount of time that you are happy to wait for.”</p>
</div>
</div>
<p>If the model is still getting better, then you haven’t trained your model long enough.</p>
<p>If your metric(s) are getting worse, “if you find that you have overfit, <strong><em>what you should do is retrain your model from scratch, and this time select a total number of epochs based on where your previous best results were found.</em></strong>”</p>
<p><strong>When to choose a deeper architecture?</strong></p>
<p>“A larger (more layers and parameters; sometimes described as the <em>capacity</em> of a model) version of ResNet will always be able to give us a better training loss, but it can suffer more from overfitting, because it has more parameters to overfit with. In general, a bigger model has the ability to better capture the real underlying relationships in your data, as well as to capture and memorize the specific details of your individual images.”</p>
<p>So consider these if … 1. You aren’t getting the results you need. 2. Have time to experiment and a big enough GPU to experiment with</p>
<p>You may need to reduce the size of your batches with these bigger models, and you can also us <strong>mixed-precision training</strong>, in order to get things to run on your GPU. The later results in faster training and gives you the ability to have bigger batch sizes than you would be able to support otherwise. All you need to do is add <code>to_fp16()</code> to your `Learner.</p>
<div id="cell-40" class="cell" data-outputid="ce0bccbe-8f5b-4b90-87c5-b95b1b0b8a00">
<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">learn <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> cnn_learner(dls, resnet50, metrics<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>error_rate).to_fp16()</span>
<span id="cb23-2">learn.fine_tune(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span>, freeze_epochs<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 class="cell-output cell-output-stderr">
<pre><code>Downloading: "https://download.pytorch.org/models/resnet50-19c8e357.pth" to /root/.cache/torch/hub/checkpoints/resnet50-19c8e357.pth</code></pre>
</div>
<div class="cell-output cell-output-display">
<script type="application/vnd.jupyter.widget-view+json">
{"model_id":"77aee302acf9450c8bdbfab95fdb1799","version_major":2,"version_minor":0,"quarto_mimetype":"application/vnd.jupyter.widget-view+json"}
</script>
</div>
<div class="cell-output cell-output-stdout">
<pre><code></code></pre>
</div>
<div class="cell-output cell-output-display">
<table class="dataframe caption-top table table-sm table-striped small" data-quarto-postprocess="true" 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.977287</td>
<td>0.299639</td>
<td>0.100812</td>
<td>01:06</td>
</tr>
</tbody>
</table>
</div>
<div class="cell-output cell-output-display">
<table class="dataframe caption-top table table-sm table-striped small" data-quarto-postprocess="true" 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.371637</td>
<td>0.253767</td>
<td>0.080514</td>
<td>01:07</td>
</tr>
<tr class="even">
<td>1</td>
<td>0.375325</td>
<td>0.300937</td>
<td>0.079161</td>
<td>01:07</td>
</tr>
<tr class="odd">
<td>2</td>
<td>0.281241</td>
<td>0.309774</td>
<td>0.089310</td>
<td>01:07</td>
</tr>
<tr class="even">
<td>3</td>
<td>0.149089</td>
<td>0.216163</td>
<td>0.059540</td>
<td>01:07</td>
</tr>
<tr class="odd">
<td>4</td>
<td>0.093488</td>
<td>0.176675</td>
<td>0.054127</td>
<td>01:07</td>
</tr>
<tr class="even">
<td>5</td>
<td>0.063744</td>
<td>0.169187</td>
<td>0.050744</td>
<td>01:07</td>
</tr>
</tbody>
</table>
</div>
</div>
</section>
</section>
<section id="summary" class="level2">
<h2 class="anchored" data-anchor-id="summary">Summary</h2>
<p>Well, at this point, you know how to train a multiclassification computer vision task. So, go train one for yourself using what you’ve learned!</p>
<p>Make sure you understand and why we use cross-entropy loss for multiclassification problems. I can’t tell you how many times I’ve responded to questions about why someone’s model wasn’t training only to find out the reason was because they had the wrong loss function. Know it, love it, use it :)</p>
<p>Also, so much of what fastai incorporates from the LR finder and the <code>fit_one_cycle</code>, comes from Leslie Smith’s research. Checkout the “Resources” section below for some of his more influential papers, all of which I’ve read and encourage the rest of you to read if you want some inside scoop about why fastai works the way it does. I guarantee, reading and studying those papers will make you a better deep learning practioner and a better fastai developer in particular! You may think you’re not ready to start reading academic papers at chapter 5, but believe me, I’ve been there, and you are :)</p>
</section>
<section id="resources" class="level2">
<h2 class="anchored" data-anchor-id="resources">Resources</h2>
<ol type="1">
<li><p>https://book.fast.ai - The book’s website; it’s updated regularly with new content and recommendations from everything to GPUs to use, how to run things locally and on the cloud, etc…</p></li>
<li><p><a href="https://arxiv.org/abs/1506.01186">Cyclical Learning Rates for Training Neural Networks</a></p></li>
<li><p><a href="https://arxiv.org/abs/1708.07120">Super-Convergence: Very Fast Training of Neural Networks Using Large Learning Rates</a></p></li>
<li><p><a href="https://arxiv.org/abs/1803.09820">A disciplined approach to neural network hyper-parameters: Part 1 – learning rate, batch size, momentum, and weight decay</a></p></li>
<li><p><a href="https://arxiv.org/abs/1801.06146">Universal Language Model Fine-tuning for Text Classification</a></p></li>
<li><p><a href="https://arxiv.org/abs/2002.04688">fastai: A Layered API for Deep Learning</a></p></li>
</ol>


</section>

 ]]></description>
  <category>fastai</category>
  <category>fastbook</category>
  <category>multiclass classification</category>
  <category>computer vision</category>
  <guid>https://ohmeow.com/posts/2021-06-03-ajtfb-chapter-5.html</guid>
  <pubDate>Thu, 03 Jun 2021 07:00:00 GMT</pubDate>
  <media:content url="https://ohmeow.com/posts/images/fastbook.jpg" medium="image" type="image/jpeg"/>
</item>
<item>
  <title>Contributing to fastai: Setup your local development environment &amp; submit a PR</title>
  <dc:creator>Wayde Gilliam</dc:creator>
  <link>https://ohmeow.com/posts/2021-06-02-how-to-submit-a-pr-to-fastai.html</link>
  <description><![CDATA[ 




<section id="steps" class="level2">
<h2 class="anchored" data-anchor-id="steps">Steps</h2>
<section id="configure-your-local-development-environment" class="level3">
<h3 class="anchored" data-anchor-id="configure-your-local-development-environment">Configure your local development environment</h3>
<ol type="1">
<li>Install the github CLI, <code>gh</code>. Instructions for all the OS flavor are <a href="https://github.com/cli/cli">here</a>!</li>
</ol>
<p>The CLI makes it trivial to work on open source projects. In particular, it really shines when making a PR as you’ll see below. Here’s the link to the cli’s<a href="https://cli.github.com/manual/">excellent documentation</a> which you’ll likely be referring to again and again (so keep it handy).</p>
<ol start="2" type="1">
<li>Clone the fastai repo locally</li>
</ol>
<pre><code>gh repo clone https://github.com/fastai/fastai.git
cd ./fastai</code></pre>
<ol start="3" type="1">
<li>Build your conda environment (I’m using <a href="https://mamba.readthedocs.io/en/latest/">mamba</a> based on Jeremy Howard’s recommendation)</li>
</ol>
<p>Mamba is a makes issuing conda commands faster! Basically just replace <code>conda</code> with <code>mamba</code> whenever you are working with packages in your environment.</p>
<pre><code>mamba env create -f environment.yml</code></pre>
<ol start="4" type="1">
<li>Activate the environment (you want to make sure you’re in the <code>fastai</code> environment going forward)</li>
</ol>
<pre><code>conda activate fastai</code></pre>
<ol start="5" type="1">
<li>Install Jupyter and extensions <em>into your fastai environment</em> (I do this all the time because it leads to less problems when trying to use a base install of jupyter notebook for everything)</li>
</ol>
<pre><code>mamba install -c conda-forge notebook
mamba install -c conda-forge jupyter_contrib_nbextensions</code></pre>
<ol start="6" type="1">
<li>Install nbdev and run the <code>nbdev_install_git_hooks</code> script per the fastai docs</li>
</ol>
<pre><code>mamba install -c fastai nbdev
nbdev_install_git_hooks</code></pre>
<ol start="7" type="1">
<li>Create a symlink from <code>/nbs/fastai</code> to <code>fastai</code> to make sure the notebooks can find the fastai library which is up one level from the notebooks</li>
</ol>
<pre><code>cd ./nbs
ln -s ../fastai fastai
cd ..</code></pre>
<p><strong>At this point your local development environment is good to go!</strong> Run <code>jupyter notebook</code>, open your browser, and head over to the <code>/nbs</code> folder to begin.</p>
</section>
<section id="submit-a-pr" class="level3">
<h3 class="anchored" data-anchor-id="submit-a-pr">Submit a PR</h3>
<p>With the github CLI, its amazingly easy! Once you’ve made your changes and added your unit tests all you have to do is:</p>
<ol type="1">
<li>Make sure you’re local repo is up-to-date <strong><em>BEFORE</em></strong> you start working. In fact, this is a good command to run periodically so you don’t have to deal with any conflicts once you make your PR.</li>
</ol>
<pre><code>git pull</code></pre>
<ol start="2" type="1">
<li>Commit your changes to git</li>
</ol>
<pre><code>git commit -am 'My amazing addition to fastai here'</code></pre>
<ol start="3" type="1">
<li>Submit a PR using <code>gh</code></li>
</ol>
<pre><code>gh pr create --title "My amaizing change" --body "Here's what you need to know about it!"</code></pre>
<p>There are actually a few ways to issue the pr, but the above is the easiest. Check out the <a href="https://cli.github.com/manual/gh_pr_create">gh pr create docs</a> for more options.</p>
<p>Once you do this, you’ll be asked some questions about where to push the branch and offer an option to fork the base repository under your own account. Easy peasy friends.</p>
<p><strong>Congrats! You’re a contributor now.</strong></p>
</section>
</section>
<section id="summary" class="level2">
<h2 class="anchored" data-anchor-id="summary">Summary</h2>
<p>But that’s not all! There are all kinds of cool things you can do using the github CLI including monitoring the status of your PRs and also fixing them (which you’ll likely have to do when the base repo owners ask you to make changes of one sort or another). It’s all in the docs and it’s all fairly straightforward!</p>


</section>

 ]]></description>
  <category>fastai</category>
  <category>github</category>
  <category>open source</category>
  <category>pull requests</category>
  <guid>https://ohmeow.com/posts/2021-06-02-how-to-submit-a-pr-to-fastai.html</guid>
  <pubDate>Wed, 02 Jun 2021 07:00:00 GMT</pubDate>
  <media:content url="https://ohmeow.com/posts/images/thumbs_up_kid.jpeg" medium="image" type="image/jpeg"/>
</item>
<item>
  <title>Multilingual Sequence Classifaction with the MBart Family</title>
  <dc:creator>Wayde Gilliam</dc:creator>
  <link>https://ohmeow.com/posts/2021-05-25-mbart-sequence-classification-with-blurr.html</link>
  <description><![CDATA[ 




<div id="cell-1" class="cell" data-execution_count="1">
<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="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span>pip install ohmeow<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>blurr <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>q</span>
<span id="cb1-2"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span>pip install datasets <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>q</span></code></pre></div>
</div>
<div id="cell-2" class="cell" data-execution_count="2">
<div class="sourceCode cell-code" id="cb2" 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> fastai.text.<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="cb2-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> datasets <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> load_dataset</span>
<span id="cb2-3"><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> AutoModelForSequenceClassification</span>
<span id="cb2-4"></span>
<span id="cb2-5"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> blurr.utils <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> BLURR</span>
<span id="cb2-6"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> blurr.data.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="cb2-7"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> blurr.modeling.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></code></pre></div>
</div>
<div id="cell-3" class="cell" data-outputid="0734add7-6d0f-4ce6-c9db-3e8ebbd07e24" data-execution_count="3">
<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;">from</span> blurr <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> __version__ <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> blurr_version</span>
<span id="cb3-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> fastai <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> __version__ <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> fa_version</span>
<span id="cb3-3"><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> __version__ <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> pt_version</span>
<span id="cb3-4"><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> __version__ <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> hft_version</span>
<span id="cb3-5"></span>
<span id="cb3-6"><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'Using blurr </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>blurr_version<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="cb3-7"><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'Using pytorch </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>pt_version<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="cb3-8"><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'Using fastai </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>fa_version<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="cb3-9"><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'Using transformers </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>hft_version<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 class="cell-output cell-output-stdout">
<pre><code>Using blurr 0.0.25
Using pytorch 1.8.1+cu101
Using fastai 2.3.1
Using transformers 4.6.1</code></pre>
</div>
</div>
<section id="data" class="level2">
<h2 class="anchored" data-anchor-id="data">Data</h2>
<div id="cell-5" class="cell" data-outputid="e431cb0b-1b14-4fac-f9fd-6ec08d78f0e3" data-execution_count="4">
<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">trn_ds, val_ds, tst_ds <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> load_dataset(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"amazon_reviews_multi"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"de"</span>, split<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'train'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'validation'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'test'</span>])</span></code></pre></div>
<div class="cell-output cell-output-stderr">
<pre><code>Reusing dataset amazon_reviews_multi (/root/.cache/huggingface/datasets/amazon_reviews_multi/de/1.0.0/724e94f4b0c6c405ce7e476a6c5ef4f87db30799ad49f765094cf9770e0f7609)</code></pre>
</div>
</div>
<div id="cell-6" class="cell" data-execution_count="5">
<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">trn_df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> pd.DataFrame(trn_ds)</span>
<span id="cb7-2">val_df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> pd.DataFrame(val_ds)</span>
<span id="cb7-3">tst_df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> pd.DataFrame(tst_ds)</span></code></pre></div>
</div>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>Use a subset of the data when building your model to speed up developement time!</p>
</div>
</div>
<p>After you got everything, throw the full dataset at it and go get some coffee :)</p>
<div id="cell-8" class="cell" data-execution_count="6">
<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"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># testing with a subset ... (comment out to train on full dataset!!!)</span></span>
<span id="cb8-2"></span>
<span id="cb8-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># this won't work because the rows are ordered by our targets!</span></span>
<span id="cb8-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># trn_ds, val_ds = load_dataset("amazon_reviews_multi", "de", split=['train[:10%]', 'validation[:10%]'])</span></span>
<span id="cb8-5"></span>
<span id="cb8-6">trn_df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> trn_df.sample(frac<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.05</span>)</span>
<span id="cb8-7">val_df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> val_df.sample(frac<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.05</span>)</span></code></pre></div>
</div>
<div id="cell-9" class="cell" data-outputid="2d7071fe-fbdd-49b6-f170-0f7808fc4e06" data-execution_count="7">
<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">trn_df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'is_valid'</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="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> val_df[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'is_valid'</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>
<span id="cb9-2">df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> pd.concat([trn_df, val_df])</span>
<span id="cb9-3"></span>
<span id="cb9-4"><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;">len</span>(trn_df), <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(val_df), <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(df))</span></code></pre></div>
<div class="cell-output cell-output-stdout">
<pre><code>10000 250 10250</code></pre>
</div>
</div>
<div id="cell-10" class="cell" data-outputid="0f7a6479-2092-48a9-84df-103fa549c142" data-execution_count="8">
<div class="sourceCode cell-code" id="cb11" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb11-1">trn_df.head()</span></code></pre></div>
<div class="cell-output cell-output-display" data-execution_count="8">
<div>


<table class="dataframe caption-top table table-sm table-striped small" data-quarto-postprocess="true" data-border="1">
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th">language</th>
<th data-quarto-table-cell-role="th">product_category</th>
<th data-quarto-table-cell-role="th">product_id</th>
<th data-quarto-table-cell-role="th">review_body</th>
<th data-quarto-table-cell-role="th">review_id</th>
<th data-quarto-table-cell-role="th">review_title</th>
<th data-quarto-table-cell-role="th">reviewer_id</th>
<th data-quarto-table-cell-role="th">stars</th>
<th data-quarto-table-cell-role="th">is_valid</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td data-quarto-table-cell-role="th">115812</td>
<td>de</td>
<td>apparel</td>
<td>product_de_0727194</td>
<td>für so einen Preis muss ich dazusagen, es hält was es verspricht, natürlich ist hier keine hohe Qualität zu erwarten, aber für solchen Preis recht gut. ist. Die Nähte gehen mit Zeit auf</td>
<td>de_0580512</td>
<td>Preis Leistung Ok</td>
<td>reviewer_de_0542714</td>
<td>3</td>
<td>False</td>
</tr>
<tr class="even">
<td data-quarto-table-cell-role="th">58074</td>
<td>de</td>
<td>toy</td>
<td>product_de_0014211</td>
<td>Die Qualität ist nicht gut. Nur nach kurzem nutzen sind die plastikverkleidungen abgefallen. Der Ball lässt sich schlecht für Kinder entfernen. Die Scheiben sehen nach kurzer Nutzung aus als wären sie Jahre im Gebrauch. Würde ich nicht wieder kaufen.</td>
<td>de_0100470</td>
<td>Schlechte Qualität</td>
<td>reviewer_de_0719961</td>
<td>2</td>
<td>False</td>
</tr>
<tr class="odd">
<td data-quarto-table-cell-role="th">122195</td>
<td>de</td>
<td>toy</td>
<td>product_de_0304268</td>
<td>Erfüllt seinen Zweck und sie gut aus.</td>
<td>de_0811174</td>
<td>Toller Lederbeutel</td>
<td>reviewer_de_0999635</td>
<td>4</td>
<td>False</td>
</tr>
<tr class="even">
<td data-quarto-table-cell-role="th">75151</td>
<td>de</td>
<td>other</td>
<td>product_de_0720910</td>
<td>Ich mach es kurz; Kauft euch das Album nicht und behaltet Rise Against so on Erinnerung wie sie früher waren. Alles nach Appeal to reason ist generisch, einfallslos und irgendwie langweilig geworden. The Violence ist der einzige Track der mir vielleicht im Gedächtnis bleiben könnte.</td>
<td>de_0713777</td>
<td>Langweilg</td>
<td>reviewer_de_0130191</td>
<td>2</td>
<td>False</td>
</tr>
<tr class="odd">
<td data-quarto-table-cell-role="th">94760</td>
<td>de</td>
<td>digital_video_download</td>
<td>product_de_0847576</td>
<td>Fand die Twists im Film ziemlich vorhersehbar. Dennoch fand ich den Film ansich ganz cool, da ich 1. Den Schauspieler sehr mag und 2. Diese Thematik immer wieder spannend finde. Für abends zuhause mit dem Partner auf der Couch ein solider Film, den man durchaus mal schauen kann, aber auch kein Super hollywood Kino erwartet</td>
<td>de_0471539</td>
<td>Solider Film für zuhause</td>
<td>reviewer_de_0223020</td>
<td>3</td>
<td>False</td>
</tr>
</tbody>
</table>

</div>
</div>
</div>
<div id="cell-11" class="cell" data-outputid="f437224b-107e-482f-fb72-709bbe98134d" data-execution_count="9">
<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">unique_tgt_vals <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> trn_df.stars.value_counts()</span>
<span id="cb12-2"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(unique_tgt_vals)</span>
<span id="cb12-3"></span>
<span id="cb12-4">labels <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;">sorted</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>(df.stars.unique()))</span>
<span id="cb12-5"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(labels)</span></code></pre></div>
<div class="cell-output cell-output-stdout">
<pre><code>4    2054
3    2054
5    2025
2    1946
1    1921
Name: stars, dtype: int64
[1, 2, 3, 4, 5]</code></pre>
</div>
</div>
</section>
<section id="huggingface-objects" class="level2">
<h2 class="anchored" data-anchor-id="huggingface-objects">huggingface objects</h2>
<div id="cell-13" class="cell" data-outputid="c304c56e-1293-4bed-e0ef-9abcaade4fe1" data-execution_count="10">
<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">model_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;">"facebook/mbart-large-50"</span></span>
<span id="cb14-2">model_cls <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> AutoModelForSequenceClassification</span>
<span id="cb14-3">hf_tok_kwargs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'src_lang'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'de_DE'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'tgt_lang'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'de_DE'</span>}</span>
<span id="cb14-4"></span>
<span id="cb14-5">hf_arch, hf_config, hf_tokenizer, hf_model <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> BLURR.get_hf_objects(model_name,  </span>
<span id="cb14-6">                                                                  model_cls<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>model_cls,  </span>
<span id="cb14-7">                                                                  tokenizer_kwargs<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>hf_tok_kwargs, </span>
<span id="cb14-8">                                                                  config_kwargs<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>{<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'num_labels'</span>: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(labels)})</span>
<span id="cb14-9"></span>
<span id="cb14-10"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'arch: '</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">type</span>(hf_arch))</span>
<span id="cb14-11"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'config: '</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">type</span>(hf_config))</span>
<span id="cb14-12"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'tokenizer: '</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">type</span>(hf_tokenizer))</span>
<span id="cb14-13"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'model: '</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">type</span>(hf_model))</span></code></pre></div>
<div class="cell-output cell-output-stdout">
<pre><code>arch:  &lt;class 'str'&gt;
config:  &lt;class 'transformers.models.mbart.configuration_mbart.MBartConfig'&gt;
tokenizer:  &lt;class 'transformers.models.mbart.tokenization_mbart50_fast.MBart50TokenizerFast'&gt;
model:  &lt;class 'transformers.models.mbart.modeling_mbart.MBartForSequenceClassification'&gt;</code></pre>
</div>
</div>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>Always good to look into the config as you’ll often find good defaults to use in your training and inference!</p>
</div>
</div>
<div id="cell-15" class="cell" data-outputid="2b7f6d5d-3b2a-4481-eb0a-8fc4e00e9f9a" data-execution_count="11">
<div class="sourceCode cell-code" id="cb16" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb16-1">hf_config</span></code></pre></div>
<div class="cell-output cell-output-display" data-execution_count="11">
<pre><code>MBartConfig {
  "_name_or_path": "facebook/mbart-large-50",
  "_num_labels": 3,
  "activation_dropout": 0.0,
  "activation_function": "gelu",
  "add_bias_logits": false,
  "add_final_layer_norm": true,
  "architectures": [
    "MBartForConditionalGeneration"
  ],
  "attention_dropout": 0.0,
  "bos_token_id": 0,
  "classif_dropout": 0.0,
  "classifier_dropout": 0.0,
  "d_model": 1024,
  "decoder_attention_heads": 16,
  "decoder_ffn_dim": 4096,
  "decoder_layerdrop": 0.0,
  "decoder_layers": 12,
  "decoder_start_token_id": 2,
  "dropout": 0.1,
  "early_stopping": true,
  "encoder_attention_heads": 16,
  "encoder_ffn_dim": 4096,
  "encoder_layerdrop": 0.0,
  "encoder_layers": 12,
  "eos_token_id": 2,
  "forced_eos_token_id": 2,
  "gradient_checkpointing": false,
  "id2label": {
    "0": "LABEL_0",
    "1": "LABEL_1",
    "2": "LABEL_2",
    "3": "LABEL_3",
    "4": "LABEL_4"
  },
  "init_std": 0.02,
  "is_encoder_decoder": true,
  "label2id": {
    "LABEL_0": 0,
    "LABEL_1": 1,
    "LABEL_2": 2,
    "LABEL_3": 3,
    "LABEL_4": 4
  },
  "max_length": 200,
  "max_position_embeddings": 1024,
  "model_type": "mbart",
  "normalize_before": true,
  "normalize_embedding": true,
  "num_beams": 5,
  "num_hidden_layers": 12,
  "output_past": true,
  "pad_token_id": 1,
  "scale_embedding": true,
  "static_position_embeddings": false,
  "tokenizer_class": "MBart50Tokenizer",
  "transformers_version": "4.6.1",
  "use_cache": true,
  "vocab_size": 250054
}</code></pre>
</div>
</div>
</section>
<section id="dataloaders" class="level2">
<h2 class="anchored" data-anchor-id="dataloaders">DataLoaders</h2>
<div id="cell-17" class="cell" data-execution_count="12">
<div class="sourceCode cell-code" id="cb18" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb18-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># 3 lines!  Nice!!!</span></span>
<span id="cb18-2">blocks <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (HF_TextBlock(hf_arch, hf_config, hf_tokenizer, hf_model, max_length<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;">256</span>), CategoryBlock)</span>
<span id="cb18-3">dblock <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> DataBlock(blocks<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>blocks, get_x<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>ColReader(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'review_body'</span>), get_y<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>ColReader(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'stars'</span>), splitter<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>ColSplitter())</span>
<span id="cb18-4"></span>
<span id="cb18-5">dls <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> dblock.dataloaders(df, 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;">4</span>)</span></code></pre></div>
</div>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>It’s almost always useful to look at the <code>shape</code> of things in your batches (esp.&nbsp;when debugging)</p>
</div>
</div>
<p>For example, when running on a colab GPU I kept getting CUDA OOM even with a batch size of just 4. So I looked at the input_ids and saw that they were over 1,000 tokens long in some batches. So I adjusted the <code>max_length</code> above to ensure they weren’t longer that 128 characters and voila, you have the tutorial before you now.</p>
<p>Of course, you should run this with the biggest batch size and sequence size your GPU(s) will support.</p>
<div id="cell-19" class="cell" data-outputid="939e53a1-0d2a-4a47-f045-1957dc3f555c" data-execution_count="13">
<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">xb, yb <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> dls.one_batch()</span>
<span id="cb19-2">xb[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'input_ids'</span>].shape</span></code></pre></div>
<div class="cell-output cell-output-display" data-execution_count="13">
<pre><code>torch.Size([4, 256])</code></pre>
</div>
</div>
<div id="cell-20" class="cell" data-outputid="d3c7cdef-bf65-47d7-8f93-6b09908f2fdf" data-execution_count="14">
<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="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># what does human friendly data look like?</span></span>
<span id="cb21-2">dls.show_batch(dataloaders<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>dls, 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;">2</span>, trunc_at<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;">1500</span>)</span></code></pre></div>
<div class="cell-output cell-output-display">
<table class="dataframe caption-top table table-sm table-striped small" data-quarto-postprocess="true" data-border="1">
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th">text</th>
<th data-quarto-table-cell-role="th">category</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td data-quarto-table-cell-role="th">0</td>
<td>Ich habe mir für mein neues Apple iPad (2018er Modell) diese Folie zugelegt. Das ausschlaggebende Kriterium hierbei war natürlich die durch den Hersteller beworbene besondere Oberflächenstruktur der Folie. Ich benutze das iPad sehr oft zusammen mit dem Apple Pen und fand die Idee, dass sich der Stift beim Schreiben wie ein Bleistift auf einem Blatt Papier anfühlt, sehr verheißungsvoll. Dementsprechend war ich natürlich sehr gespannt darauf, ob die Folie denn auch hält, was der Hersteller verspricht. Dank Amazon kam die Lieferung wie gewohnt zügig an und nach dem ersten Auspacken zeigte sich, dass der Hersteller nicht zu viel versprochen hatte. Die Oberfläche der Folie fühlte sich in der Tat an wie ein Blatt Papier und auch die ersten "Trockenübungen" mit dem Apple Pen fühlten sich beinahe an wie echt. Das anbringen der Folie war dann aber leider (wie bei allen Folien) eine Herausforderung. Obwohl ich mich an die Anleitung gehalten hatte und besonders auf eine staubfreie Umgebung achtete schaffte ich es nicht die erste Folie gänzlich ohne Luft- und Staubeinschlüsse auf meinem iPad anzubringen</td>
<td>2</td>
</tr>
<tr class="even">
<td data-quarto-table-cell-role="th">1</td>
<td>Der erste Punkt das Design ist schlicht und schick. Die Uhr kann man zum Sport wie auch auf der Arbeit und in der Freizeit ohne Probleme anziehen. Das Laden der Fitnessuhr gestaltet sich ebenfalls intuitiv und schnell. Durch die USB- Schnittstelle kann die Uhr mit vorhanden Geräten geladen werden. Das waren dann auch schon die positiven Punkte der Uhr. Die Kopplung mit dem Handy funktioniert nur bedingt. Eine direkte Bluetooth Verbindung zwischen Handy und Uhr ist unmöglich. Durch die App können die Geräte zwar gekoppelt werden, diese weist aber erhebliche Fehlerstellen auf. Oft verbindet sich das Handy erst wieder mit der Uhr nach einem Neustart der Geräte. Die Uhr besitzt keinen eigenen Knopf zum An- und Ausschalten. Das automatische Aufblenden der Anzeige funktioniert ebenfalls nur bedingt und gefühlt nach dem Zufallsprinzip. Die Hilfestellungen durch Bedingungsanleitung und App bringen einen nicht wirklich weiter. Wer ausschließlich eine Uhr zum tracken der Schritte und Herzfrequenz sucht ist mit der Uhr gut aufgehoben. Zum täglichen Gebrauch als Uhrenersatz nicht zu empfehlen.</td>
<td>2</td>
</tr>
</tbody>
</table>
</div>
</div>
</section>
<section id="training" class="level2">
<h2 class="anchored" data-anchor-id="training">Training</h2>
<p>Print out the model so we can build a custom set of parameter groups for an MBart + Sequence Classification task</p>
<div id="cell-23" class="cell" data-execution_count="15">
<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"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># hf_model</span></span></code></pre></div>
</div>
<div id="cell-24" class="cell" data-execution_count="16">
<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> mbart_splitter(m):</span>
<span id="cb23-2">  model <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> m.hf_model <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>(m, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'hf_model'</span>)) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span> m</span>
<span id="cb23-3">  </span>
<span id="cb23-4">  embeds_modules <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [</span>
<span id="cb23-5">    model.model.encoder.embed_positions, </span>
<span id="cb23-6">    model.model.encoder.embed_tokens,</span>
<span id="cb23-7">    model.model.decoder.embed_positions, </span>
<span id="cb23-8">    model.model.decoder.embed_tokens</span>
<span id="cb23-9">  ]</span>
<span id="cb23-10"> </span>
<span id="cb23-11">  embeds <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> nn.Sequential(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>embeds_modules)</span>
<span id="cb23-12">  groups <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> L(embeds, model.model.encoder, model.model.decoder, model.classification_head)</span>
<span id="cb23-13">  <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> groups.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">map</span>(params).<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">filter</span>(<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">lambda</span> el: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(el) <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></code></pre></div>
</div>
<p>Configure our metrics and callbacks required by <code>blurr</code></p>
<div id="cell-26" class="cell" data-execution_count="17">
<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"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># define our metrics (see the sklearn docs for more info)</span></span>
<span id="cb24-2">precision <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> Precision(average<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'macro'</span>)</span>
<span id="cb24-3">recall <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> Recall(average<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'macro'</span>)</span>
<span id="cb24-4">f1 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> F1Score(average<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'macro'</span>)</span>
<span id="cb24-5"></span>
<span id="cb24-6">learn_metrics <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [accuracy, precision, recall, f1]</span>
<span id="cb24-7">learn_cbs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [HF_BaseModelCallback]</span></code></pre></div>
</div>
<p>Configure our <code>Learner</code> and train away …</p>
<div id="cell-28" class="cell" data-outputid="9a9184aa-e82c-4d71-f6b5-b0f8a80e6562" data-execution_count="18">
<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="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># configure our Learner; 3 lines!</span></span>
<span id="cb25-2">model <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> HF_BaseModelWrapper(hf_model)</span>
<span id="cb25-3">learn <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> Learner(dls, model, opt_func<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>Adam, loss_func<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>CrossEntropyLossFlat(), metrics<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>learn_metrics, cbs<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>learn_cbs, splitter<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>mbart_splitter)</span>
<span id="cb25-4">learn.freeze()</span>
<span id="cb25-5"></span>
<span id="cb25-6"><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;">len</span>(learn.opt.param_groups))</span></code></pre></div>
<div class="cell-output cell-output-stdout">
<pre><code>4</code></pre>
</div>
</div>
<div id="cell-29" class="cell" data-outputid="62dcfd91-96e8-498f-abcd-9742aaad7093" data-execution_count="19">
<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">learn.lr_find(suggestions<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 class="cell-output cell-output-display">

</div>
<div class="cell-output cell-output-display" data-execution_count="19">
<pre><code>SuggestedLRs(lr_min=6.918309736647643e-07, lr_steep=0.001737800776027143)</code></pre>
</div>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://ohmeow.com/posts/2021-05-25-mbart-sequence-classification-with-blurr_files/figure-html/cell-20-output-3.png" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
<div id="cell-30" class="cell" data-outputid="b56a97cc-08a9-4a64-bc46-53137e9a89d5" data-execution_count="20">
<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">learn.fit_one_cycle(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, lr_max<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;">7e-5</span>)</span></code></pre></div>
<div class="cell-output cell-output-display">
<table class="dataframe caption-top table table-sm table-striped small" data-quarto-postprocess="true" 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">accuracy</th>
<th data-quarto-table-cell-role="th">precision_score</th>
<th data-quarto-table-cell-role="th">recall_score</th>
<th data-quarto-table-cell-role="th">f1_score</th>
<th data-quarto-table-cell-role="th">time</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>0</td>
<td>1.151728</td>
<td>0.951163</td>
<td>0.592000</td>
<td>0.574056</td>
<td>0.578043</td>
<td>0.575234</td>
<td>05:23</td>
</tr>
</tbody>
</table>
</div>
</div>
<div id="cell-31" class="cell" data-outputid="1262a101-d603-47dd-e409-961a139c9fb9" data-execution_count="21">
<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">learn.show_results(learner<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>learn, 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;">2</span>, trunc_at<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;">1500</span>)</span></code></pre></div>
<div class="cell-output cell-output-display">

</div>
<div class="cell-output cell-output-stderr">
<pre><code>/usr/local/lib/python3.7/dist-packages/sklearn/metrics/_classification.py:1272: UndefinedMetricWarning: Precision is ill-defined and being set to 0.0 in labels with no predicted samples. Use `zero_division` parameter to control this behavior.
  _warn_prf(average, modifier, msg_start, len(result))
/usr/local/lib/python3.7/dist-packages/sklearn/metrics/_classification.py:1272: UndefinedMetricWarning: Recall is ill-defined and being set to 0.0 in labels with no true samples. Use `zero_division` parameter to control this behavior.
  _warn_prf(average, modifier, msg_start, len(result))</code></pre>
</div>
<div class="cell-output cell-output-display">
<table class="dataframe caption-top table table-sm table-striped small" data-quarto-postprocess="true" data-border="1">
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th">text</th>
<th data-quarto-table-cell-role="th">category</th>
<th data-quarto-table-cell-role="th">target</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td data-quarto-table-cell-role="th">0</td>
<td>Die Qualität meiner neuen Hausschuhe ist, wenn ich das nach drei Tagen schon sagen kann, sehr gut. Durch den sehr weichen Stoff "schmeicheln" sie regelrecht den Füßen. Es lässt sich wunderbar darauf laufen und -besonders wichtig für mich- sie halten auch schön warm. Was mir nicht gefällt, und deshalb ziehe ich auch einen Stern ab, ist die hintere Umrandung des Obermaterials. Hausschuhe sind ja hinten eigentlich flach, sodass ich schön in den Schuh rein- und rausschlüpfen kann. Durch die 1 cm Kante, die wahrscheinlich deshalb eingearbeitet wurde, um mehr Halt im Schuh zu haben, macht mich beim Treppensteigen sehr unsicher. Obwohl der Schuh an sich wunderbar passt, gibt mir die hintere Kante das Gefühl, jederzeit beim Laufen aus dem Schuh zu rutschen. Und beim Treppensteigen verstärkt sich dieses Gefühl. Ein klarer Minuspunkt; obwohl das sehr subjektiv ist. Manche werden wahrscheinlich nicht verstehen, was ich damit meine. Für knapp 20 Euro habe ich jedenfalls einen tollen Gegenwert erhalten. Meine letzten Hausschuhe, für die ich hier bei Amazon seinerzeit für knapp 40 Euro bezahlt habe, sind nach drei Jahren total aus</td>
<td>4</td>
<td>3</td>
</tr>
<tr class="even">
<td data-quarto-table-cell-role="th">1</td>
<td>Da ich unsere Frühstücksbrötchen gerne selber backe, habe ich mir das Baguetteblech besorgt. Das Blech ist wie abgebildet und funktioniert super. Passt genau auf ein Backblech. Reinigung ist sehr leicht, ich habe übrig gebliebene Mehl einfach mit Wasser abgewaschen. Einfetten war nicht von Nöten. Ich habe das Blech nur mit Mehl bestäubt, bevor ich die Brötchen drauf gelegt habe. Einen Stern gibt es Abzug, da bei der Lieferung bereits einige Kratzer in der Beschichtung waren. Ansonsten bin ich bisher sehr zufrieden! Nachtrag - Änderung der Punktezahl: Mittlerweile bin ich nicht mehr so von dem Backblech angetan. Der Teig bleibt immer öfter kleben und zuletzt waren die Brötchen unten sogar schwarz gefärbt. Das war nicht verbrannt sondern vom Backblech, ich weiß nicht ob sich die Beschichtung löst, oder ob das die Farbe ist. Aber das ist mit Sicherheit nicht gesund. Deswegen nur noch 2 Sterne!</td>
<td>2</td>
<td>3</td>
</tr>
</tbody>
</table>
</div>
</div>
<p>We’ll freeze all the layers with the exception of the decoder and classification_head layers (the last 2)</p>
<div id="cell-33" class="cell" data-execution_count="22">
<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">learn.freeze_to(<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 id="cell-34" class="cell" data-outputid="7f479668-02e3-4ad3-da10-bf32fee90c79" data-execution_count="23">
<div class="sourceCode cell-code" id="cb33" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb33-1">learn.lr_find(suggestions<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 class="cell-output cell-output-display">

</div>
<div class="cell-output cell-output-display" data-execution_count="23">
<pre><code>SuggestedLRs(lr_min=1.4454397387453355e-06, lr_steep=9.12010818865383e-07)</code></pre>
</div>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://ohmeow.com/posts/2021-05-25-mbart-sequence-classification-with-blurr_files/figure-html/cell-24-output-3.png" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
<div id="cell-35" class="cell" data-outputid="cc584337-81dd-48ed-a94a-fa0224723916" data-execution_count="24">
<div class="sourceCode cell-code" id="cb35" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb35-1">learn.fit_one_cycle(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>, lr_max<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>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2e-8</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2e-7</span>))</span></code></pre></div>
<div class="cell-output cell-output-display">
<table class="dataframe caption-top table table-sm table-striped small" data-quarto-postprocess="true" 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">accuracy</th>
<th data-quarto-table-cell-role="th">precision_score</th>
<th data-quarto-table-cell-role="th">recall_score</th>
<th data-quarto-table-cell-role="th">f1_score</th>
<th data-quarto-table-cell-role="th">time</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>0</td>
<td>1.020526</td>
<td>0.942416</td>
<td>0.612000</td>
<td>0.590443</td>
<td>0.597485</td>
<td>0.591900</td>
<td>10:13</td>
</tr>
<tr class="even">
<td>1</td>
<td>1.020601</td>
<td>0.935697</td>
<td>0.612000</td>
<td>0.593317</td>
<td>0.598285</td>
<td>0.594764</td>
<td>10:13</td>
</tr>
<tr class="odd">
<td>2</td>
<td>1.063076</td>
<td>0.934123</td>
<td>0.616000</td>
<td>0.597113</td>
<td>0.602207</td>
<td>0.598684</td>
<td>10:13</td>
</tr>
</tbody>
</table>
</div>
</div>
<div id="cell-36" class="cell" data-outputid="2ca7f7ea-5fdb-47b4-d11b-71d0bb5cd422" data-execution_count="25">
<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">learn.recorder.plot_loss()</span></code></pre></div>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://ohmeow.com/posts/2021-05-25-mbart-sequence-classification-with-blurr_files/figure-html/cell-26-output-1.png" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
<div id="cell-37" class="cell" data-outputid="e8d1ffef-8b6d-47a9-fb50-cc33bd0459d1" data-execution_count="26">
<div class="sourceCode cell-code" id="cb37" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb37-1">learn.show_results(learner<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>learn, 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;">2</span>, trunc_at<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;">1500</span>)</span></code></pre></div>
<div class="cell-output cell-output-display">

</div>
<div class="cell-output cell-output-stderr">
<pre><code>/usr/local/lib/python3.7/dist-packages/sklearn/metrics/_classification.py:1272: UndefinedMetricWarning: Precision is ill-defined and being set to 0.0 in labels with no predicted samples. Use `zero_division` parameter to control this behavior.
  _warn_prf(average, modifier, msg_start, len(result))
/usr/local/lib/python3.7/dist-packages/sklearn/metrics/_classification.py:1272: UndefinedMetricWarning: Recall is ill-defined and being set to 0.0 in labels with no true samples. Use `zero_division` parameter to control this behavior.
  _warn_prf(average, modifier, msg_start, len(result))</code></pre>
</div>
<div class="cell-output cell-output-display">
<table class="dataframe caption-top table table-sm table-striped small" data-quarto-postprocess="true" data-border="1">
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th">text</th>
<th data-quarto-table-cell-role="th">category</th>
<th data-quarto-table-cell-role="th">target</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td data-quarto-table-cell-role="th">0</td>
<td>Die Qualität meiner neuen Hausschuhe ist, wenn ich das nach drei Tagen schon sagen kann, sehr gut. Durch den sehr weichen Stoff "schmeicheln" sie regelrecht den Füßen. Es lässt sich wunderbar darauf laufen und -besonders wichtig für mich- sie halten auch schön warm. Was mir nicht gefällt, und deshalb ziehe ich auch einen Stern ab, ist die hintere Umrandung des Obermaterials. Hausschuhe sind ja hinten eigentlich flach, sodass ich schön in den Schuh rein- und rausschlüpfen kann. Durch die 1 cm Kante, die wahrscheinlich deshalb eingearbeitet wurde, um mehr Halt im Schuh zu haben, macht mich beim Treppensteigen sehr unsicher. Obwohl der Schuh an sich wunderbar passt, gibt mir die hintere Kante das Gefühl, jederzeit beim Laufen aus dem Schuh zu rutschen. Und beim Treppensteigen verstärkt sich dieses Gefühl. Ein klarer Minuspunkt; obwohl das sehr subjektiv ist. Manche werden wahrscheinlich nicht verstehen, was ich damit meine. Für knapp 20 Euro habe ich jedenfalls einen tollen Gegenwert erhalten. Meine letzten Hausschuhe, für die ich hier bei Amazon seinerzeit für knapp 40 Euro bezahlt habe, sind nach drei Jahren total aus</td>
<td>4</td>
<td>3</td>
</tr>
<tr class="even">
<td data-quarto-table-cell-role="th">1</td>
<td>Die Lampe machte zunächst einen ordentlichen Eindruck. Jedoch waren einige LEDs bereits bei der Auslieferung defekt. Der daraufhin kontaktierte Lieferant ignorierte mein Anschreiben. Die dazugehörige Zeitschaltuhr hat alle paar Wochen den Dienst quittiert. Da ich nicht so häufig in den Keller gehe, in dem die Lampe bei der Überwinterung Licht spenden sollte, stellte ich dies meist - offenbar jeweils einige Tage nach dem Ausfall fest - da die Pflanzen kurz vor dem krepieren waren. Die Zeitschaltuhr ließ sich mehrmals wieder aktivieren, ist nun aber nach wenigen Monaten ganz defekt, die Lampe lässt sich nicht mehr einschalten. Die Pflanzen sind nun alle eingegangen. Ich rate dringend von dem Kauf des Artikels ab.</td>
<td>1</td>
<td>1</td>
</tr>
</tbody>
</table>
</div>
</div>
</section>
<section id="inference" class="level2">
<h2 class="anchored" data-anchor-id="inference">Inference</h2>
<div id="cell-39" class="cell" data-outputid="668eb95b-0a1c-4d2e-86ac-a97867676f5f" data-execution_count="27">
<div class="sourceCode cell-code" id="cb39" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb39-1">txt <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tst_df.review_body[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>]</span>
<span id="cb39-2"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(txt)</span>
<span id="cb39-3">learn.blurr_predict(txt)</span></code></pre></div>
<div class="cell-output cell-output-stdout">
<pre><code>Leider, leider nach einmal waschen ausgeblichen . Es sieht super hübsch aus , nur leider stinkt es ganz schrecklich und ein Waschgang in der Maschine ist notwendig ! Nach einem mal waschen sah es aus als wäre es 10 Jahre alt und hatte 1000 e von Waschgängen hinter sich :( echt schade !</code></pre>
</div>
<div class="cell-output cell-output-display" data-execution_count="27">
<pre><code>[(('1',),
  (#1) [tensor(0)],
  (#1) [tensor([0.5725, 0.3474, 0.0716, 0.0067, 0.0018])])]</code></pre>
</div>
</div>
<div id="cell-40" class="cell" data-outputid="6af479e5-2bba-4606-9525-307116321cea" data-execution_count="28">
<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">txts <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>(tst_df.review_body.values[<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;">10</span>])</span>
<span id="cb42-2"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(txts)</span>
<span id="cb42-3">learn.blurr_predict(txts)</span></code></pre></div>
<div class="cell-output cell-output-stdout">
<pre><code>['zunächst macht der Anker Halter einen soliden Eindruck. Die Magnethalterung ist auch brauchbar. Was gar nicht geht ist die Tatsache, dass die Halterung für runde Lüftungsdüsen, anders als vom Hersteller beschrieben, nicht geeignet ist! Ständig fällt das Smartphone runter. Durch das häufige Wiederanbringen ist nun auch die Gummierung kaputt, was zur Folge hat, dass die Lüftungsdüse schön zerkratzt wird! Also Schrott, der auch noch mein Auto beschädigt! Für mich ist das nicht brauchbar!', 'Siegel sowie Verpackung war beschädigt und ware war gebraucht mit Verschleiß und Fingerabdrücke. Zurück geschickt und bessere qualitativere Artikel gekauft.', 'Habe dieses Produkt NIE erhalten und das Geld wurde nicht rückerstattet!!!!!!!', 'Die Träger sind schnell abgerissen', 'Druckbild ist leider nicht akzeptabel. Die kompletten seiten werden grau eingefärbt. Verkäufer antwortet nicht auf Emails. Deshalb absolut nicht empfehlenswert.', '🤬🤬🤬 Stoff löst sich nach kurzer Zeit', 'Beim zweiten Gebrauch bereits undicht!!!', 'Die Lieferung war prompt. 2 Gläser sind bereits undicht und Wasser befindet sich in den Zwischenräumen... was nun?', 'Bin überhaupt nicht zufrieden. Das Handy ist mir einmal kurz, aus minimalen Höhe ca 30cm, auf den Tisch gefallen und die Folie ist schon wieder kaputt. MfG Sonja Sax']</code></pre>
</div>
<div class="cell-output cell-output-display" data-execution_count="28">
<pre><code>[(('2',),
  (#1) [tensor(1)],
  (#1) [tensor([0.1873, 0.5228, 0.2539, 0.0327, 0.0032])]),
 (('1',),
  (#1) [tensor(0)],
  (#1) [tensor([0.6606, 0.2255, 0.0867, 0.0233, 0.0038])]),
 (('1',),
  (#1) [tensor(0)],
  (#1) [tensor([9.5275e-01, 4.1451e-02, 5.0995e-03, 3.2897e-04, 3.6943e-04])]),
 (('1',),
  (#1) [tensor(0)],
  (#1) [tensor([0.3692, 0.2738, 0.2347, 0.0907, 0.0316])]),
 (('1',),
  (#1) [tensor(0)],
  (#1) [tensor([8.1323e-01, 1.5297e-01, 3.0495e-02, 2.6044e-03, 6.9975e-04])]),
 (('4',),
  (#1) [tensor(3)],
  (#1) [tensor([0.0447, 0.1097, 0.2021, 0.3402, 0.3033])]),
 (('1',),
  (#1) [tensor(0)],
  (#1) [tensor([0.6773, 0.1921, 0.0808, 0.0320, 0.0179])]),
 (('3',),
  (#1) [tensor(2)],
  (#1) [tensor([0.1179, 0.2596, 0.4055, 0.1970, 0.0200])]),
 (('1',),
  (#1) [tensor(0)],
  (#1) [tensor([0.6736, 0.2547, 0.0619, 0.0078, 0.0020])])]</code></pre>
</div>
</div>
<p>Well that’s it!</p>
<p>I hope this article helps your fastai, huggingface, blurr out, and hey, if I’m doing something wrong above please let me know! I’m far from perfect :)</p>
<p>For more information on the MBart/MBar-50 architecture, see the huggingface docs <a href="https://huggingface.co/transformers/model_doc/mbart.html">here</a>.</p>


</section>

 ]]></description>
  <category>blurr</category>
  <category>huggingface</category>
  <category>fastai</category>
  <category>multilingual</category>
  <category>sequence classification</category>
  <guid>https://ohmeow.com/posts/2021-05-25-mbart-sequence-classification-with-blurr.html</guid>
  <pubDate>Tue, 25 May 2021 07:00:00 GMT</pubDate>
  <media:content url="https://ohmeow.com/posts/images/blurr-logo-small.png" medium="image" type="image/png" height="250" width="127"/>
</item>
<item>
  <title>A Journey Through Fastbook (AJTFB) - Chapter 4: Stochastic Gradient Descent</title>
  <dc:creator>Wayde Gilliam</dc:creator>
  <link>https://ohmeow.com/posts/2021-05-23-ajtfb-chapter-4.html</link>
  <description><![CDATA[ 




<p>Other posts in this series:</p>
<p><a href="../posts/2020-11-06-ajtfb-chapter-1.html">A Journey Through Fastbook (AJTFB) - Chapter 1</a><br>
<a href="../posts/2020-11-16-ajtfb-chapter-2.html">A Journey Through Fastbook (AJTFB) - Chapter 2</a><br>
<a href="../posts/2020-11-22-ajtfb-chapter-3.html">A Journey Through Fastbook (AJTFB) - Chapter 3</a><br>
<a href="../posts/2021-06-03-ajtfb-chapter-5.html">A Journey Through Fastbook (AJTFB) - Chapter 5</a><br>
<a href="../posts/2021-06-10-ajtfb-chapter-6-multilabel.html">A Journey Through Fastbook (AJTFB) - Chapter 6a</a><br>
<a href="../posts/2022-02-09-ajtfb-chapter-6-regression.html">A Journey Through Fastbook (AJTFB) - Chapter 6b</a><br>
<a href="../posts/2022-03-28-ajtfb-chapter-7.html">A Journey Through Fastbook (AJTFB) - Chapter 7</a><br>
<a href="../posts/2022-03-31-ajtfb-chapter-8.html">A Journey Through Fastbook (AJTFB) - Chapter 8</a><br>
<a href="../posts/2022-04-25-ajtfb-chapter-9.html">A Journey Through Fastbook (AJTFB) - Chapter 9</a></p>
<section id="how-to-visualize-a-grayscale-image-in-pandas" class="level2">
<h2 class="anchored" data-anchor-id="how-to-visualize-a-grayscale-image-in-pandas">How to visualize a grayscale image in pandas …</h2>
<div id="cell-4" class="cell" data-outputid="1409b4e2-9b5c-45dc-a376-0540bc964494">
<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">mnist_path <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> untar_data(URLs.MNIST_SAMPLE)</span>
<span id="cb1-2">mnist_path.ls()</span></code></pre></div>
<div class="cell-output cell-output-display">

</div>
<div class="cell-output cell-output-display" data-execution_count="2">
<pre><code>(#3) [Path('/root/.fastai/data/mnist_sample/labels.csv'),Path('/root/.fastai/data/mnist_sample/valid'),Path('/root/.fastai/data/mnist_sample/train')]</code></pre>
</div>
</div>
<div id="cell-5" class="cell" data-outputid="3922a9d8-a6e7-4e21-d6ee-da4ed1cb2717">
<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">sample_3 <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>((mnist_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;">'train/3'</span>).ls().<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sorted</span>()[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>])</span>
<span id="cb3-2">sample_3</span></code></pre></div>
<div class="cell-output cell-output-display" data-execution_count="3">
<div>
<figure class="figure">
<p><img src="https://ohmeow.com/posts/2021-05-23-ajtfb-chapter-4_files/figure-html/cell-4-output-1.png" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
<div id="cell-6" class="cell" data-outputid="acbb81b3-9f1f-422f-c014-ad52d60870ef">
<div class="sourceCode cell-code" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb4-1">sample_3_t <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tensor(sample_3)</span>
<span id="cb4-2">df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> pd.DataFrame(sample_3_t[<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;">15</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;">22</span>])</span>
<span id="cb4-3">df.style.set_properties(<span 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-size'</span>:<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'6pt'</span>}).background_gradient(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Greys'</span>)</span></code></pre></div>
<div class="cell-output cell-output-display" data-execution_count="4">
<style type="text/css">
#T_09cd021a_bc13_11eb_9210_0242ac1c0002row0_col0,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row0_col1,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row0_col2,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row0_col3,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row0_col4,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row0_col5,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row0_col6,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row0_col7,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row0_col8,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row0_col9,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row0_col10,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row0_col11,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row0_col12,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row0_col13,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row0_col14,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row0_col15,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row0_col16,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row0_col17,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row1_col0,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row1_col1,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row1_col2,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row1_col3,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row1_col4,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row1_col15,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row1_col16,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row1_col17,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row2_col0,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row2_col1,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row2_col2,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row2_col15,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row2_col16,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row2_col17,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row3_col0,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row3_col15,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row3_col16,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row3_col17,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row4_col0,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row4_col6,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row4_col7,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row4_col8,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row4_col9,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row4_col10,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row4_col15,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row4_col16,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row4_col17,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row5_col0,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row5_col5,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row5_col6,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row5_col7,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row5_col8,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row5_col9,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row5_col15,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row5_col16,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row5_col17,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row6_col0,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row6_col1,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row6_col2,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row6_col3,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row6_col4,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row6_col5,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row6_col6,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row6_col7,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row6_col8,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row6_col9,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row6_col14,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row6_col15,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row6_col16,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row6_col17,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row7_col0,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row7_col1,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row7_col2,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row7_col3,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row7_col4,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row7_col5,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row7_col6,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row7_col13,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row7_col14,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row7_col15,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row7_col16,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row7_col17,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row8_col0,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row8_col1,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row8_col2,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row8_col3,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row8_col4,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row8_col13,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row8_col14,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row8_col15,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row8_col16,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row8_col17,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row9_col0,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row9_col1,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row9_col2,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row9_col3,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row9_col4,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row9_col16,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row9_col17,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row10_col0,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row10_col1,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row10_col2,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row10_col3,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row10_col4,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row10_col5,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row10_col6,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row10_col17{
            font-size:  6pt;
            background-color:  #ffffff;
            color:  #000000;
        }#T_09cd021a_bc13_11eb_9210_0242ac1c0002row1_col5{
            font-size:  6pt;
            background-color:  #efefef;
            color:  #000000;
        }#T_09cd021a_bc13_11eb_9210_0242ac1c0002row1_col6,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row1_col13{
            font-size:  6pt;
            background-color:  #7c7c7c;
            color:  #000000;
        }#T_09cd021a_bc13_11eb_9210_0242ac1c0002row1_col7{
            font-size:  6pt;
            background-color:  #4a4a4a;
            color:  #f1f1f1;
        }#T_09cd021a_bc13_11eb_9210_0242ac1c0002row1_col8,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row1_col9,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row1_col10,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row2_col5,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row2_col6,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row2_col7,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row2_col11,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row2_col12,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row2_col13,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row3_col4,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row3_col12,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row3_col13,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row4_col1,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row4_col2,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row4_col3,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row4_col12,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row4_col13,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row5_col12,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row6_col11,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row9_col11,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row10_col11,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row10_col12,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row10_col13,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row10_col14,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row10_col15,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row10_col16{
            font-size:  6pt;
            background-color:  #000000;
            color:  #f1f1f1;
        }#T_09cd021a_bc13_11eb_9210_0242ac1c0002row1_col11{
            font-size:  6pt;
            background-color:  #606060;
            color:  #f1f1f1;
        }#T_09cd021a_bc13_11eb_9210_0242ac1c0002row1_col12{
            font-size:  6pt;
            background-color:  #4d4d4d;
            color:  #f1f1f1;
        }#T_09cd021a_bc13_11eb_9210_0242ac1c0002row1_col14{
            font-size:  6pt;
            background-color:  #bbbbbb;
            color:  #000000;
        }#T_09cd021a_bc13_11eb_9210_0242ac1c0002row2_col3{
            font-size:  6pt;
            background-color:  #e4e4e4;
            color:  #000000;
        }#T_09cd021a_bc13_11eb_9210_0242ac1c0002row2_col4,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row8_col6{
            font-size:  6pt;
            background-color:  #6b6b6b;
            color:  #000000;
        }#T_09cd021a_bc13_11eb_9210_0242ac1c0002row2_col8,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row2_col14,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row3_col14{
            font-size:  6pt;
            background-color:  #171717;
            color:  #f1f1f1;
        }#T_09cd021a_bc13_11eb_9210_0242ac1c0002row2_col9,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row3_col11{
            font-size:  6pt;
            background-color:  #4b4b4b;
            color:  #f1f1f1;
        }#T_09cd021a_bc13_11eb_9210_0242ac1c0002row2_col10,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row7_col10,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row8_col8,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row8_col10,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row9_col8,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row9_col10{
            font-size:  6pt;
            background-color:  #010101;
            color:  #f1f1f1;
        }#T_09cd021a_bc13_11eb_9210_0242ac1c0002row3_col1{
            font-size:  6pt;
            background-color:  #272727;
            color:  #f1f1f1;
        }#T_09cd021a_bc13_11eb_9210_0242ac1c0002row3_col2{
            font-size:  6pt;
            background-color:  #0a0a0a;
            color:  #f1f1f1;
        }#T_09cd021a_bc13_11eb_9210_0242ac1c0002row3_col3{
            font-size:  6pt;
            background-color:  #050505;
            color:  #f1f1f1;
        }#T_09cd021a_bc13_11eb_9210_0242ac1c0002row3_col5{
            font-size:  6pt;
            background-color:  #333333;
            color:  #f1f1f1;
        }#T_09cd021a_bc13_11eb_9210_0242ac1c0002row3_col6{
            font-size:  6pt;
            background-color:  #e6e6e6;
            color:  #000000;
        }#T_09cd021a_bc13_11eb_9210_0242ac1c0002row3_col7,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row3_col10{
            font-size:  6pt;
            background-color:  #fafafa;
            color:  #000000;
        }#T_09cd021a_bc13_11eb_9210_0242ac1c0002row3_col8{
            font-size:  6pt;
            background-color:  #fbfbfb;
            color:  #000000;
        }#T_09cd021a_bc13_11eb_9210_0242ac1c0002row3_col9{
            font-size:  6pt;
            background-color:  #fdfdfd;
            color:  #000000;
        }#T_09cd021a_bc13_11eb_9210_0242ac1c0002row4_col4{
            font-size:  6pt;
            background-color:  #1b1b1b;
            color:  #f1f1f1;
        }#T_09cd021a_bc13_11eb_9210_0242ac1c0002row4_col5{
            font-size:  6pt;
            background-color:  #e0e0e0;
            color:  #000000;
        }#T_09cd021a_bc13_11eb_9210_0242ac1c0002row4_col11{
            font-size:  6pt;
            background-color:  #4e4e4e;
            color:  #f1f1f1;
        }#T_09cd021a_bc13_11eb_9210_0242ac1c0002row4_col14{
            font-size:  6pt;
            background-color:  #767676;
            color:  #000000;
        }#T_09cd021a_bc13_11eb_9210_0242ac1c0002row5_col1{
            font-size:  6pt;
            background-color:  #fcfcfc;
            color:  #000000;
        }#T_09cd021a_bc13_11eb_9210_0242ac1c0002row5_col2,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row5_col3{
            font-size:  6pt;
            background-color:  #f6f6f6;
            color:  #000000;
        }#T_09cd021a_bc13_11eb_9210_0242ac1c0002row5_col4,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row7_col7{
            font-size:  6pt;
            background-color:  #f8f8f8;
            color:  #000000;
        }#T_09cd021a_bc13_11eb_9210_0242ac1c0002row5_col10,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row10_col7{
            font-size:  6pt;
            background-color:  #e8e8e8;
            color:  #000000;
        }#T_09cd021a_bc13_11eb_9210_0242ac1c0002row5_col11{
            font-size:  6pt;
            background-color:  #222222;
            color:  #f1f1f1;
        }#T_09cd021a_bc13_11eb_9210_0242ac1c0002row5_col13,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row6_col12{
            font-size:  6pt;
            background-color:  #090909;
            color:  #f1f1f1;
        }#T_09cd021a_bc13_11eb_9210_0242ac1c0002row5_col14{
            font-size:  6pt;
            background-color:  #d0d0d0;
            color:  #000000;
        }#T_09cd021a_bc13_11eb_9210_0242ac1c0002row6_col10,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row7_col11,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row9_col6{
            font-size:  6pt;
            background-color:  #060606;
            color:  #f1f1f1;
        }#T_09cd021a_bc13_11eb_9210_0242ac1c0002row6_col13{
            font-size:  6pt;
            background-color:  #979797;
            color:  #000000;
        }#T_09cd021a_bc13_11eb_9210_0242ac1c0002row7_col8{
            font-size:  6pt;
            background-color:  #b6b6b6;
            color:  #000000;
        }#T_09cd021a_bc13_11eb_9210_0242ac1c0002row7_col9{
            font-size:  6pt;
            background-color:  #252525;
            color:  #f1f1f1;
        }#T_09cd021a_bc13_11eb_9210_0242ac1c0002row7_col12{
            font-size:  6pt;
            background-color:  #999999;
            color:  #000000;
        }#T_09cd021a_bc13_11eb_9210_0242ac1c0002row8_col5{
            font-size:  6pt;
            background-color:  #f9f9f9;
            color:  #000000;
        }#T_09cd021a_bc13_11eb_9210_0242ac1c0002row8_col7{
            font-size:  6pt;
            background-color:  #101010;
            color:  #f1f1f1;
        }#T_09cd021a_bc13_11eb_9210_0242ac1c0002row8_col9,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row9_col9{
            font-size:  6pt;
            background-color:  #020202;
            color:  #f1f1f1;
        }#T_09cd021a_bc13_11eb_9210_0242ac1c0002row8_col11{
            font-size:  6pt;
            background-color:  #545454;
            color:  #f1f1f1;
        }#T_09cd021a_bc13_11eb_9210_0242ac1c0002row8_col12{
            font-size:  6pt;
            background-color:  #f1f1f1;
            color:  #000000;
        }#T_09cd021a_bc13_11eb_9210_0242ac1c0002row9_col5{
            font-size:  6pt;
            background-color:  #f7f7f7;
            color:  #000000;
        }#T_09cd021a_bc13_11eb_9210_0242ac1c0002row9_col7{
            font-size:  6pt;
            background-color:  #030303;
            color:  #f1f1f1;
        }#T_09cd021a_bc13_11eb_9210_0242ac1c0002row9_col12{
            font-size:  6pt;
            background-color:  #181818;
            color:  #f1f1f1;
        }#T_09cd021a_bc13_11eb_9210_0242ac1c0002row9_col13{
            font-size:  6pt;
            background-color:  #303030;
            color:  #f1f1f1;
        }#T_09cd021a_bc13_11eb_9210_0242ac1c0002row9_col14{
            font-size:  6pt;
            background-color:  #a9a9a9;
            color:  #000000;
        }#T_09cd021a_bc13_11eb_9210_0242ac1c0002row9_col15{
            font-size:  6pt;
            background-color:  #fefefe;
            color:  #000000;
        }#T_09cd021a_bc13_11eb_9210_0242ac1c0002row10_col8,#T_09cd021a_bc13_11eb_9210_0242ac1c0002row10_col9{
            font-size:  6pt;
            background-color:  #bababa;
            color:  #000000;
        }#T_09cd021a_bc13_11eb_9210_0242ac1c0002row10_col10{
            font-size:  6pt;
            background-color:  #393939;
            color:  #f1f1f1;
        }</style>
<table id="T_09cd021a_bc13_11eb_9210_0242ac1c0002" class="caption-top table table-sm table-striped small" data-quarto-postprocess="true">
<thead>
<tr class="header">
<th class="blank level0" data-quarto-table-cell-role="th"></th>
<th class="col_heading level0 col0" data-quarto-table-cell-role="th">0</th>
<th class="col_heading level0 col1" data-quarto-table-cell-role="th">1</th>
<th class="col_heading level0 col2" data-quarto-table-cell-role="th">2</th>
<th class="col_heading level0 col3" data-quarto-table-cell-role="th">3</th>
<th class="col_heading level0 col4" data-quarto-table-cell-role="th">4</th>
<th class="col_heading level0 col5" data-quarto-table-cell-role="th">5</th>
<th class="col_heading level0 col6" data-quarto-table-cell-role="th">6</th>
<th class="col_heading level0 col7" data-quarto-table-cell-role="th">7</th>
<th class="col_heading level0 col8" data-quarto-table-cell-role="th">8</th>
<th class="col_heading level0 col9" data-quarto-table-cell-role="th">9</th>
<th class="col_heading level0 col10" data-quarto-table-cell-role="th">10</th>
<th class="col_heading level0 col11" data-quarto-table-cell-role="th">11</th>
<th class="col_heading level0 col12" data-quarto-table-cell-role="th">12</th>
<th class="col_heading level0 col13" data-quarto-table-cell-role="th">13</th>
<th class="col_heading level0 col14" data-quarto-table-cell-role="th">14</th>
<th class="col_heading level0 col15" data-quarto-table-cell-role="th">15</th>
<th class="col_heading level0 col16" data-quarto-table-cell-role="th">16</th>
<th class="col_heading level0 col17" data-quarto-table-cell-role="th">17</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002level0_row0" class="row_heading level0 row0" data-quarto-table-cell-role="th">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row0_col0" class="data row0 col0">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row0_col1" class="data row0 col1">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row0_col2" class="data row0 col2">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row0_col3" class="data row0 col3">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row0_col4" class="data row0 col4">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row0_col5" class="data row0 col5">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row0_col6" class="data row0 col6">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row0_col7" class="data row0 col7">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row0_col8" class="data row0 col8">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row0_col9" class="data row0 col9">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row0_col10" class="data row0 col10">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row0_col11" class="data row0 col11">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row0_col12" class="data row0 col12">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row0_col13" class="data row0 col13">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row0_col14" class="data row0 col14">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row0_col15" class="data row0 col15">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row0_col16" class="data row0 col16">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row0_col17" class="data row0 col17">0</td>
</tr>
<tr class="even">
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002level0_row1" class="row_heading level0 row1" data-quarto-table-cell-role="th">1</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row1_col0" class="data row1 col0">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row1_col1" class="data row1 col1">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row1_col2" class="data row1 col2">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row1_col3" class="data row1 col3">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row1_col4" class="data row1 col4">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row1_col5" class="data row1 col5">29</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row1_col6" class="data row1 col6">150</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row1_col7" class="data row1 col7">195</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row1_col8" class="data row1 col8">254</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row1_col9" class="data row1 col9">255</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row1_col10" class="data row1 col10">254</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row1_col11" class="data row1 col11">176</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row1_col12" class="data row1 col12">193</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row1_col13" class="data row1 col13">150</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row1_col14" class="data row1 col14">96</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row1_col15" class="data row1 col15">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row1_col16" class="data row1 col16">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row1_col17" class="data row1 col17">0</td>
</tr>
<tr class="odd">
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002level0_row2" class="row_heading level0 row2" data-quarto-table-cell-role="th">2</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row2_col0" class="data row2 col0">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row2_col1" class="data row2 col1">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row2_col2" class="data row2 col2">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row2_col3" class="data row2 col3">48</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row2_col4" class="data row2 col4">166</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row2_col5" class="data row2 col5">224</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row2_col6" class="data row2 col6">253</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row2_col7" class="data row2 col7">253</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row2_col8" class="data row2 col8">234</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row2_col9" class="data row2 col9">196</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row2_col10" class="data row2 col10">253</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row2_col11" class="data row2 col11">253</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row2_col12" class="data row2 col12">253</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row2_col13" class="data row2 col13">253</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row2_col14" class="data row2 col14">233</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row2_col15" class="data row2 col15">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row2_col16" class="data row2 col16">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row2_col17" class="data row2 col17">0</td>
</tr>
<tr class="even">
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002level0_row3" class="row_heading level0 row3" data-quarto-table-cell-role="th">3</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row3_col0" class="data row3 col0">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row3_col1" class="data row3 col1">93</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row3_col2" class="data row3 col2">244</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row3_col3" class="data row3 col3">249</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row3_col4" class="data row3 col4">253</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row3_col5" class="data row3 col5">187</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row3_col6" class="data row3 col6">46</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row3_col7" class="data row3 col7">10</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row3_col8" class="data row3 col8">8</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row3_col9" class="data row3 col9">4</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row3_col10" class="data row3 col10">10</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row3_col11" class="data row3 col11">194</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row3_col12" class="data row3 col12">253</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row3_col13" class="data row3 col13">253</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row3_col14" class="data row3 col14">233</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row3_col15" class="data row3 col15">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row3_col16" class="data row3 col16">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row3_col17" class="data row3 col17">0</td>
</tr>
<tr class="odd">
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002level0_row4" class="row_heading level0 row4" data-quarto-table-cell-role="th">4</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row4_col0" class="data row4 col0">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row4_col1" class="data row4 col1">107</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row4_col2" class="data row4 col2">253</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row4_col3" class="data row4 col3">253</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row4_col4" class="data row4 col4">230</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row4_col5" class="data row4 col5">48</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row4_col6" class="data row4 col6">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row4_col7" class="data row4 col7">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row4_col8" class="data row4 col8">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row4_col9" class="data row4 col9">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row4_col10" class="data row4 col10">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row4_col11" class="data row4 col11">192</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row4_col12" class="data row4 col12">253</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row4_col13" class="data row4 col13">253</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row4_col14" class="data row4 col14">156</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row4_col15" class="data row4 col15">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row4_col16" class="data row4 col16">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row4_col17" class="data row4 col17">0</td>
</tr>
<tr class="even">
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002level0_row5" class="row_heading level0 row5" data-quarto-table-cell-role="th">5</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row5_col0" class="data row5 col0">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row5_col1" class="data row5 col1">3</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row5_col2" class="data row5 col2">20</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row5_col3" class="data row5 col3">20</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row5_col4" class="data row5 col4">15</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row5_col5" class="data row5 col5">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row5_col6" class="data row5 col6">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row5_col7" class="data row5 col7">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row5_col8" class="data row5 col8">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row5_col9" class="data row5 col9">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row5_col10" class="data row5 col10">43</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row5_col11" class="data row5 col11">224</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row5_col12" class="data row5 col12">253</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row5_col13" class="data row5 col13">245</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row5_col14" class="data row5 col14">74</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row5_col15" class="data row5 col15">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row5_col16" class="data row5 col16">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row5_col17" class="data row5 col17">0</td>
</tr>
<tr class="odd">
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002level0_row6" class="row_heading level0 row6" data-quarto-table-cell-role="th">6</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row6_col0" class="data row6 col0">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row6_col1" class="data row6 col1">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row6_col2" class="data row6 col2">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row6_col3" class="data row6 col3">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row6_col4" class="data row6 col4">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row6_col5" class="data row6 col5">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row6_col6" class="data row6 col6">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row6_col7" class="data row6 col7">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row6_col8" class="data row6 col8">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row6_col9" class="data row6 col9">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row6_col10" class="data row6 col10">249</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row6_col11" class="data row6 col11">253</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row6_col12" class="data row6 col12">245</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row6_col13" class="data row6 col13">126</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row6_col14" class="data row6 col14">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row6_col15" class="data row6 col15">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row6_col16" class="data row6 col16">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row6_col17" class="data row6 col17">0</td>
</tr>
<tr class="even">
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002level0_row7" class="row_heading level0 row7" data-quarto-table-cell-role="th">7</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row7_col0" class="data row7 col0">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row7_col1" class="data row7 col1">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row7_col2" class="data row7 col2">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row7_col3" class="data row7 col3">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row7_col4" class="data row7 col4">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row7_col5" class="data row7 col5">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row7_col6" class="data row7 col6">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row7_col7" class="data row7 col7">14</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row7_col8" class="data row7 col8">101</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row7_col9" class="data row7 col9">223</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row7_col10" class="data row7 col10">253</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row7_col11" class="data row7 col11">248</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row7_col12" class="data row7 col12">124</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row7_col13" class="data row7 col13">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row7_col14" class="data row7 col14">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row7_col15" class="data row7 col15">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row7_col16" class="data row7 col16">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row7_col17" class="data row7 col17">0</td>
</tr>
<tr class="odd">
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002level0_row8" class="row_heading level0 row8" data-quarto-table-cell-role="th">8</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row8_col0" class="data row8 col0">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row8_col1" class="data row8 col1">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row8_col2" class="data row8 col2">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row8_col3" class="data row8 col3">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row8_col4" class="data row8 col4">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row8_col5" class="data row8 col5">11</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row8_col6" class="data row8 col6">166</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row8_col7" class="data row8 col7">239</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row8_col8" class="data row8 col8">253</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row8_col9" class="data row8 col9">253</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row8_col10" class="data row8 col10">253</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row8_col11" class="data row8 col11">187</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row8_col12" class="data row8 col12">30</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row8_col13" class="data row8 col13">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row8_col14" class="data row8 col14">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row8_col15" class="data row8 col15">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row8_col16" class="data row8 col16">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row8_col17" class="data row8 col17">0</td>
</tr>
<tr class="even">
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002level0_row9" class="row_heading level0 row9" data-quarto-table-cell-role="th">9</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row9_col0" class="data row9 col0">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row9_col1" class="data row9 col1">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row9_col2" class="data row9 col2">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row9_col3" class="data row9 col3">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row9_col4" class="data row9 col4">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row9_col5" class="data row9 col5">16</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row9_col6" class="data row9 col6">248</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row9_col7" class="data row9 col7">250</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row9_col8" class="data row9 col8">253</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row9_col9" class="data row9 col9">253</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row9_col10" class="data row9 col10">253</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row9_col11" class="data row9 col11">253</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row9_col12" class="data row9 col12">232</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row9_col13" class="data row9 col13">213</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row9_col14" class="data row9 col14">111</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row9_col15" class="data row9 col15">2</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row9_col16" class="data row9 col16">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row9_col17" class="data row9 col17">0</td>
</tr>
<tr class="odd">
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002level0_row10" class="row_heading level0 row10" data-quarto-table-cell-role="th">10</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row10_col0" class="data row10 col0">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row10_col1" class="data row10 col1">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row10_col2" class="data row10 col2">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row10_col3" class="data row10 col3">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row10_col4" class="data row10 col4">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row10_col5" class="data row10 col5">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row10_col6" class="data row10 col6">0</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row10_col7" class="data row10 col7">43</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row10_col8" class="data row10 col8">98</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row10_col9" class="data row10 col9">98</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row10_col10" class="data row10 col10">208</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row10_col11" class="data row10 col11">253</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row10_col12" class="data row10 col12">253</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row10_col13" class="data row10 col13">253</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row10_col14" class="data row10 col14">253</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row10_col15" class="data row10 col15">187</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row10_col16" class="data row10 col16">22</td>
<td id="T_09cd021a_bc13_11eb_9210_0242ac1c0002row10_col17" class="data row10 col17">0</td>
</tr>
</tbody>
</table>
</div>
</div>
</section>
<section id="what-is-a-baseline-model-and-why-do-you-want-one" class="level2">
<h2 class="anchored" data-anchor-id="what-is-a-baseline-model-and-why-do-you-want-one">What is a baseline model and why do you want one?</h2>
<blockquote class="blockquote">
<p>A simple model that you are confident should perform reasonably well. It should be simple to implement and easy to test</p>
</blockquote>
<p><strong>Why do you want to start with a baseline model?</strong> &gt; … without starting with a sensible baseline, it is difficult to know whether your super-fancy models are any good</p>
<p><strong>How do you build/find one of these models?</strong></p>
<p>You can search online for folks that have trained models to solve a problem similar to your’s and/or you can start with one of the high-level examples in the fastai docs against your data. There are a bunch covering core vision, text, tabuluar and colab filtering tasks right <a href="https://docs.fast.ai/tutorial.html">here</a>.</p>
</section>
<section id="tensors" class="level2">
<h2 class="anchored" data-anchor-id="tensors">Tensors</h2>
<p><strong>What is a “Tensor”?</strong></p>
<p>Like a numpy array, but with GPU support. The data it contains must be of the <strong><em>same type</em></strong> and must conform in <strong><em>rectangular shape</em></strong>.</p>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>“try to avoid as much as possible writing loops, and replace them by commands that work directly on arrays or tensors”</p>
</div>
</div>
<p>Let’s take a look ..</p>
<div id="cell-9" class="cell" data-outputid="dabab129-c5de-4d68-8e0e-410fe5beada3">
<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">threes <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (mnist_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;">'train/3'</span>).ls().<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sorted</span>()</span>
<span id="cb5-2"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(threes), threes[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>]</span></code></pre></div>
<div class="cell-output cell-output-display" data-execution_count="5">
<pre><code>(6131, Path('/root/.fastai/data/mnist_sample/train/3/10.png'))</code></pre>
</div>
</div>
<div id="cell-10" class="cell" data-outputid="348eec91-90d7-41d9-b8d8-690f31d8932b">
<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">all_threes <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [ tensor(Image.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">open</span>(fp)) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> fp <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> threes ]</span>
<span id="cb7-2"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(all_threes), all_threes[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>].shape</span></code></pre></div>
<div class="cell-output cell-output-display" data-execution_count="6">
<pre><code>(6131, torch.Size([28, 28]))</code></pre>
</div>
</div>
<div id="cell-11" class="cell" data-outputid="a9d31cfe-372d-44a8-e636-5182bf17b860">
<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">stacked_threes <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> torch.stack(all_threes).<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><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">255</span></span>
<span id="cb9-2">stacked_threes.shape</span></code></pre></div>
<div class="cell-output cell-output-display" data-execution_count="7">
<pre><code>torch.Size([6131, 28, 28])</code></pre>
</div>
</div>
<p>Important information about tensors include its <code>shape</code>, <code>rank</code>, and <code>type</code>:</p>
<div id="cell-13" class="cell" data-outputid="7dd41606-9def-4baa-c38d-07a060860728">
<div class="sourceCode cell-code" id="cb11" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb11-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># shape = the length of each axis</span></span>
<span id="cb11-2"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'shape: '</span>, stacked_threes.shape)</span>
<span id="cb11-3"></span>
<span id="cb11-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># rank = the total number of axes</span></span>
<span id="cb11-5"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'rank: '</span>, stacked_threes.ndim)</span>
<span id="cb11-6"></span>
<span id="cb11-7"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># type = the datatype of its contents</span></span>
<span id="cb11-8"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'type: '</span>, stacked_threes.dtype)</span></code></pre></div>
<div class="cell-output cell-output-stdout">
<pre><code>shape:  torch.Size([6131, 28, 28])
rank:  3
type:  torch.float32</code></pre>
</div>
</div>
<p>Important things you can do to a tensor, <code>view</code>, <code>@</code>, <code>where</code></p>
<div id="cell-15" class="cell" data-outputid="23294969-8b8e-4c89-86b0-3ff0ac3f58db">
<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"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># view = change the shape of a tensor without changing its contents</span></span>
<span id="cb13-2">stacked_threes_rank_2 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> stacked_threes.view(<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;">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="cb13-3"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'orig. shape: '</span>, stacked_threes.shape)</span>
<span id="cb13-4"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'make into a rank 2 tensor'</span>, stacked_threes_rank_2.shape)</span>
<span id="cb13-5"></span>
<span id="cb13-6"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># @ = operator for matrix multiplication</span></span>
<span id="cb13-7"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'result of matrix multiplication: '</span>, (stacked_threes <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">@</span> torch.randn((<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;">28</span>,<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">28</span>))).shape)</span>
<span id="cb13-8"></span>
<span id="cb13-9"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># where = torch.where(a,b,c) =&gt; [b[i] if a[i] else c[i] for i in range(len(a))] ... see p.167</span></span>
<span id="cb13-10">trgs <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;">0</span>,<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>])</span>
<span id="cb13-11">preds <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tensor([<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.9</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.4</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.2</span>])</span>
<span id="cb13-12"></span>
<span id="cb13-13"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> mnist_loss(preds, targs):</span>
<span id="cb13-14">  <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> torch.where(targs <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;">1</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> preds, preds).mean()</span>
<span id="cb13-15"></span>
<span id="cb13-16"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'output of where: '</span>, mnist_loss(preds, trgs))</span></code></pre></div>
<div class="cell-output cell-output-stdout">
<pre><code>orig. shape:  torch.Size([6131, 28, 28])
make into a rank 2 tensor torch.Size([6131, 784])
result of matrix multiplication:  torch.Size([6131, 28, 28])
output of where:  tensor(0.4333)</code></pre>
</div>
</div>
<p>For an interactive lesson on matrix multiplication, <a href="http://matrixmultiplication.xyz/">this is the best</a>!</p>
<p>Check out pp.145-148 to learn about “broadcasting”, a critical piece to understanding how you can and should manipulate tensors or numpy arrays!</p>
</section>
<section id="stochastic-gradient-descent---how-to-train-a-model" class="level2">
<h2 class="anchored" data-anchor-id="stochastic-gradient-descent---how-to-train-a-model">Stochastic Gradient Descent - How to train a model</h2>
<p>Here are the steps:</p>
<ol type="1">
<li><p><strong>INITIALIZE</strong> the weights = initializing parameters to random values</p></li>
<li><p>For each image, <strong>PREDICT</strong> whether it is a 3 or 7</p></li>
<li><p>Based on the predictions, calculate how good the model is by calculating its <strong>LOSS</strong> (small is good)</p></li>
<li><p>Calculate the <strong>GRADIENT</strong>, <strong><em>“which measures for each weight how changing the weight would change the loss”</em></strong></p></li>
<li><p><strong>STEP</strong>, change all the weights based on the gradient</p></li>
<li><p>Starting at step 2, <strong>REPEAT</strong></p></li>
<li><p><strong>STOP</strong> when you don’t want to train any longer or the model is good enough</p></li>
</ol>
<p>Below, we’ll delve deeper into these steps. We’ll do this by getting a big more into the sample code beginning on p.150 …</p>
<section id="step-1-initializing-weights" class="level3">
<h3 class="anchored" data-anchor-id="step-1-initializing-weights">Step 1: Initializing weights</h3>
<p>One way is presented on p.164:</p>
<pre><code>def init_params(size, std=1.0) return (torch.randn(size)*std).requires_grad_()

weights = init_params((28*28,1)) #=&gt; raturns a rank 2, 784x1 tensor, with random values</code></pre>
</section>
<section id="step-3-calculating-the-loss" class="level3">
<h3 class="anchored" data-anchor-id="step-3-calculating-the-loss">Step 3: Calculating the loss</h3>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>“For continuous data, it’s common to use <em>mean squared error</em>”. In order to understand how to write this, read it right-to-left (e.g., error -&gt; square -&gt; mean)</p>
</div>
</div>
<pre><code>def mse(preds, targs): return ((preds-targs)**2).mean()

# in PyTorch
loss = F.mse_loss(preds, targs)</code></pre>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>Accuracy is a bad loss function</p>
</div>
</div>
<p><strong>Why is accuracy a poor loss function?</strong></p>
<blockquote class="blockquote">
<p>“The gradient of a funciton is its slope, or its steepness … how much the value of the function goes up or down, divided by how much we changed the input <code>(y_new - y_old) / (x_new - x_old)</code> …. The problem with [accuracy] is that a small change in weights from <code>x_old</code> to <code>x_new</code> isn’t likely to cause any prediction to change, so <code>(y_new - y_old)</code> will almost always be 0 … **the gradient is 0 almost everywhere. A very small change in the value of a weight will often not change the accuracy at all</p>
</blockquote>
<p>A gradient = 0 will mean that the weights aren’t updated.</p>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>“We need a loss function that, when our weights result in slightly better predictions, gives us a slightly better loss”</p>
</div>
</div>
<p><strong>Metrics v. Loss</strong></p>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>“… <strong><em>the metric is to drive human understanding</em></strong> and <strong><em>the loss is to drive automated learning</em></strong>.</p>
</div>
</div>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>“… focus on these metrics, rather than the loss, when judging the performance of a model.”</p>
</div>
</div>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>“… the loss must be a function that has a meaningful derivative … must be reasonably smooth [so] that [it] would respond to small changes in confidence level.</p>
</div>
</div>
<p>The loss function is one that can be optimized using its gradient!</p>
</section>
<section id="step-4-calculating-the-gradients" class="level3">
<h3 class="anchored" data-anchor-id="step-4-calculating-the-gradients">Step 4: Calculating the gradients</h3>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>“the gradients <strong><em>tell us how much we have to change each weight</em></strong> to make our model better … allows us to more quickly calculate whether our loss will go up or down we we make those adjustments”</p>
</div>
</div>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>“The gradients <strong><em>tell us only the slope of our function</em></strong>; they don’t tell us exactly how far to adjust the parameters. But they do give us some idea of how far” (large slope = bigger adjustments needed whereas a small slope suggests we are close to the optimal value)</p>
</div>
</div>
<p>“The <strong><em>derivative</em></strong> of a function tells you how much a change in its parameters will change its result”</p>
<p>Remember: We are calculating a gradient for <em>EVERY</em> weight so we know how to adjust it to make our model better (i.e., lower the LOSS)</p>
<p><code>requires_grad</code> tells PyTorch “that we want to calculate gradients with respect to that variable at that value”</p>
<div id="cell-22" class="cell">
<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"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> plot_function(f, tx<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>, ty<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>, title<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;">min</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="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;">2</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;">6</span>,<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>)):</span>
<span id="cb17-2">    x <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> torch.linspace(<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;">max</span>)</span>
<span id="cb17-3">    fig,ax <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> plt.subplots(figsize<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>figsize)</span>
<span id="cb17-4">    ax.plot(x,f(x))</span>
<span id="cb17-5">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> tx <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>: ax.set_xlabel(tx)</span>
<span id="cb17-6">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> ty <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>: ax.set_ylabel(ty)</span>
<span id="cb17-7">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> title <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>: ax.set_title(title)</span></code></pre></div>
</div>
<p>Here we pretend that the below is our <strong>loss function</strong>. Running a number through it, our <strong>weight</strong> will produce a result, an <strong>activation</strong> … in this case, our <strong>loss</strong> (which again is a value telling us how good or bad our model is; smaller = good)</p>
<div id="cell-24" class="cell" data-outputid="29366394-f913-43f9-afb6-72333886b1aa">
<div class="sourceCode cell-code" id="cb18" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb18-1">xt <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tensor(<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;">1.5</span>).requires_grad_()<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> xt</span></code></pre></div>
<div class="cell-output cell-output-display" data-execution_count="11">
<pre><code>tensor(-1.5000, requires_grad=True)</code></pre>
</div>
</div>
<div id="cell-25" class="cell" data-outputid="de2424d9-7e70-4cc5-a248-6bb890499716">
<div class="sourceCode cell-code" id="cb20" 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> f(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><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span></span>
<span id="cb20-2">loss <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> f(xt)</span>
<span id="cb20-3"></span>
<span id="cb20-4">plot_function(f, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'x'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'x**2'</span>)</span>
<span id="cb20-5">plt.scatter(xt.detach().numpy(), loss.detach().numpy(), 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;">'red'</span>)</span>
<span id="cb20-6"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Loss: '</span>, loss.item())</span></code></pre></div>
<div class="cell-output cell-output-stdout">
<pre><code>Loss:  2.25</code></pre>
</div>
<div class="cell-output cell-output-stderr">
<pre><code>/usr/local/lib/python3.7/dist-packages/ipykernel_launcher.py:2: UserWarning: Not providing a value for linspace's steps is deprecated and will throw a runtime error in a future release. This warning will appear only once per process. (Triggered internally at  /pytorch/aten/src/ATen/native/RangeFactories.cpp:23.)
  </code></pre>
</div>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://ohmeow.com/posts/2021-05-23-ajtfb-chapter-4_files/figure-html/cell-13-output-3.png" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
<p>So if our parameter is <code>-1.5</code> we get a loss = <code>2.25</code>. Since the direction of our slope is downward (negative), by changing its value to be a bit more positive, we get closer to achieving our goal of <em>minimizing our loss</em></p>
<div id="cell-27" class="cell" data-outputid="cdfc5b45-dbd6-448f-b1f8-1076b7db3dfc">
<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">xt <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tensor(<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;">1.</span>).requires_grad_()<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> xt</span>
<span id="cb23-2"></span>
<span id="cb23-3">loss <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> f(xt)</span>
<span id="cb23-4"></span>
<span id="cb23-5">plot_function(f, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'x'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'x**2'</span>)</span>
<span id="cb23-6">plt.scatter(xt.detach().numpy(), loss.detach().numpy(), 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;">'red'</span>)</span>
<span id="cb23-7"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Loss: '</span>, loss.item())</span></code></pre></div>
<div class="cell-output cell-output-stdout">
<pre><code>Loss:  1.0</code></pre>
</div>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://ohmeow.com/posts/2021-05-23-ajtfb-chapter-4_files/figure-html/cell-14-output-2.png" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
<p>And yes, our loss has improved! If the direction of our slope were upwards (positive), we would conversely want <code>x</code> to be smaller.</p>
<p><strong><em>BUT</em></strong> now … imagine having to figure all this out for a million parameters. Obviously, we wouldn’t want to try doing this manually as we did before, and thanks to PyTorch, we don’t have too :)</p>
<p>Remember that by utilizing the <code>requires_grad_()</code> function, we have told PyTorch to keep track of how to compute the gradients based on the other calucations we perform, like running it through our loss function above. Let’s see what that looks like.</p>
<div id="cell-30" class="cell" data-outputid="ac4db2fb-2de7-4ec1-c5b1-e967f1f9c14d">
<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">xt <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tensor(<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;">1.</span>).requires_grad_()<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> </span>
<span id="cb25-2"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(xt)</span>
<span id="cb25-3"></span>
<span id="cb25-4">loss <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> f(xt)</span>
<span id="cb25-5"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(loss)</span></code></pre></div>
<div class="cell-output cell-output-stdout">
<pre><code>tensor(-1., requires_grad=True)
tensor(1., grad_fn=&lt;PowBackward0&gt;)</code></pre>
</div>
</div>
<p>That <code>&lt;PowBackward0&gt;</code> is the gradient function it will use to calculate the gradients when needed. And when we need it, we call the <code>backward</code> method to do so.</p>
<div id="cell-32" class="cell" data-outputid="912bbbb2-662f-4636-dbd1-ef3935c8f808">
<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">loss.backward()</span>
<span id="cb27-2"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(xt.grad)</span></code></pre></div>
<div class="cell-output cell-output-stdout">
<pre><code>tensor(-2.)</code></pre>
</div>
</div>
<p>And the calcuated gradient is exactly what we expected given that to calculate the derivate of <code>x**2</code> is <code>2x</code> … <code>2*-1 = -2</code>.</p>
<p>Again, the gradient tells us <strong><em>the slope of our function</em></strong>. Here have a a negative/downward slope and so at the very least, we know what moving in that direction will get us closer to the minimum.</p>
<p>The question is now, <strong>How far do we move in that direction?</strong></p>
</section>
<section id="step-5-change-all-the-weights-based-on-the-gradient-using-a-learning-rate" class="level3">
<h3 class="anchored" data-anchor-id="step-5-change-all-the-weights-based-on-the-gradient-using-a-learning-rate">Step 5: Change all the weights based on the gradient using a “Learning Rate”</h3>
<p>The <strong>learning rate</strong> (or LR) is a number (usually a small number like 1e-3 or 0.1) that we multiply the gradient by to get a better parameter value. For a given parameter/weight <code>w</code>, the calculation looks like this:</p>
<p><code>w -= w.grad * lr</code></p>
<p>Notice we take the negative of the grad * lr operation because we want to move in the opposite direction.</p>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>We do this in a <code>with torch.no_grad()</code> so that we don’t calculate the gradient for the gradient calculating operation</p>
</div>
</div>
<div id="cell-35" class="cell" data-outputid="9237bae3-589e-4748-f778-e19ca3460649">
<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">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.01</span></span>
<span id="cb29-2"></span>
<span id="cb29-3"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">with</span> torch.no_grad():</span>
<span id="cb29-4"> xt <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-=</span> xt.grad <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> lr</span>
<span id="cb29-5"></span>
<span id="cb29-6"> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'New value for xt: '</span>, xt)</span>
<span id="cb29-7"> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'New loss: '</span>, f(xt))</span></code></pre></div>
<div class="cell-output cell-output-stdout">
<pre><code>New value for xt:  tensor(-0.9800, requires_grad=True)
New loss:  tensor(0.9604)</code></pre>
</div>
</div>
<p>You can see the loss get smaller which is exactly what we want! “The magnitude of the gradient (i.e., the steepness of the slope) [tells] us how big a step to take.”</p>
<p>The above operation is also called the <strong>optimization step</strong></p>
<p>See pp.156-157 for examples of what using a too small or too large LR might look like when training. This could help you troubleshoot things if yours looks wonky.</p>
</section>
</section>
<section id="datasets-dataloaders" class="level2">
<h2 class="anchored" data-anchor-id="datasets-dataloaders">Datasets &amp; DataLoaders</h2>
<p>A <strong>Dataset</strong> contains tuples of independent and dependent variables</p>
<div id="cell-39" class="cell" data-outputid="23986db7-b9a7-4fe8-d071-bd266d826eb5">
<div class="sourceCode cell-code" id="cb31" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb31-1">ds <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> L(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">enumerate</span>(string.ascii_lowercase))</span>
<span id="cb31-2">ds</span></code></pre></div>
<div class="cell-output cell-output-display" data-execution_count="17">
<pre><code>(#26) [(0, 'a'),(1, 'b'),(2, 'c'),(3, 'd'),(4, 'e'),(5, 'f'),(6, 'g'),(7, 'h'),(8, 'i'),(9, 'j')...]</code></pre>
</div>
</div>
<p>A <strong>DataLoader</strong> receives a dataset and gives us back as many <em>mini-batches</em> are necessary based on the <em>batch size</em> we specify</p>
<div id="cell-41" class="cell" data-outputid="da2e2f86-cfd1-4e37-d1db-e17b4554e21b">
<div class="sourceCode cell-code" id="cb33" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb33-1">dl <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> DataLoader(ds, 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;">6</span>, 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>
<span id="cb33-2"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>(dl)</span></code></pre></div>
<div class="cell-output cell-output-display" data-execution_count="18">
<pre><code>[(tensor([17,  5,  9, 22, 18, 21]), ('r', 'f', 'j', 'w', 's', 'v')),
 (tensor([15,  3, 23,  1,  0, 19]), ('p', 'd', 'x', 'b', 'a', 't')),
 (tensor([ 4, 10, 16, 25,  8,  2]), ('e', 'k', 'q', 'z', 'i', 'c')),
 (tensor([24, 14,  7, 20, 13, 12]), ('y', 'o', 'h', 'u', 'n', 'm')),
 (tensor([11,  6]), ('l', 'g'))]</code></pre>
</div>
</div>
</section>
<section id="measuring-distances" class="level2">
<h2 class="anchored" data-anchor-id="measuring-distances">Measuring distances</h2>
<p>See pp.141-142. There are two main ways to measure distances.</p>
<p><strong>L1 norm</strong> (or mean absolute difference): Take the mean of the absolute value of differences</p>
<p><code>l1_loss = (tensor_a - tensor_b).abs().mean()</code></p>
<p><strong>L2 norm</strong> (or root mean squared error, RMSE): Take the square root of the mean of the square differences. The squaring of differences makes everything positive and the square root undoes the squaring.</p>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>“… the latter will penalize bigger mistakes more heavily than the former (and be more lenient with small mistakes)”</p>
</div>
</div>
<p><code>l2_loss = ((tensor_a - tensor_b) ** 2).sqrt()</code></p>
</section>
<section id="important-pytorch-modules" class="level2">
<h2 class="anchored" data-anchor-id="important-pytorch-modules">Important PyTorch Modules</h2>
<p>A <strong>module</strong> is a class that inherits from PyTorch’s <code>nn.Module</code> class. “Every PyTorch module knows that <strong>parameters</strong> it has that can be trained.”</p>
<p>Here are some key ones …</p>
<section id="nn.linear" class="level3">
<h3 class="anchored" data-anchor-id="nn.linear"><code>nn.Linear</code></h3>
<p>Initializes its parameters and performs a linear operation. It contains both the weights and biases in a single class</p>
<div id="cell-45" class="cell" data-outputid="ad3a236a-c759-4142-a815-167d1a55f02c">
<div class="sourceCode cell-code" id="cb35" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb35-1">lin1 <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;">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 class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb35-2"></span>
<span id="cb35-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># the trainable parameters</span></span>
<span id="cb35-4">weights, bias <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> lin1.parameters()</span>
<span id="cb35-5"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(weights.shape, bias.shape)</span></code></pre></div>
<div class="cell-output cell-output-stdout">
<pre><code>torch.Size([1, 784]) torch.Size([1])</code></pre>
</div>
</div>
</section>
<section id="nn.relu" class="level3">
<h3 class="anchored" data-anchor-id="nn.relu"><code>nn.ReLU</code></h3>
<p>Allows us to add a non-linearity between linear classifiers. Simply put, it ensures that all activations passed to it are a positive number with every negative number replaced with a 0.</p>
<p>Notice below that it has no trainable parameters!</p>
<div id="cell-47" class="cell" data-outputid="03887384-7944-4094-b567-82977c05544f">
<div class="sourceCode cell-code" id="cb37" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb37-1">plot_function(F.relu)</span></code></pre></div>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://ohmeow.com/posts/2021-05-23-ajtfb-chapter-4_files/figure-html/cell-21-output-1.png" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
<div id="cell-48" class="cell" data-outputid="d16af357-b5a4-418a-8d1c-d895cc1134fa">
<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">non_lin1 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> nn.ReLU()</span>
<span id="cb38-2"><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;">list</span>(non_lin1.parameters()))</span>
<span id="cb38-3"></span>
<span id="cb38-4"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'using nn.ReLU: '</span>, non_lin1(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;">1</span>)), non_lin1(tensor(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>)))</span>
<span id="cb38-5"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'using 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;">1</span>).<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">max</span>(tensor(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.0</span>)), tensor(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>).<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">max</span>(tensor(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.0</span>)))</span></code></pre></div>
<div class="cell-output cell-output-stdout">
<pre><code>[]
using nn.ReLU:  tensor(0) tensor(4)
using max() tensor(0.) tensor(4.)</code></pre>
</div>
</div>
<p><strong>Why do you want to have non-linearities?</strong></p>
<blockquote class="blockquote">
<p>Because “there’s no point in just putting one linear layout directly after another one, because when we multiply things together and then add them up multiple times, that could be replaced by multiplying different things together and adding them up just once …. BUT if we put a non-linear between them … this is no longer true. <strong><em>Now each linear layer is somewhat decoupled from the other ones and can do its own useful work</em></strong>.”</p>
</blockquote>
<p>These kind of functions are also called <strong>“activation functions”</strong>, because the only operate and produce activations … there are no trainable parameters.</p>
</section>
<section id="nn.sequential" class="level3">
<h3 class="anchored" data-anchor-id="nn.sequential"><code>nn.Sequential</code></h3>
<p>A module that can be passed modules, which when called, calls each of those layers in turn.</p>
<div id="cell-51" class="cell" data-outputid="9f6f0d69-49ea-4939-9cf2-6e91cc431d12">
<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">lin2 <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;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span>)</span>
<span id="cb40-2">seq_model <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> nn.Sequential(lin1, non_lin1, lin2)</span>
<span id="cb40-3"></span>
<span id="cb40-4">seq_params <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>(seq_model.parameters())</span>
<span id="cb40-5"><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;">len</span>(seq_params))</span>
<span id="cb40-6"></span>
<span id="cb40-7"><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> seq_params: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(p.shape)</span></code></pre></div>
<div class="cell-output cell-output-stdout">
<pre><code>4
torch.Size([1, 784])
torch.Size([1])
torch.Size([10, 1])
torch.Size([10])</code></pre>
</div>
</div>
<p>Why <code>4</code>? Simple, remember that each <code>nn.Linear</code> above has two trainable parameters (the weights and bias), 2+2 = 4.</p>
</section>
</section>
<section id="summary" class="level2">
<h2 class="anchored" data-anchor-id="summary">Summary</h2>
<p>This chapter walks you through creating a baseline model to a full blown training loop in PyTorch. <strong><em>Read it, and read it again and again!</em></strong> (I do and have).</p>
<p><strong>Important Vocb/Concepts</strong></p>
<p><em>Activations</em>: Numbers that are calculated by both linear and non-linear layers</p>
<p><em>Parameters</em>: Randomly initialized parameters that can be trained.</p>
<p><em>Neural Network</em>: A chain of linear and non-linear functions your data runs through to produce a result.</p>
<p><em>Gradient</em>: “The derivative of the loss with respect to some parameter of the model”</p>
<p><em>Backpropagation</em>: The computing of the gradients “of the loss with respect to all model parameters”</p>
<p><em>Gradient Descent</em>: “Taking a step in the direction opposite to the gradients to make the model parameters a little bit better”</p>
</section>
<section id="resources" class="level2">
<h2 class="anchored" data-anchor-id="resources">Resources</h2>
<ol type="1">
<li>https://book.fast.ai - The book’s website; it’s updated regularly with new content and recommendations from everything to GPUs to use, how to run things locally and on the cloud, etc…</li>
</ol>


</section>

 ]]></description>
  <category>fastai</category>
  <category>fastbook</category>
  <guid>https://ohmeow.com/posts/2021-05-23-ajtfb-chapter-4.html</guid>
  <pubDate>Sun, 23 May 2021 07:00:00 GMT</pubDate>
  <media:content url="https://ohmeow.com/posts/images/fastbook.jpg" medium="image" type="image/jpeg"/>
</item>
<item>
  <title>A Journey Through Fastbook (AJTFB) - Chapter 3: Data Ethics</title>
  <dc:creator>Wayde Gilliam</dc:creator>
  <link>https://ohmeow.com/posts/2020-11-22-ajtfb-chapter-3.html</link>
  <description><![CDATA[ 




<p>Other posts in this series:</p>
<p><a href="../posts/2020-11-06-ajtfb-chapter-1.html">A Journey Through Fastbook (AJTFB) - Chapter 1</a><br>
<a href="../posts/2020-11-16-ajtfb-chapter-2.html">A Journey Through Fastbook (AJTFB) - Chapter 2</a><br>
<a href="../posts/2021-05-23-ajtfb-chapter-4.html">A Journey Through Fastbook (AJTFB) - Chapter 4</a><br>
<a href="../posts/2021-06-03-ajtfb-chapter-5.html">A Journey Through Fastbook (AJTFB) - Chapter 5</a><br>
<a href="../posts/2021-06-10-ajtfb-chapter-6-multilabel.html">A Journey Through Fastbook (AJTFB) - Chapter 6a</a><br>
<a href="../posts/2022-02-09-ajtfb-chapter-6-regression.html">A Journey Through Fastbook (AJTFB) - Chapter 6b</a><br>
<a href="../posts/2022-03-28-ajtfb-chapter-7.html">A Journey Through Fastbook (AJTFB) - Chapter 7</a><br>
<a href="../posts/2022-03-31-ajtfb-chapter-8.html">A Journey Through Fastbook (AJTFB) - Chapter 8</a><br>
<a href="../posts/2022-04-25-ajtfb-chapter-9.html">A Journey Through Fastbook (AJTFB) - Chapter 9</a></p>
<section id="data-ethics" class="level2">
<h2 class="anchored" data-anchor-id="data-ethics">Data Ethics</h2>
<blockquote class="blockquote">
<p>… sometimes machine learning models can go wrong. They can have bugs. They can be presented with data that they haven’t seen before and behave in ways we don’t expect. Or … they can be used for something that we would much prefer they were never, ever used for.</p>
</blockquote>
<blockquote class="blockquote">
<p>… no one really agrees on what right and wrong are, whether they exist, how to spot them, which people are good and which bad, or pretty much anything else.</p>
</blockquote>
<p>If anything, this is a call to humility, self-examination, and thoughtful dialog. Though we are increasingly living in a polarized world where one is judged by what particular slogans they choose, what party they belong too, who they follow on Facebook, and so on, we have the choice to not be such human beings. But in my experience that is easier said than done. It’s too easy to shout at, rather than talk with, the “other” side because we can in blissful ignorance continue believing we got it right without ever being challenged. It’s hard to really reason out our world views and argue with those who don’t agree. If we did, we have find we have more in common that imagined and make further progress as a society into figuring these things out … things like right and wrong, good and evil, justice and injustice, and how we can get along with each other despite our differences.</p>
<p><strong><em>The point of this chapter is simple: The goal of ML isn’t to find the model with the lowest loss … it is to build a model that drives the right kind of actions</em></strong></p>
</section>
<section id="recourse-and-accountability" class="level2">
<h2 class="anchored" data-anchor-id="recourse-and-accountability">Recourse and accountability</h2>
<blockquote class="blockquote">
<p>In a complex system, it is easy for no one person to feel responsible for outcomes.</p>
</blockquote>
<p>As deep learning practioniers, we have better insight than most into what kind of actions will be made as a result of our model’s results. Therefore, if we care about people in general, we’ll care about those outcomes as much as our model’s validation loss.</p>
</section>
<section id="feedback-loops" class="level2">
<h2 class="anchored" data-anchor-id="feedback-loops">Feedback Loops</h2>
<blockquote class="blockquote">
<p>Feedback loops can occur when your model is controlling the next round of data you get.</p>
</blockquote>
<blockquote class="blockquote">
<p>… an algorithm can interact with its environment to create a feedback loop, making predictions that reinforce actions taken in the real world, which lead to predictions even more pronounced in the same direction.</p>
</blockquote>
<blockquote class="blockquote">
<p>Part of the problem here is the centrality of metrics in driving a financially important system.</p>
</blockquote>
<p>See the “Meetup” example on p.105</p>
<blockquote class="blockquote">
<p>Once people join a single conspiracy-minded [Facebook] group, they are algorithmically routed to a plethora of others. Join an anti-vaccine group, and your suggestions will include anit-GMO, chemtrail watch, falt Earther (yes, really), and “curing cancer naturallay” groups. Rather than pulling a user out of the rabbit hole, the recommendation engine pushes them farther in.</p>
</blockquote>
<p>FYI, I think most social media has a net-negative effect on us as humain beings. In particular, I try to avoid Facebook, Instagram, TikTok, and Snapchat while doing my best to limit my only social media account, a Twitter account, to things relevant to data science and public health (and that ain’t easy).</p>
</section>
<section id="bias" class="level2">
<h2 class="anchored" data-anchor-id="bias">Bias</h2>
<p>There are different kinds of “data ethics” bias, here are 4 types:</p>
<section id="historical-bias" class="level3">
<h3 class="anchored" data-anchor-id="historical-bias">Historical Bias</h3>
<blockquote class="blockquote">
<p>… comes from the fact that people are biased, processes are biased, and society is biased. [It] is a fundamental, structural issue with the first step of data generation process and can exist even given perfect sampling and feature selection.</p>
</blockquote>
<blockquote class="blockquote">
<p>Any dataset involving human can have this kind of bias: medical data, sales data, housing data, political data, and so on.</p>
</blockquote>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>Maybe the best way to understand historical biase in your dataset is by spending time looking at both the outcomes and how they might be used???</p>
</div>
</div>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>Make sure your data is representative of what your model will see and to evaluate any automatic “labeling” features in your system. (see gorillas example on pp.107-108).</p>
</div>
</div>
<blockquote class="blockquote">
<p>So what this showed is that the developers failed to utilize datasets containing enough darker faces, or test their product with darker faces.</p>
</blockquote>
<p>A good reminder that your model will only be as good as the data you trained it on! Sound familiar?</p>
<blockquote class="blockquote">
<p>… the vast majority of AI researches and developers are young white men. Most projects that we have seen do most user testing using friends and families of the immediate product development group. Given this, the kinds of problems we just discussed should not be suprising.</p>
</blockquote>
<p>I think at the very least, we need to be forthright about our dataset as much as on model performance. That way, expectations can be managed and a confidence level assigned to the results. A threshold perhaps that could trigger human intervention.</p>
</section>
<section id="measurement-bias" class="level3">
<h3 class="anchored" data-anchor-id="measurement-bias">Measurement bias</h3>
<blockquote class="blockquote">
<p>… occurs when our models make mistakes because we are measuring the wrong thing, or measuring it the wrong way, or incorporating that measurement into the model inappropriately.</p>
</blockquote>
<p>Not sure why, but this is perhaps the most insidious bias because I think its the hardest to figure out.</p>
</section>
<section id="aggregation-bias" class="level3">
<h3 class="anchored" data-anchor-id="aggregation-bias">Aggregation bias</h3>
<blockquote class="blockquote">
<p>… occurs when models do not aggregate data in a way that incorporates all of the appropriate factors, or when a model does not include the necessary interaction terms, nonlineraities, or so forth.</p>
</blockquote>
<p>These are features that are not included though they would actually improve model performance if they were.</p>
</section>
<section id="representation-bias" class="level3">
<h3 class="anchored" data-anchor-id="representation-bias">Representation bias</h3>
<blockquote class="blockquote">
<p>When there is a clear, easy-to-see underlying relationship, a simple model will often assume that this relationship holds all the time.</p>
</blockquote>
<p>Essentially models can see this real imbalance and make it bigger than it is.</p>
</section>
</section>
<section id="disinformation" class="level2">
<h2 class="anchored" data-anchor-id="disinformation">Disinformation</h2>
<blockquote class="blockquote">
<p>It is not necessarily about getting someone to belive something false, but rather often used to sow disharmony and uncertainty, and to get people to give up on seeking the truth. Receiving conflicting accounts can lead people to assume that they can never know whom or what to trust.</p>
</blockquote>
<p>Disinformation will unfotunately be one of the greatest legacies of President Trump. A step backwards for American society. A culture that will back if you if you tell them what they want to hear, even if you’re a compulsive liar and base your statements on “gut feel” rather than facts and logic.</p>
<blockquote class="blockquote">
<p>While most of us like to think of ourselves as independent-minded, in reality we evolved to be influenced by others in our in-group, and in opposition to those in our out-group. Online discussions can influence our viewpoints, or alter the range of what we consider acceptable viewpoints. Humans are social animals, and as social animals, we are extremely influenced by the people around us. Increasingly, radicalization occurs in online environments; so influence is coming from people in the virtual space of online forums and social networks.</p>
</blockquote>
<p>The biggest take here is that I am not as independently minded as I think I am. Knowing thyself is perhaps the best preventative of being swallowed up by disinformation. Limiting social media is another.</p>
<blockquote class="blockquote">
<p>Disinformation through autogenerated text is a particularly significant issue</p>
</blockquote>
<p>As an NLP guy, this one scares me since part of my work is to summarize text. Knowing this, the first step I’ve taken is to let all business owners know the risk of text generation algorithms generating text that is either false and/or not necessarily reflective of the inputs, as in the case of abstract summarization. The second step I took was to introduce human beings into the process and a workflow that has them look at at least the most potentially wrong summarizations before reports go out.</p>
</section>
<section id="what-to-do" class="level2">
<h2 class="anchored" data-anchor-id="what-to-do">What to do???</h2>
<blockquote class="blockquote">
<p>You must assume that any personal data that Facebook or Android keeps are data that governments around the world will try to get or that thieves will try to steal.</p>
</blockquote>
<p>Data use and storage are things you need to think about.</p>
<p>I think these are good questions to ask/answer in any project to ensure good outcomes:</p>
<blockquote class="blockquote">
<ul>
<li>Whose interests, desires, skills, experiences, and values have we simply assumed rather than actually consulted?</li>
<li>Who are all the stakeholders who will be directly affected by our product? How have their interests been protected? How do we know what their interests really are - have we asked?</li>
<li>Whowhich groups and individuals will be indirectly affected in signficant ways?</li>
<li>Who might use this product that we didn’t expect to use it, or for purposes we didn’t initially intend?</li>
</ul>
</blockquote>
<p>See pp.119-120 for a bunch of good questions to put into your practice!</p>
<blockquote class="blockquote">
<p>When everybody on a team has similar backgrounds, they are likely to have similar blind spots around ethical tasks.</p>
</blockquote>
<blockquote class="blockquote">
<p>… first come up with a process, definition, set of questions etc., which is designed to resolve a problem. Then try to come up with an example in which the apparent solution results in a proposal that no one would consider acceptable. This can then lead to further refinement of the solution.</p>
</blockquote>
<p>Thinking about all these things may lead one to analysis paralysis or even worse, complete apathy. We need to start with something and be okay with criticism and refactoring. Additionally, we need to be thoughtful in even spot on criticism of others’ systems. I don’t think most folks try to make something racist or mysoginistic or whatever, so instead of calling them a “Hitler” on Twitter when we taste something that looks to us like fasicism, maybe a phone call and one-on-one chat is the better and more productive move.</p>
</section>
<section id="resources" class="level2">
<h2 class="anchored" data-anchor-id="resources">Resources</h2>
<ol type="1">
<li><p>https://book.fast.ai - The book’s website; it’s updated regularly with new content and recommendations from everything to GPUs to use, how to run things locally and on the cloud, etc…</p></li>
<li><p>https://forums.fast.ai/c/data-ethics/47 - Forum subcategory for all things “data ethics”.</p></li>
</ol>


</section>

 ]]></description>
  <category>fastai</category>
  <category>fastbook</category>
  <guid>https://ohmeow.com/posts/2020-11-22-ajtfb-chapter-3.html</guid>
  <pubDate>Sun, 22 Nov 2020 08:00:00 GMT</pubDate>
  <media:content url="https://ohmeow.com/posts/images/fastbook.jpg" medium="image" type="image/jpeg"/>
</item>
<item>
  <title>A Journey Through Fastbook (AJTFB) - Chapter 2: Doing Deep Learning</title>
  <dc:creator>Wayde Gilliam</dc:creator>
  <link>https://ohmeow.com/posts/2020-11-16-ajtfb-chapter-2.html</link>
  <description><![CDATA[ 




<div id="cell-2" class="cell">
<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="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> PIL</span>
<span id="cb1-2"></span>
<span id="cb1-3"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> fastai.data.<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="cb1-4"><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></code></pre></div>
</div>
<p>Other posts in this series:</p>
<p><a href="../posts/2020-11-06-ajtfb-chapter-1.html">A Journey Through Fastbook (AJTFB) - Chapter 1</a><br>
<a href="../posts/2020-11-22-ajtfb-chapter-3.html">A Journey Through Fastbook (AJTFB) - Chapter 3</a><br>
<a href="../posts/2021-05-23-ajtfb-chapter-4.html">A Journey Through Fastbook (AJTFB) - Chapter 4</a><br>
<a href="../posts/2021-06-03-ajtfb-chapter-5.html">A Journey Through Fastbook (AJTFB) - Chapter 5</a><br>
<a href="../posts/2021-06-10-ajtfb-chapter-6-multilabel.html">A Journey Through Fastbook (AJTFB) - Chapter 6a</a><br>
<a href="../posts/2022-02-09-ajtfb-chapter-6-regression.html">A Journey Through Fastbook (AJTFB) - Chapter 6b</a><br>
<a href="../posts/2022-03-28-ajtfb-chapter-7.html">A Journey Through Fastbook (AJTFB) - Chapter 7</a><br>
<a href="../posts/2022-03-31-ajtfb-chapter-8.html">A Journey Through Fastbook (AJTFB) - Chapter 8</a><br>
<a href="../posts/2022-04-25-ajtfb-chapter-9.html">A Journey Through Fastbook (AJTFB) - Chapter 9</a></p>
<section id="starting-your-project" class="level2">
<h2 class="anchored" data-anchor-id="starting-your-project">Starting Your Project</h2>
<section id="things-to-think-about-when-deciding-on-project-feasibility" class="level3">
<h3 class="anchored" data-anchor-id="things-to-think-about-when-deciding-on-project-feasibility">Things to think about when deciding on project feasibility</h3>
<p>“When selecting a project, the most important consideration is data availability.” If you don’t have enough quality data … good luck :)</p>
<div class="callout callout-style-default callout-tip 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">
Tip
</div>
</div>
<div class="callout-body-container callout-body">
<p>Consider that <strong>data augmentation</strong> can alleviate both the need for more manual labelling and also protect you from problems with <em>out-of-domain</em> data (e.g.&nbsp;when unexpected image types arise in the data when the model is being used in production) by synthetically creating more data likely to be seen that may not be in your dataset as is.</p>
</div>
</div>
<div class="callout callout-style-default 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">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>“… iterate from end to end in your project; don’t spend months fine-tuning your model, or polishing the perfect GUI, or labeling the perfect dataset”</p>
</div>
</div>
<p>This is good advice for <em>any</em> software project …<strong><em>fail early and fail often</em></strong>. If you don’t, you’re likely to only uncover critical problems much later than you would have before, and even worse, you’re likely to not produce anything at all! In the world of deep learning there are a number of tools, that while helpful, can really get you so bogged down that you never deploy something usable (e.g., experiment tracking tools, hyperparameter optimization libraries, etc…).</p>
<p>Also, remember that getting something in production is a different task from winning a kaggle competition, where the later may require use of some of those aforementioned tools and the ensembling of dozens of models. <strong><em>For production, something better than human is often good enough to get out there and through refactoring, improve.</em></strong></p>
</section>
</section>
<section id="the-drivetrain-approach" class="level2">
<h2 class="anchored" data-anchor-id="the-drivetrain-approach">The Drivetrain Approach</h2>
<p><img src="https://ohmeow.com/posts/images/drivetrain-approach.png" class="img-fluid"></p>
<section id="four-steps" class="level3">
<h3 class="anchored" data-anchor-id="four-steps">Four Steps</h3>
<section id="step-1-define-your-objectives" class="level4">
<h4 class="anchored" data-anchor-id="step-1-define-your-objectives">Step 1: Define your objective(s)</h4>
<p>It’s amazing how in my 20+ years as a developer, how rare it is that a customer is able to clearly define what they want! In my experience, more than not, it is the developers that end up defining the goals. Not having a clear objective is likely to waste time, energy, and money to produce something that won’t even see the light of day. <strong><em>You can’t gauge the completion or quality of any software project without clear objective(s).</em></strong></p>
<p>Ex.1: Show most relevant search results.<br>
Ex.2: Drive additional sales by recommending to customers items to purchase they otherwise wouldn’t</p>
</section>
<section id="step-2-what-actions-can-you-take-to-achieve-those-objectives" class="level4">
<h4 class="anchored" data-anchor-id="step-2-what-actions-can-you-take-to-achieve-those-objectives">Step 2: What actions can you take to achieve those objective(s)?</h4>
<p>What things can make your goals a reality. Pretty simple.</p>
<p>Ex.1: Ranking the search results will help show the most relevants ones first.<br>
Ex.2: Ranking the recommendations will help.</p>
</section>
<section id="step-3-what-data-is-needed-to-take-those-actions" class="level4">
<h4 class="anchored" data-anchor-id="step-3-what-data-is-needed-to-take-those-actions">Step 3: What data is needed to take those actions?</h4>
<p>If you don’t have the data, you’ll need to get it … because the data pulls the levers which get you closer to your objective(s).</p>
<p>Ex.1: Seeing what how pages linked to other pages.<br>
Ex.2: Collecting data on what customers purchased, what was recommended, and what they did with that info.</p>
</section>
<section id="step-4-build-models" class="level4">
<h4 class="anchored" data-anchor-id="step-4-build-models">Step 4: Build models</h4>
<p>Only once you have the data and know what actions you want to be able to take based on the information within it, do you being modeling … first, defining what models you can even build with that data and second, what data you need to collect for models you can’t.</p>
<p>Ex.1: A model that takes the page relation data and predicts a ranking given a query.<br>
Ex.2: Two models that predict the purchasing proabilities conditional on seeing or not seeing a recommendation.</p>
</section>
</section>
</section>
<section id="how-to-avoid-disaster" class="level2">
<h2 class="anchored" data-anchor-id="how-to-avoid-disaster">How to Avoid Disaster</h2>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>Your model is only as good as the data it was trained on</p>
</div>
</div>
<p>Two problems to watch out for:</p>
<ol type="1">
<li><strong>out-of-domain data</strong>: “data that our model sees in production that is very different to what it saw during training.</li>
<li><strong>domain shift</strong>: “whereby the type of data that our model sees changes over time.”</li>
</ol>
<p>Mitigation steps:</p>
<p><img src="https://raw.githubusercontent.com/ohmeow/ohmeow_website/master/images/articles/avoid-disaster-steps.png" class="img-fluid"></p>
<p>“Where possible, the <strong>first step</strong> is to use an entirely manual process with your model running in parallel and not being used to directly drive any actions.”</p>
<p>“The <strong>second step</strong> is to try and limit the scope of the model.”</p>
<p>“The <strong>third step</strong> is to gradually increase the scope of your rollout.”</p>
<div class="callout callout-style-default callout-tip 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">
Tip
</div>
</div>
<div class="callout-body-container callout-body">
<p>“Try to think about all the ways in which your system could go wrong, and then think about what measure or report or picture could reflect that problem, and ensure that your regular reporting includes that information.”</p>
</div>
</div>
<div class="callout callout-style-default 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">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>Defining good validation and tests sets are part of the solution. See my “<a href="https://ohmeow.com/what-is/training-validation-test-sets#How-to-create-good-validation-and-test-sets">How to create good validation and test sets</a>” for more details.</p>
</div>
</div>
</section>
<section id="getting-help" class="level2">
<h2 class="anchored" data-anchor-id="getting-help">Getting help</h2>
<p>A few of ways …</p>
<div id="cell-8" class="cell">
<div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb2-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># method signature only</span></span>
<span id="cb2-2">download_images?</span></code></pre></div>
</div>
<div id="cell-9" class="cell">
<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="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># full source of method</span></span>
<span id="cb3-2">download_images??</span></code></pre></div>
</div>
<div id="cell-10" class="cell">
<div class="sourceCode cell-code" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb4-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># get link to fastai docs</span></span>
<span id="cb4-2">doc(download_images)</span></code></pre></div>
</div>
<p>You can also use <code>pdb.set_trace</code> (in code) or <code>%debug</code>(in a new cell following the one with the error) to step through your code. I use the former all the time … its a great way to debug and also learn what the code is doing and why. For example, I use it to look at the shape of things as the travel through and out of different layers in my NNs.</p>
<div id="cell-12" class="cell">
<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="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> pdb</span>
<span id="cb5-2"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> div_by_zero():</span>
<span id="cb5-3">  pdb.set_trace()</span>
<span id="cb5-4">  x <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><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span></span>
<span id="cb5-5">  <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'here'</span>)</span>
<span id="cb5-6"></span>
<span id="cb5-7"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># uncomment this to see what I'm talking about ...</span></span>
<span id="cb5-8"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># div_by_zero()</span></span></code></pre></div>
</div>
</section>
<section id="getting-and-cleaning-your-images" class="level2">
<h2 class="anchored" data-anchor-id="getting-and-cleaning-your-images">Getting and cleaning your images</h2>
<ol type="1">
<li>Use <code>download_images</code> listed as URLs in a text file <code>urls</code> to download the actual images locally.<br>
</li>
<li>Get the file path to the images via <code>get_image_files</code> in an <code>L</code> object.<br>
</li>
<li>Get rid of the corrupt images using <code>verify_images</code> and <code>Path.unlink</code>.</li>
</ol>
<pre><code>path = Path('bears/grizzly')
download_images(path, urls=image_urls.txt)

file_paths = get_image_files(path)
failed = verify_images(file_paths)
failed.map(Path.unlink)</code></pre>
<p>Notice how <code>L</code>’s <code>map</code> method is used to apply the <code>Path.unlink</code> function to each item in-place.</p>
</section>
<section id="datablock-api-basics" class="level2">
<h2 class="anchored" data-anchor-id="datablock-api-basics">DataBlock API Basics</h2>
<p>The <strong>DataBlock API</strong> represents fastai’s high-level approach for building <strong>DataLoaders</strong> from your raw data sources. It is a reusable blueprint for how data is used both during model training and at inference time, and along with the fastai callback system, it represents one of the core pieces of the fastai framework.</p>
<p>“<strong>… a <code>DataBlock object</code> … is like a template for creating a <code>DataLoaders</code> object</strong>”</p>
<p>“A <code>DataLoader</code> is a class that provides batches of a few items at a time to the GPU”</p>
<section id="defining-your-blueprint-using-the-datablock-api" class="level3">
<h3 class="anchored" data-anchor-id="defining-your-blueprint-using-the-datablock-api">Defining your “blueprint” using the DataBlock API</h3>
<p>There are <strong>four</strong> things you need to specify to make your data usable for training (e.g., to build at minimum a training and validation <code>DataLoader</code>).</p>
<ol type="1">
<li>What <strong>kind of data</strong> you are working with</li>
<li>How to <strong>get</strong> the data</li>
<li>How to <strong>label</strong> the data</li>
<li>How to <strong>create a validation set</strong></li>
</ol>
<p>Here’s an example of how this is done with the <code>DataBlock API</code>:</p>
<pre><code>d_block = DataBlock(
  blocks=(ImageBlock, CategoryBlock),              #=&gt; our independent and dependent variable datatypes
  get_items=get_image_files,                       #=&gt; how to get our data
  splitter=RandomSplitter(valid_pct=0.2, seed=42), #=&gt; how to create the validation set
  get_y=parent_label,                              #=&gt; how to label our data
  item_tfms=Resize(128))                           #=&gt; code that runs against each item as it is fetched</code></pre>
<div class="callout callout-style-default callout-tip 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">
Tip
</div>
</div>
<div class="callout-body-container callout-body">
<p>Use the <code>seed</code> argument to ensure you get the same training/validation set each time you run that code; else you won’t be able to know if, as you change hyperparameter values, your model performance changed because of those values and/or because of difference in your training/validation sets!</p>
</div>
</div>
<div class="callout callout-style-default 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">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>To ensure reproducibility in your fastai training, follow the tips/tricks laid out in the <a href="https://forums.fast.ai/t/solved-reproducibility-where-is-the-randomness-coming-in/31628">Reproducibility: Where is the randomness coming in?</a> forum post.</p>
</div>
</div>
</section>
<section id="using-your-blueprint-to-build-your-dataloaders" class="level3">
<h3 class="anchored" data-anchor-id="using-your-blueprint-to-build-your-dataloaders">Using your “blueprint” to build your <code>DataLoaders</code></h3>
<p>Once you’ve defined your blueprint for how to get your modelable data (i.e., your <code>DataLoaders</code>), you need to pass it the “actual source” of your data, which can be a path or a DataFrame or whatever.</p>
<pre><code>dls = d_block.dataloaders(path)</code></pre>
<div class="callout callout-style-default 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">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>Use <code>dls.show_batch(...)</code> or <code>dls.valid.show_batch(...)</code> to visualize your training/validation data.</p>
</div>
</div>
</section>
</section>
<section id="transforms" class="level2">
<h2 class="anchored" data-anchor-id="transforms">Transforms</h2>
<p>The DataBlock API relies heavily on the use of fastai <strong>transforms</strong>. They are used in the <code>blocks</code> you see above as well as inline, as you’ll see below.</p>
<section id="what-is-a-transform" class="level3">
<h3 class="anchored" data-anchor-id="what-is-a-transform">What is a “Transform”?</h3>
<p>A <strong><em>Transform</em></strong> contains code that is applied automatically during training.</p>
</section>
<section id="what-kinds-of-transforms-are-there" class="level3">
<h3 class="anchored" data-anchor-id="what-kinds-of-transforms-are-there">What kinds of transforms are there?</h3>
<p>There are <strong>two</strong> kinds of transforms:</p>
<p><strong>Item Transforms</strong>: Applied to each individual item in your dataset, they are applied to an item from your dataset when it is fetched.</p>
<div class="callout callout-style-default 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">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>Use the <code>item_tfms</code> argument to define your batch transforms. It is more technically correct to think of them as your <em>after batch</em> transforms since that is whey they are applied</p>
</div>
</div>
<p><strong>Batch Transforms</strong>: Applied to a <em>batch of items</em> using the GPU, they are applied to a collection of items on the GPU <em>after</em> they have been collated into the same shape.</p>
<div class="callout callout-style-default 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">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>Use the <code>batch_tfms</code> argument to define your batch transforms. It is more technically correct to think of them as your <em>after batch</em> transforms since that is whey they are applied</p>
</div>
</div>
<p>An example:</p>
<pre><code>d_block = d_block.new(item_tfms=RandomResizedCrop(128, min_scale=0.3), batch_tfms=aug_transforms(mult=2))</code></pre>
<div class="callout callout-style-default 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">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p><code>aug_transforms</code> are “a standard set of augmentations that we have found work pretty well”</p>
</div>
</div>
</section>
<section id="when-should-i-use-an-item-transform" class="level3">
<h3 class="anchored" data-anchor-id="when-should-i-use-an-item-transform">When should I use an <strong>item transform</strong>?</h3>
<p>TODO</p>
</section>
<section id="when-should-i-use-a-batch-transform" class="level3">
<h3 class="anchored" data-anchor-id="when-should-i-use-a-batch-transform">When should I use a <strong>batch transform</strong>?</h3>
<section id="data-augmentation" class="level4">
<h4 class="anchored" data-anchor-id="data-augmentation">Data augmentation</h4>
<p><strong>Data augmentation</strong> transorms (e.g., rotation, flipping, perspective warping, brightness changes, contrast changes, etc…) are defined as <strong>batch transforms</strong> and run on the GPU.</p>
</section>
</section>
<section id="tips-tricks" class="level3">
<h3 class="anchored" data-anchor-id="tips-tricks">Tips &amp; Tricks</h3>
<section id="changing-your-transforms-without-having-to-redefine-your-datablock-from-scratch" class="level4">
<h4 class="anchored" data-anchor-id="changing-your-transforms-without-having-to-redefine-your-datablock-from-scratch">1. Changing your transforms without having to redefine your DataBlock from scratch</h4>
<p>You can change the transforms in your DataBlock by reusing an existing DataBlock via <code>d_block.new</code>.</p>
<div class="sourceCode" id="cb10" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb10-1">d_block <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> d_block.new(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;">128</span>, ResizeMethod.squish))</span>
<span id="cb10-2">dls <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> d_block.dataloaders(path)</span>
<span id="cb10-3">...</span>
<span id="cb10-4">d_block <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> d_block.new(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;">128</span>, ResizeMethod.Pad, pad_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;">'zeroes'</span>))</span>
<span id="cb10-5">dls <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> d_block.dataloaders(path)</span>
<span id="cb10-6">...</span></code></pre></div>
</section>
</section>
</section>
<section id="how-to-train-an-image-classification-model-with-the-high-level-api" class="level2">
<h2 class="anchored" data-anchor-id="how-to-train-an-image-classification-model-with-the-high-level-api">How to train an image classification model with the high-level API</h2>
<section id="step-1-get-your-data" class="level3">
<h3 class="anchored" data-anchor-id="step-1-get-your-data">Step 1: Get your data</h3>
<p>We can grab all kinda of useful datasets via the <a href="https://course.fast.ai/datasets">fast.ai Datasets</a> for various tasks and data types (e.g., images, text, etc…). In this example we’ll work with the <code>Imagnette</code> dataset, a “subset of 10 easily classified classes from Imagenet.”</p>
<div class="callout callout-style-default callout-tip 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">
Tip
</div>
</div>
<div class="callout-body-container callout-body">
<p>Working with a representative subset of your full dataset is recommended for experimentation and as a means to verify your data prep and model training.</p>
</div>
</div>
<p>We’ll use <code>untar_data</code> to both download and decompress the dataset. It will return a <code>Pathlib</code> object pointing to where the data has been downloaded</p>
<div id="cell-18" class="cell">
<div class="sourceCode cell-code" id="cb11" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb11-1">raw_data_path <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> untar_data(URLs.IMAGENETTE)</span>
<span id="cb11-2"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(raw_data_path)</span>
<span id="cb11-3">raw_data_path.ls()</span></code></pre></div>
</div>
<p>We can use <code>get_image_files()</code> to grab all the image filepaths in the training set. This method takes a path as an argument and recursively grabs all the images in that path by default.</p>
<p>We’ll need to know how to infer the class for each image and this can be done by looking at one or more of the actual image filepaths.</p>
<div id="cell-20" class="cell">
<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">files <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> get_image_files(raw_data_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;">'train'</span>)</span></code></pre></div>
</div>
<div id="cell-21" class="cell">
<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">files[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>]</span></code></pre></div>
</div>
<p>Here we can see that the convention followed for this dataset is having the class Id we want to predict in its parent folder, while each image’s unique name is the class_id followed by a unique identifier: <code>{class_id}/{class_id}_{unique_id}.JPEG</code>.</p>
<p>We can validate this by ensure we see 10 parent folders …</p>
<div id="cell-23" class="cell">
<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">(raw_data_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;">'train'</span>).ls()</span></code></pre></div>
</div>
<p>We can even look at one or more of the images using the <code>PIL</code> package</p>
<div id="cell-25" class="cell">
<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">img <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> PIL.Image.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">open</span>(files[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>])</span>
<span id="cb15-2">img</span></code></pre></div>
</div>
</section>
<section id="step-2-build-your-datablock" class="level3">
<h3 class="anchored" data-anchor-id="step-2-build-your-datablock">Step 2: Build your <code>DataBlock</code></h3>
<p>The objective here is to ultimately be able to build <code>DataLoaders</code> you can feed into your model. There are a variety of ways to do this but the recommended go to is to use the mid-level <code>DataBlock API</code> if you can. A <code>DataBlock</code> represents a blueprint for building <code>DataLoaders</code> from your raw data, whereas the <code>DataLoaders</code> are what allow us to feed our examples into our model a mini-batch (a few) at a time.</p>
<div id="cell-27" class="cell">
<div class="sourceCode cell-code" id="cb16" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb16-1">dblock <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> DataBlock(</span>
<span id="cb16-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;"># tell the block what are INPUTS/TARGETS are (images and a category/class here)</span></span>
<span id="cb16-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;"># tell the block HOW TO GET THE DATA (here its files but could also be rows in a .csv, etc...)</span></span>
<span id="cb16-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 class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># tell the block HOW TO BUILD THE VALIDATION SET (here we just randomly select 20% data)</span></span>
<span id="cb16-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;"># tell the block WHERE TO GET OUR LABELS (here from the parent folder)</span></span>
<span id="cb16-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;">128</span>)                            <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># tell the block things WE WANT DONE EACH TIME WE GRAB AN ITEM from the dataset</span></span>
<span id="cb16-7">)</span></code></pre></div>
</div>
<p>If you’re unsure what any of these classes or methods do, don’t forget about the <code>??</code> syntax you can use in notebooks. For example …</p>
<div id="cell-29" class="cell">
<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">ImageBlock??</span></code></pre></div>
</div>
<div class="callout callout-style-default 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">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>We specify <code>Resize(128)</code> as an <strong>item transform</strong> because ultimately we’ll feed the data into our model a <em>mini-batch</em> at a time, and in order to take advantage of the GPU and tensor operations that items we feed in need to be the same size.</p>
</div>
</div>
<p>“<strong><em>Item transforms</em></strong> are pieces of code that run on each individual item, whether it be an image, category, or so forth.”</p>
<div id="cell-31" class="cell">
<div class="sourceCode cell-code" id="cb18" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb18-1">dls <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> dblock.dataloaders(raw_data_path)</span></code></pre></div>
</div>
<p>We <em>implement</em> our blueprint by passing the path to the image files into the <code>DataBlock.dataloaders()</code> method. Whatever we pass in as an argument here, gets passed to the function we specified in <code>get_items</code> above (which is<code>get_image_files</code> in this case). While iterating over each image, <code>get_y</code> will be used to grab the label of the image and our two blocks, <code>ImageBlock</code> and <code>CategoryBlock</code> will provide both the pre and post-processing necessary to work with our images and classes. Finally, our <code>splitter</code> will randomly take 20% of the dataset and set it aside for our validation set.</p>
<div class="callout callout-style-default callout-tip 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">
Tip
</div>
</div>
<div class="callout-body-container callout-body">
<p>You want to ensure you get the same validation set each time so you can meaningfully assess the performance of your model(s) as you tweak things. You do this by assigning a <code>seed</code>. If you don’t do this, you won’t know if your model’s performance is due to it seeing different images in the validation set or because of change you’ve made in your hyperparameters, model architecture, etc…</p>
</div>
</div>
<p>Each time we grab an image, regardless of the size, from the dataset, we resize it as a 128x128 tensor.</p>
<div id="cell-33" class="cell">
<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">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;">4</span>, nrows<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>We can use the <code>DataBlock.new()</code> method to modify only parts of our <code>DataBlock</code> defined above, and so create a new instance. Here for example, we can change how the <code>Resize</code> transform resizes images so that it randomly crops the image, keeping at least 30% of the image each time.</p>
<p>By default, this method crops the images to fit a square (but as you can see here we can also have fastai pad the images with zeroes, squish, or stretch them.).</p>
<div id="cell-35" class="cell">
<div class="sourceCode cell-code" id="cb20" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb20-1">dblock2 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> dblock.new(item_tfms<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>RandomResizedCrop(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">128</span>, min_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.2</span>))</span>
<span id="cb20-2">dls <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> dblock2.dataloaders(raw_data_path)</span></code></pre></div>
</div>
<div id="cell-36" class="cell">
<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">dls.valid.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;">4</span>, nrows<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="callout callout-style-default callout-tip 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">
Tip
</div>
</div>
<div class="callout-body-container callout-body">
<p>When dealing with data augmentation, its often helpful to see how a <strong><em>single</em></strong> example is augmented.</p>
</div>
</div>
<div id="cell-38" class="cell">
<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">dls.train.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;">4</span>, nrows<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>, unique<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>Using <code>RandomResizedCrop</code> allows ” our model can learn to focus on, and recognize, different features in our images. It also reflects how images work in the real world: different photos of the same thing may be framed in slightly different ways.”</p>
<div class="callout callout-style-default callout-tip 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">
Tip
</div>
</div>
<div class="callout-body-container callout-body">
<p>“…training the neural network with examples of images where the objects are in slightly different places and slightly different sizes helps it to understand the basic concept of what an object is, and how it can be represented in an image.”</p>
</div>
</div>
<p>We can, and should, also use <strong>data augmentation</strong> to create “random variations” that are representative of what our model will see in the wild. “Examples of common data augmentation techniques for images are rotation, flipping, perspective warping, brightness changes and contrast changes.”</p>
<p>For “natural photos”, fastai provides the <code>aug_tranforms()</code> method that have proven to work well in general.</p>
<p>In addition, such “data augmentations” are tyically desirable to have run on the GPU since they’ll run much faster. To make this happen, these “transforms” are specified as <code>batch_tfms</code> since them happen on a “mini-batch” at a time.</p>
<div id="cell-40" class="cell">
<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">dblock2 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> dblock.new(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;">128</span>), batch_tfms<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>aug_transforms(mult<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="cb23-2">dls <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> dblock2.dataloaders(raw_data_path)</span>
<span id="cb23-3">dls.train.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;">8</span>, nrows<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>, unique<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>Using the <code>unique=True</code> argument with our <code>DataLoaders.show_batch()</code> method allows us to see how these augmentations are applied to a single image.</p>
<div class="callout callout-style-default callout-tip 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">
Tip
</div>
</div>
<div class="callout-body-container callout-body">
<p>Verify that the augmentations you use are representative of what your model will see in the wild</p>
</div>
</div>
<div class="callout callout-style-default callout-tip 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">
Tip
</div>
</div>
<div class="callout-body-container callout-body">
<p>Use augmentations to artificially provide more images than you do in your raw dataset</p>
</div>
</div>
</section>
<section id="step-3-train-your-model" class="level3">
<h3 class="anchored" data-anchor-id="step-3-train-your-model">Step 3: Train your model</h3>
<div id="cell-43" class="cell">
<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">dblock <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> dblock.new(</span>
<span id="cb24-2">    item_tfms<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>RandomResizedCrop(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">224</span>, min_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.5</span>),</span>
<span id="cb24-3">    batch_tfms<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>aug_transforms()</span>
<span id="cb24-4">)</span>
<span id="cb24-5"></span>
<span id="cb24-6">dls <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> dblock.dataloaders(raw_data_path)</span></code></pre></div>
</div>
<div id="cell-44" class="cell">
<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">learn <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> cnn_learner(dls, resnet18, metrics<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>error_rate)</span>
<span id="cb25-2">learn.fine_tune(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>)</span></code></pre></div>
</div>
<div id="cell-45" class="cell">
<div class="sourceCode cell-code" id="cb26" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb26-1">interp <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> ClassificationInterpretation.from_learner(learn)</span>
<span id="cb26-2">interp.plot_confusion_matrix()</span></code></pre></div>
</div>
<div class="callout callout-style-default callout-tip 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">
Tip
</div>
</div>
<div class="callout-body-container callout-body">
<p>“It’s helpful to see where exactly our errors are occurring, to see whether they’re due to a dataset problem (e.g., images that aren’t bears at all, or are labeled incorrectly, etc.), or a model problem (perhaps it isn’t handling images taken with unusual lighting, or from a different angle, etc.). To do this, we can sort our images by their loss.”</p>
</div>
</div>
<p>For each image shown, <code>ClassificationInterpretation.plot_top_losses()</code> shows four things: the predicted class, the actual class, the loss, and the probability</p>
<div id="cell-47" class="cell">
<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">interp.plot_top_losses(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>, nrows<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="callout callout-style-default callout-tip 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">
Tip
</div>
</div>
<div class="callout-body-container callout-body">
<p>” a model can actually help you find data issues more quickly and easily. So, we normally prefer to train a quick and simple model first, and then use it to help us with data cleaning.”</p>
</div>
</div>
<p>fastai includes the <code>ImageClassifierCleaner</code> that can be used to “clean your dataset” (remove or re-label images). See chapter 2 for more information on how to use this utility.</p>
<hr>
</section>
<section id="step-4-inference" class="level3">
<h3 class="anchored" data-anchor-id="step-4-inference">Step 4: Inference</h3>
<p>“Remember that a model consists of two parts: the architecture and the trained parameters. The easiest way to save the model is to save both of these, because that way when you load a model you can be sure that you have the matching architecture and parameters.”</p>
<p>How do we do this? We use <code>Learner.export()</code>.</p>
<p>By using this method we don’t have to redefine how the data needs to be transformed as the inference learner will know what transforms to apply based on what was applied to your validation <code>DataLoader</code>. For example, it will know <strong><em>not</em></strong> to apply any data augmentation which is only really useful during training.</p>
<div id="cell-50" class="cell">
<div class="sourceCode cell-code" id="cb28" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb28-1">learn.export()</span>
<span id="cb28-2"></span>
<span id="cb28-3">path <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> Path()</span>
<span id="cb28-4">path.ls(file_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;">'.pkl'</span>)</span></code></pre></div>
</div>
<div id="cell-51" class="cell">
<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">learn_inf <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> load_learner(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;">'export.pkl'</span>)</span>
<span id="cb29-2">learn_inf.dls.vocab</span></code></pre></div>
</div>
<p>Calling <code>Learner.predict()</code> will return the predicated label, the label index in the vocab, and the probabilities assigned to each of our 10 labels.</p>
<div id="cell-53" class="cell">
<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">learn_inf.predict(files[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>])</span></code></pre></div>
</div>
</section>
</section>
<section id="inference" class="level2">
<h2 class="anchored" data-anchor-id="inference">Inference</h2>
<p><strong>Inference</strong> is about how you used your trained model to get predictions on new data. It is often structured to perform in real-time on a single (or at least a small set of data) item or in the background where large quantities of data can be processed together in batches. For the former, we can use fastai’s <code>Learner.predict()</code> method while for the later we can use either fastai’s <code>Learner.get_preds()</code> or write our own inference loop using PyTorch.</p>
<section id="export-and-predict" class="level3">
<h3 class="anchored" data-anchor-id="export-and-predict"><code>export()</code> and <code>predict()</code></h3>
<p>“a model consists of two parts: the <em>architecture</em> and the trained <em>parameters</em>.” You can use it just like any other function</p>
<pre><code># saves the architecture, the trained parameters, and the definintion of how to create your DataLoaders
learn.export() </code></pre>
<div class="callout callout-style-default 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">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>fastai … uses your validation set <code>DataLoader</code> for inference by default, <strong><em>so your data augmentation will not be applied.</em></strong></p>
</div>
</div>
<div class="sourceCode" id="cb32" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb32-1">inf_learn <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> load_learner(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;">'export.pkl'</span>)</span>
<span id="cb32-2">inf_learn.predict(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'images/grizzly.jpg'</span>)</span>
<span id="cb32-3">inf_learn.dls.vocab <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># =&gt; To view possible classification categories/labels</span></span></code></pre></div>
<p>For options on how to deploy your app, see the <a href="https://course.fast.ai/">Deployment section</a> in the course website. I personally like to use <a href="https://fastapi.tiangolo.com/">FastAPI</a> and there is a good <a href="https://forums.fast.ai/t/fastai2-fastapi-starter-template/69373?u=wgpubs">starter template here</a> for that.</p>
</section>
</section>
<section id="resources" class="level2">
<h2 class="anchored" data-anchor-id="resources">Resources</h2>
<ol type="1">
<li><p>https://book.fast.ai - The book’s website; it’s updated regularly with new content and recommendations from everything to GPUs to use, how to run things locally and on the cloud, etc…</p></li>
<li><p>https://docs.fast.ai/ - The library’s documentation; includes tutorials and other tips for development.</p></li>
<li><p>https://forums.fast.ai/ - If you’re not part of the community yet, you should be. Before posting a question, search to see if it has been answered already (95% of the time, it has).</p></li>
</ol>


</section>

 ]]></description>
  <category>fastai</category>
  <category>fastbook</category>
  <guid>https://ohmeow.com/posts/2020-11-16-ajtfb-chapter-2.html</guid>
  <pubDate>Mon, 16 Nov 2020 08:00:00 GMT</pubDate>
  <media:content url="https://ohmeow.com/posts/images/fastbook.jpg" medium="image" type="image/jpeg"/>
</item>
<item>
  <title>A Journey Through Fastbook (AJTFB) - Chapter 1: The Basics of Deep Learning</title>
  <dc:creator>Wayde Gilliam</dc:creator>
  <link>https://ohmeow.com/posts/2020-11-06-ajtfb-chapter-1.html</link>
  <description><![CDATA[ 




<p>Other posts in this series:</p>
<p><a href="../posts/2020-11-16-ajtfb-chapter-2.html">A Journey Through Fastbook (AJTFB) - Chapter 2</a><br>
<a href="../posts/2020-11-22-ajtfb-chapter-3.html">A Journey Through Fastbook (AJTFB) - Chapter 3</a><br>
<a href="../posts/2021-05-23-ajtfb-chapter-4.html">A Journey Through Fastbook (AJTFB) - Chapter 4</a><br>
<a href="../posts/2021-06-03-ajtfb-chapter-5.html">A Journey Through Fastbook (AJTFB) - Chapter 5</a><br>
<a href="../posts/2021-06-10-ajtfb-chapter-6-multilabel.html">A Journey Through Fastbook (AJTFB) - Chapter 6a</a><br>
<a href="../posts/2022-02-09-ajtfb-chapter-6-regression.html">A Journey Through Fastbook (AJTFB) - Chapter 6b</a><br>
<a href="../posts/2022-03-28-ajtfb-chapter-7.html">A Journey Through Fastbook (AJTFB) - Chapter 7</a><br>
<a href="../posts/2022-03-31-ajtfb-chapter-8.html">A Journey Through Fastbook (AJTFB) - Chapter 8</a><br>
<a href="../posts/2022-04-25-ajtfb-chapter-9.html">A Journey Through Fastbook (AJTFB) - Chapter 9</a></p>
<p>Cervantes once wrote that “the journey is better than the inn”, but I rather like to think that the journey <em>is</em> the inn.</p>
<p>It means that the journey, irrespective to its difficulties (and likely because of them), is what you look back on with fondness at its end rather than the end itself. It’s why I enjoy reading “The Lord of the Rings” every five years or so, where as I age and experience the hand life has dealt me, I find myself appreciating different aspects of the story from the time before and gaining new insights into what I value and want to be as a human being. I find my journey with deep learning to be roughly analgous to that.</p>
<p>I’ve been a part of <a href="https://forums.fast.ai/u/wgpubs/summary">the fast.ai community</a> for several years. I’ve been through <a href="https://course.fast.ai/">the course</a> multiple times (since it was using theano back in the old days), I’ve contributed to the library, and use it as the basis for one of <a href="https://ohmeow.github.io/blurr/">my own</a>. And as with each course, with a re-reading of the book I find myself deriving new insights and appreciating different ideas than those I had before.</p>
<p>And so, while your journey may bring you different revelations, here are the meandering thoughts of one 49 year old married father of 3 living in San Diego, California, USA, as I embark upon the first chapter in what I consider “The Lord of the Rings” of deep learning.</p>
<section id="how-to-learn-deep-learning" class="level2">
<h2 class="anchored" data-anchor-id="how-to-learn-deep-learning">How to learn Deep Learning</h2>
<section id="you-can-do-this" class="level3">
<h3 class="anchored" data-anchor-id="you-can-do-this">You can do this!</h3>
<blockquote class="blockquote">
<p>Hi, everybody; I’m Jeremy … I do not have any formal technical education … didn’t have great grades. I was much more interested in doing real projects.</p>
</blockquote>
<p>This is meaningful to me as someone with a BA in History and a MA in Theology. It’s a reminder that if you want something, it’s within your grasp to make it happen if you are willing to put in the work. It’s also a reminder that key to getting there is actually doing something! I find too many people thinking that if they just get into that school, or if they can just take that class, then they’ll be a good software enginner or deep learning practitioner. The reality is that the <em>only</em> way you get there is by doing it … just like pull-ups (which aren’t much fun when you’re starting out and/or you’re 49 and overweight).</p>
</section>
<section id="the-problem-with-traditional-education" class="level3">
<h3 class="anchored" data-anchor-id="the-problem-with-traditional-education">The problem with traditional education</h3>
<blockquote class="blockquote">
<p>… how math is taught - we require students to spend years doing rote memorization and learning dry disconnected <em>fundatmentals</em> that we claim will pay off later, long after most of them quit the subject.</p>
</blockquote>
<p>This also is the problem with higher education in general, where young people spend at least four to five years learning things they already learned in High School or else things they don’t really care about and will be forgotten right after finals, spending in excess of $100,000 for the privilege of it and likely going into debt in the tens of thousands of dollars, all with this idea that having done it they will be prepared for the real world. Unfortunately, that’s not how it works. Whether you are in a university of even go to university, what matter is what you do … not what classes you took or what your GPA is.</p>
</section>
<section id="deep-learning-and-coding-in-general-is-an-art-maybe-more-so-than-a-science" class="level3">
<h3 class="anchored" data-anchor-id="deep-learning-and-coding-in-general-is-an-art-maybe-more-so-than-a-science">Deep Learning (and coding in general) is an art maybe more so than a science</h3>
<blockquote class="blockquote">
<p>The hardest part of deep learning is artisanal.</p>
</blockquote>
<p>I remember going to an iOS conference way back in the day and a conference speaker asking how many folks in the session I was sitting in had a background in music. 80-90% of the audience raised their hands. Sure, there is math and stats and a science to deep learning, but like any coding enterprise, it’s an art … with some artists being better than others along with room for improvement regardless of whether you’re Van Gough or painting by the numbers.</p>
</section>
<section id="doing-is-how-you-learn-and-what-youve-done-is-what-matters" class="level3">
<h3 class="anchored" data-anchor-id="doing-is-how-you-learn-and-what-youve-done-is-what-matters">Doing is how you learn, and what you’ve done is what matters</h3>
<blockquote class="blockquote">
<p>… focus on your hobbies and passions … Common character traits in the people who do well at deep learning include playfulness and curiosity.</p>
</blockquote>
<blockquote class="blockquote">
<p>at Tesla .. CEO Elon Musk says ‘A PhD is definitely not required. All that matters is a deep understanding of AI &amp; ability to implement NNs in a way that is actually useful …. Don’t care if you even graduated High School.’</p>
</blockquote>
<blockquote class="blockquote">
<p>… the most important thing for learning deep learning is writing code and experimenting.”</p>
</blockquote>
</section>
<section id="folks-to-follow" class="level3">
<h3 class="anchored" data-anchor-id="folks-to-follow">Folks to follow</h3>
<p>It’s always helpful to have some role models; folks who practice the lessons learned above and can help you along your journey.</p>
<p>For starters, consider this image of the top 12 users based on most likes in the fast.ai forums: <img src="https://github.com/ohmeow/ohmeow_website/blob/master/images/articles/20211102-fastai-forums-top-12.png?raw=1" class="img-fluid"></p>
<p>Aside from the founders of <a href="https://www.fast.ai/">fast.ai</a> and a bunch of them working for noteable ML companies like <a href="https://huggingface.co/">Hugging Face</a> and <a href="https://wandb.ai/site">Weights &amp; Biases</a>, I can think of at least <strong><em>FOUR</em></strong> things these folks have in common:</p>
<ol type="1">
<li><p>They are <strong>fearless in asking what they may have even considered, dumb questions</strong>.</p></li>
<li><p>They are <strong>active in researching the answers to their own questions</strong> (even the dumb ones) and those asked by others.</p></li>
<li><p>They are <strong>active in teaching</strong> others through blogs, books, open source libraries, study groups, and podcasts.</p></li>
<li><p><strong>They build</strong> things! That is, they all have experience building models and making them usable via deployed applications and/or in kaggle compeititions. Anyone can bake a half-cooked model in a Jupyter notebook, but few can turn it into something others can use.</p></li>
</ol>
<p>These traits aren’t just key to learning deep learning; they are key to learning anything! Practice them and you guarantee yourself success in learning anything you’ve set your mind on.</p>
<p>If you had to choose just three …</p>
<p>Aside from Jeremy (<a href="https://twitter.com/jeremyphoward"><span class="citation" data-cites="jeremyphoward">@jeremyphoward</span></a>), who’s a given, if I could only follow three people who have mastered to art of learning deep learning, they would be …</p>
<p><strong>Radek Osmulsk</strong>: (twitter: <a href="https://twitter.com/radekosmulski"><span class="citation" data-cites="radekosmulski">@radekosmulski</span></a>)</p>
<blockquote class="twitter-tweet blockquote" data-conversation="none" data-theme="dark">
<p lang="en" dir="ltr">
If you found this of value, you might be interested in a book on learning deep learning that I wrote<br><br>check it out here &gt;&gt;&gt; <a href="https://t.co/ApKlm8BRmy">https://t.co/ApKlm8BRmy</a>
</p>
— <span class="citation" data-cites="radek">@radek</span><span class="citation" data-cites="sigmoid.social">@sigmoid.social</span> (Mastodon) 🇺🇦 (<span class="citation" data-cites="radekosmulski">@radekosmulski</span>) <a href="https://twitter.com/radekosmulski/status/1455527697661169664?ref_src=twsrc%5Etfw">November 2, 2021</a>
</blockquote>
<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
<p><strong>Zach Mueller</strong>: (twitter: <a href="https://twitter.com/TheZachMueller"><span class="citation" data-cites="TheZachMueller">@TheZachMueller</span></a>)</p>
<blockquote class="twitter-tweet blockquote" data-conversation="none" data-theme="dark">
<p lang="en" dir="ltr">
To me, I think it boiled down to how I learned. I took those two courses essentially over the course of a year or so. Approaching each lesson slowly, and letting myself wander in the related concepts, learning as much as I could through online communities.
</p>
— Zach Mueller (<span class="citation" data-cites="TheZachMueller">@TheZachMueller</span>) <a href="https://twitter.com/TheZachMueller/status/1451941577841127433?ref_src=twsrc%5Etfw">October 23, 2021</a>
</blockquote>
<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
<p><strong>Sanyam Bhutani</strong>: (twitter: <a href="https://twitter.com/bhutanisanyam1"><span class="citation" data-cites="bhutanisanyam1">@bhutanisanyam1</span></a>)</p>
<blockquote class="twitter-tweet blockquote" data-theme="dark">
<p lang="en" dir="ltr">
The <a href="https://twitter.com/PyTorch?ref_src=twsrc%5Etfw"><span class="citation" data-cites="PyTorch">@PyTorch</span></a> book reading group <a href="https://twitter.com/weights_biases?ref_src=twsrc%5Etfw"><span class="citation" data-cites="weights_biases">@weights_biases</span></a> comes to an end🙏<br><br>We had an incredible 10 weeks of learning!<br><br>As a group wanted to extend our gratitude to the incredible authors: Eli, <a href="https://twitter.com/lantiga?ref_src=twsrc%5Etfw"><span class="citation" data-cites="lantiga">@lantiga</span></a> &amp; <a href="https://twitter.com/ThomasViehmann?ref_src=twsrc%5Etfw"><span class="citation" data-cites="ThomasViehmann">@ThomasViehmann</span></a> <br><br>A few words from our community:<a href="https://t.co/3ODz6J1vad">https://t.co/3ODz6J1vad</a>
</p>
— Sanyam Bhutani (<span class="citation" data-cites="bhutanisanyam1">@bhutanisanyam1</span>) <a href="https://twitter.com/bhutanisanyam1/status/1452599997493481472?ref_src=twsrc%5Etfw">October 25, 2021</a>
</blockquote>
<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
<p>Personally, I <strong>do</strong> follow each of these individuals on twitter and you should too! Though I’ve never met any of them IRL, I consider the colleagues, friends, and amongst the most helpful for those looking to get started in machine learning.</p>
<div class="callout callout-style-default callout-tip 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">
Tip
</div>
</div>
<div class="callout-body-container callout-body">
<p>Twitter is imo the best place to network with fellow ML/DL practioners and stay up-to-date with the latest developments in ML in general</p>
</div>
</div>
<p>Here’s a tl;dr for folks too lazy to read the above …</p>
<div class="quarto-video ratio ratio-16x9"><iframe data-external="1" src="https://www.youtube.com/embed/_QUEXsHfsA0?" title="" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe></div>
</section>
</section>
<section id="what-is-machine-learning" class="level2">
<h2 class="anchored" data-anchor-id="what-is-machine-learning">What is machine learning?</h2>
<p>Here we look at machine learning in general (of which deep learning is a subset) as well as the process of finetuning a pretrained ML model. When you think of deep learning … think neural networks.</p>
<p><img src="https://ohmeow.com/posts/images/what-is-ai-ml-dl.jpg" class="img-fluid"></p>
<section id="a-picture" class="level3">
<h3 class="anchored" data-anchor-id="a-picture">A picture</h3>
<p><img src="https://ohmeow.com/posts/images/ajtfb-ch-1-deep_learning_overview.png" title="Credit: Fastbook p.25" class="img-fluid"></p>
</section>
<section id="an-explanation" class="level3">
<h3 class="anchored" data-anchor-id="an-explanation">An explanation</h3>
<blockquote class="blockquote">
<p>“Suppose we arrange for some automatic means of testing the effectiveness of any current weight assignment in terms of actual performance and provide a mechanism for altering the weight assignment so as to maximize the performance. We need not go into the details of such a procedure to see that it could be made entirely automatic and to see that a machine so programmed would ‘learn’ from its experince” - Arthur Samuel</p>
</blockquote>
<section id="architecture-vs.-model" class="level4">
<h4 class="anchored" data-anchor-id="architecture-vs.-model">Architecture vs.&nbsp;model</h4>
<blockquote class="blockquote">
<p>… a <strong><em>model</em></strong> is a special kind of program: it’s one that can do <em>many different things</em>, depending on the <strong>weights</strong>.</p>
</blockquote>
<blockquote class="blockquote">
<p>The functional form of the <em>model</em> is called its <strong><em>architecture</em></strong>.</p>
</blockquote>
<div class="callout callout-style-default 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">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>The <strong>architecture</strong> is “the <em>template</em> of the model that we’re trying to fit; i.e., the actual mathematical function that we’re passing the input data and parameters to” … whereas the <strong>model</strong> is a particular set of parameters + the architecture.</p>
</div>
</div>
</section>
<section id="parameters" class="level4">
<h4 class="anchored" data-anchor-id="parameters">Parameters</h4>
<blockquote class="blockquote">
<p><strong>Weights</strong> are just variables, and a <strong>weight assignment</strong> is a particuarl choice of values for those variables. [Weights] are generally referred to as model <strong><em>parameters</em></strong> … the term <em>weights</em> being reserved for a particular type of model parameter.</p>
</blockquote>
<blockquote class="blockquote">
<p>The <em>weights</em> are called <strong><em>parameters</em></strong>.</p>
</blockquote>
<div class="callout callout-style-default 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">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>These parameters are the things that are “learnt”; the values that can be updated, whereas <strong>activations</strong> in a neural network are simply numbers as the result of some calculation.</p>
</div>
</div>
</section>
<section id="inputs-vs.labels" class="level4">
<h4 class="anchored" data-anchor-id="inputs-vs.labels">Inputs vs.labels</h4>
<p>The <strong><em>inputs</em></strong>, also known as your <strong><em>independent variable(s)</em></strong> [your <code>X</code>] is what your model uses to make <strong><em>predictions</em></strong>.</p>
<p>The <strong><em>labels</em></strong>, also known as your <strong><em>dependent variable(s)</em></strong> [your <code>y</code>] represent the correct target value for your task.</p>
</section>
<section id="loss" class="level4">
<h4 class="anchored" data-anchor-id="loss">Loss</h4>
<blockquote class="blockquote">
<p>The [model’s] measure of performance is called the <strong><em>loss</em></strong> … [the value of which depends on how well your model is able to predict] the correct <strong><em>labels</em></strong>.</p>
</blockquote>
<p>The <strong><em>loss</em></strong> is a measure of model performance that SGD can use to make your model better. A good loss function provides good gradients (slopes) that can be used to make even very minor changes to your weights so as to improve things. Visually, you want gentle rolling hills rather than abrupt steps or jagged peaks.</p>
<div class="callout callout-style-default 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">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>You can think of the <strong>loss</strong> as the model’s <strong>metric</strong>, that is, how it both understands how good it is and can help it improve.</p>
</div>
</div>
</section>
</section>
</section>
<section id="transfer-learning" class="level2">
<h2 class="anchored" data-anchor-id="transfer-learning">Transfer learning</h2>
<p><strong><em>Transfer learning</em></strong> is the process of taking a <strong>“pretrained model”</strong> that has been trained on a very large dataset with proven SOTA results, and <strong>“fine tuning”</strong> it for your specific task, which while likely similar to the task the pretrained model was trained for to one degree or another, is not the necesarily the same.</p>
<section id="how-does-it-work" class="level3">
<h3 class="anchored" data-anchor-id="how-does-it-work">How does it work?</h3>
<ol type="1">
<li>The <strong>head</strong> of your model (the newly added part specific to your dataset/task) should be trained first since it is the only one with completely random weights.</li>
<li>The degree to which your weights of the pretrained model will need to be updated is proportional to how similar your data is to the data it was trained on. The more dissimilar, the more the weights will need to be changed.</li>
<li>Your model will only be as good as the data it was trained on, so make sure what you have is representative of what it will see in the real world. It “can learn to operate on only the patterns seen in the input data used to train it.”</li>
</ol>
<blockquote class="blockquote">
<p>The process of <em>training</em> (or <em>fitting</em>) the model is the process of finding a set of <em>parameter values</em> (or <em>weights</em>) that specialize that general architecture into a model that works well for our particular kind of data [and task]</p>
</blockquote>
</section>
<section id="what-is-the-high-level-approach-in-fastai" class="level3">
<h3 class="anchored" data-anchor-id="what-is-the-high-level-approach-in-fastai">What is the high-level approach in fastai?</h3>
<p>fastai provides a <code>fine_tune</code> method that uses proven tricks and hyperparameters for various DL tasks that the author’s have found works well most of the time.</p>
</section>
<section id="what-do-we-have-at-the-end-of-training-or-finetuning" class="level3">
<h3 class="anchored" data-anchor-id="what-do-we-have-at-the-end-of-training-or-finetuning">What do we have at the end of training (or finetuning)?</h3>
<blockquote class="blockquote">
<p>… once the model is trained - that is, once we’ve chosen our final weight assignments - then we can think of the weights as being <em>part of the model</em> since we’re not varying them anymore.</p>
</blockquote>
<p>This means a trained model can be treated like a typical function.</p>
</section>
</section>
<section id="metrics" class="level2">
<h2 class="anchored" data-anchor-id="metrics">Metrics</h2>
<section id="a-definition" class="level3">
<h3 class="anchored" data-anchor-id="a-definition">A definition</h3>
<p><strong>Metrics</strong> are a human-understandable measures of model quality whereas the <strong>loss</strong> is the machine’s. They are based on your validation set and are what you really care about, whereas the loss is “a measure of performance” that the training system can use to update weights automatically.</p>
<p>A good choice for loss is a function “that is easy for <strong><em>stochastic gradient descent (SGD)</em></strong> to use, whereas a good choies for your metrics are functions that your business users will care about. Seldom are they the same because most metrics don’t provide smooth gradients that SGD can use to update your model’s weights.</p>
<div class="callout callout-style-default 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">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>Again, they are based on your validation/test sets (not your training set). Ultimately, we want to have a model that generalizes well to inputs it was <em>not</em> trained on, and this is what our validation/test sets represent. This is how we relay our model quality.</p>
</div>
</div>
</section>
<section id="examples" class="level3">
<h3 class="anchored" data-anchor-id="examples">Examples</h3>
<p>There are a whole list of metrics built into the fastai library, <a href="https://docs.fast.ai/metrics.html">see here</a>. Below I begin a listing of the most common ones as they come up in the fastbook (and from personal experience).</p>
<p><strong>error rate</strong> = “the proportion of images that were incorrectly identified.”</p>
<p><strong>accuracy</strong> = the proportation of images that were correctly identified (<code>1 - error rate</code>)</p>
</section>
<section id="metrics-to-use-based-on-task" class="level3">
<h3 class="anchored" data-anchor-id="metrics-to-use-based-on-task">Metrics to use based on task</h3>
<div id="cell-8" class="cell" data-outputid="a3b9d6b7-2d91-43d2-9486-3104aecaab32" data-vscode="{&quot;languageId&quot;:&quot;python&quot;}">
<div class="cell-output cell-output-display" data-execution_count="2">


<table id="T_6f6f8_" class="dataframe caption-top table table-sm table-striped small" data-quarto-postprocess="true">
<thead>
<tr class="header">
<th class="col_heading level0 col0" data-quarto-table-cell-role="th">Metric</th>
<th class="col_heading level0 col1" data-quarto-table-cell-role="th">Multiclass classification</th>
<th class="col_heading level0 col2" data-quarto-table-cell-role="th">Multilabel classification</th>
<th class="col_heading level0 col3" data-quarto-table-cell-role="th">Regression</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td id="T_6f6f8_row0_col0" class="data row0 col0">error rate</td>
<td id="T_6f6f8_row0_col1" class="data row0 col1">Yes</td>
<td id="T_6f6f8_row0_col2" class="data row0 col2">Yes*</td>
<td id="T_6f6f8_row0_col3" class="data row0 col3">No</td>
</tr>
<tr class="even">
<td id="T_6f6f8_row1_col0" class="data row1 col0">accuracy</td>
<td id="T_6f6f8_row1_col1" class="data row1 col1">Yes</td>
<td id="T_6f6f8_row1_col2" class="data row1 col2">Yes*</td>
<td id="T_6f6f8_row1_col3" class="data row1 col3">No</td>
</tr>
</tbody>
</table>
</div>
</div>
<p><code>*</code> indicates that other metrics may be better for the given task.</p>
</section>
</section>
<section id="training-validation-and-test-datasets" class="level2">
<h2 class="anchored" data-anchor-id="training-validation-and-test-datasets">Training, validation, and test datasets</h2>
<section id="what-is-a-training-set" class="level3">
<h3 class="anchored" data-anchor-id="what-is-a-training-set">What is a training set?</h3>
<p>A <strong><em>training set</em></strong> consits of the data your model sees during training. These are the inputs and labels your model will use to determine the loss and update it’s parameters in a way that will hopefully lead to a model that works well for its given task.</p>
<section id="why-do-we-need-a-training-set" class="level5">
<h5 class="anchored" data-anchor-id="why-do-we-need-a-training-set">Why do we need a training set?</h5>
<p>Because a model needs something to train on. It should be representative of the data the model will see in the future, and it should be updated if/when you discover that is not the case.</p>
</section>
<section id="how-to-use-a-training-set" class="level4">
<h4 class="anchored" data-anchor-id="how-to-use-a-training-set">How to use a training set?</h4>
<ol type="1">
<li><p>To train a model on examples resembling that which the model will seen in the future. More is generally better, but quality is king (e.g., bad data in, bad data out).</p></li>
<li><p>To provide augmented examples for your model to see so as to increase the number of examples and better reflect what the model may see in the real world.</p></li>
</ol>
</section>
</section>
<section id="what-is-a-validation-set" class="level3">
<h3 class="anchored" data-anchor-id="what-is-a-validation-set">What is a validation set?</h3>
<p>A <strong><em>validation set</em></strong> (also know as the “development set”) does not include any data from the <strong><em>training set</em></strong>. It’s purpose to is gauge the generalization prowess of your model and also ensure you are neight overfitting or underfitting.</p>
<blockquote class="blockquote">
<p>“If [the model] makes an accurate prediction for a data item, that should be because it has learned characteristics of that kind of item, and not because the model has been shaped by <em>actually having seen that particular item</em>.”</p>
</blockquote>
<section id="why-do-we-need-a-validation-set" class="level4">
<h4 class="anchored" data-anchor-id="why-do-we-need-a-validation-set">Why do we need a validation set?</h4>
<blockquote class="blockquote">
<p>“[because] what we care about is how well our model works on <em>previously unseen images</em> … the longer you train for, the better your accuracy will get on the training set … as the model starts to memorize the training set rather than finding generalizable underlying patterns in the data = <strong>overfitting</strong>”</p>
</blockquote>
<p><img src="https://raw.githubusercontent.com/fastai/fastbook/41a60e44d588139a03452f1907359fc2322f8d5f/images/att_00000.png" class="img-fluid"></p>
<p><strong><em>Overfitting</em></strong> happens when the model “remembers specific features of the input data, rather than generalizing well to data not seen during training.”</p>
<div class="callout callout-style-default 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">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p><strong>ALWAYS</strong> overfit before anything else. It is your training loss gets better while your validation loss gets worse … in other words, if you’re validation loss is improving, even if not to the extent of your training loss, you are <em>not</em> overfitting</p>
</div>
</div>
<div class="callout callout-style-default 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">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p><strong>ALWAYS</strong> include a validation set.</p>
</div>
</div>
<div class="callout callout-style-default 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">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p><strong>ALWAYS</strong> use the validation set to measure your accuracy (or any metrics).</p>
</div>
</div>
<div class="callout callout-style-default 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">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p><strong>ALWAYS</strong> set the <code>seed</code> parameter so that you “get the same validation set every time” so that “if we change our model and retrain it, we know any differences are due to the changes to the model, not due to having a different random validation set.”</p>
</div>
</div>
<div class="callout callout-style-default callout-tip 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">
Tip
</div>
</div>
<div class="callout-body-container callout-body">
<p>For a good discussion of how to achieve predictable randomness, see <a href="https://forums.fast.ai/t/lesson1-reproducible-results-setting-seed-not-working/37921/5">this discussion</a> on the fast.ai forums. There are actually several seeds you need to set and in several places when using fast.ai to achieve reproducibility.</p>
</div>
</div>
</section>
<section id="how-to-use-a-validation-set" class="level4">
<h4 class="anchored" data-anchor-id="how-to-use-a-validation-set">How to use a validation set?</h4>
<ol type="1">
<li><p>It gives us a sense of how well our model is doing on examples <em>it hasn’t seen</em>, which makes sense since the ultimate worth of a model is in how well it generalizes to things unseen in the future.</p></li>
<li><p>The validation set also informs us how we may change the <strong><em>hyperparamters</em></strong> (e.g., model architecture, learning rates, data augmentation, etc…) to improve results. These parameters are NOT learned … they are choices WE make that affect the learning of the model parameters.</p></li>
</ol>
</section>
</section>
<section id="what-is-a-test-set" class="level3">
<h3 class="anchored" data-anchor-id="what-is-a-test-set">What is a test set?</h3>
<p>A <strong><em>test set</em></strong> ensures that we aren’t overfitting our hyperparameter choices; it is held back even from ourselves and used to evaulate the model at the very end.</p>
<blockquote class="blockquote">
<p>“[Since we] are evaluating the model by looking at predictions on the validation data when we decide to explore new hyperparameter values … subsequent version of the model are, indirectly, shaped by us having seen the validation data … [and therefore], we are in danger of overfitting the validation data through human trial and error and exploration.”</p>
</blockquote>
<div class="callout callout-style-default 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">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>A key property of the validation and test sets is that they must be representative of the new data you will see in the future.</p>
</div>
</div>
<section id="why-do-we-need-a-test-set" class="level4">
<h4 class="anchored" data-anchor-id="why-do-we-need-a-test-set">Why do we need a test set?</h4>
<p>To ensure we aren’t inadvertently causing the model to overfit via our hyperparameter tuning which happens as a result of us looking at the validation set. It is a completely hidden dataset; it isn’t used for training or tuning, only for measuring performance.</p>
</section>
<section id="how-to-use-a-test-set" class="level4">
<h4 class="anchored" data-anchor-id="how-to-use-a-test-set">How to use a test set?</h4>
<ol type="1">
<li><p>If evaluating 3rd party solutions. You’ll want to know how to create a good test set and how to create a good baseline model. Hold these out from the potential consultants and use them to fairly evaluate their work.</p></li>
<li><p>To ensure you aren’t overfitting your model as a result of validation set examination. As with the validation set, a good test set offers further assurance your model isn’t learning particular ancillary features of particular things in your images.</p></li>
</ol>
</section>
</section>
<section id="how-to-create-good-validation-and-test-sets" class="level3">
<h3 class="anchored" data-anchor-id="how-to-create-good-validation-and-test-sets">How to create good validation and test sets</h3>
<p>It isn’t always as easy as randomly shuffling your data!</p>
<p>Again, what both of these sets should haven in common is that they “must be representative of the new data you will see in the future.” And what this looks like often dependes on your use case and task.</p>
<div class="callout callout-style-default callout-tip 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">
Tip
</div>
</div>
<div class="callout-body-container callout-body">
<p>You really need to think about what you need to predict and what you’d look at to make that prediction. You also need to make sure your training data is qualitatively different enough from your real world data (e.g., what the validation and test sets represent) as to learn patterns and not specific examples.</p>
</div>
</div>
<p><strong>First</strong>, consider cases where historical data is required to predict the future, for example of quant traders use “<em>backtesting</em> to check whether their models are predictive of future periods, based on past data”</p>
<div class="callout callout-style-default 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">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>“For a <strong>time series</strong> … (where you are using historical data to build a model for use in the future … you will want to choose a continuous section with the latest dates as your validation set”</p>
</div>
</div>
<p>“A <strong>second</strong> common case occurs when you can easily anticipate ways the data you will be making predictions for in production may be <em>qualitatively different</em> from the data you have to train your model with.”</p>
<p>As an example of this, <a href="https://www.kaggle.com/c/state-farm-distracted-driver-detection">the Kaggle distracted driver competition</a> is used. In it, based on pictures of drivers you need to predict categories of distraction. Since the goal of such a model would be to make good predictions against <strong><em>drivers the model hasn’t seen</em></strong>, it would make sense to create a validation and also a test set consiting of specific drivers the training set doesn’t include (in fact, the competition’s test set is exactly that!). “If you used all the people in training your model, your model might be overfitting to the paricipants of those specific people and not just learning the states (texting, eating, etc.).”</p>
<p>Another example of this is <a href="https://www.kaggle.com/c/the-nature-conservancy-fisheries-monitoring">the Kaggle fisheries competition</a> where the objective is to predict the species of fish caught on fishing boats. As the goal of such a model is to predict the species on other/future boats, it makes sense then that “the test set consisted of images from boats that didn’t appear in the training data, so in this case you’d want your validation set to also include boats that are not in the training set.”</p>
<div class="callout callout-style-default callout-tip 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">
Tip
</div>
</div>
<div class="callout-body-container callout-body">
<p>Start with training a model and let the results guide your EDA!</p>
</div>
</div>
<p>For a stellar example of how this looks in practice, <a href="https://twitter.com/borisdayma/status/1447939363296489473">see this thread from Boris Dayma</a> on an issue he noticed when looking at his results on the training and validation sets. <strong><em>Note how his EDA was directed via training a model</em></strong> … and also make sure to read through all the comments, replies, etc… for other things to pay attention too when seeing unusual results during training (there is a lot of good stuff there). Ultimately, in his case, what he found out was that the dataset was imbalanced and the imbalanced data was getting lumped together in the same batches due to poor shuffling strategy. He documents <a href="https://twitter.com/borisdayma/status/1448355381374242816">his fix in a subsequent thread</a> so check that out too.</p>
<div class="callout callout-style-default callout-tip 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">
Tip
</div>
</div>
<div class="callout-body-container callout-body">
<p>Knowing how to read your training/validation results drives EDA and will lead to better train/validation/test splits.</p>
</div>
</div>
</section>
</section>
<section id="categorical-datatypes" class="level2">
<h2 class="anchored" data-anchor-id="categorical-datatypes">Categorical datatypes</h2>
<p><strong><em>Categorical</em></strong> data “contains values that are one of a discrete set of choice” such as gender, occupation, day of week, etc…</p>
<section id="what-if-our-target-is-categorical" class="level3">
<h3 class="anchored" data-anchor-id="what-if-our-target-is-categorical">What if our <strong>target</strong> is categorical?</h3>
<p>If your target/lables are categorical, then you have either a <strong>multi-classification classification</strong> problem (e.g., you are trying to predict a single class) or a <strong>multi-label classification problem</strong> (e.g., you are trying to predict whether your example belongs to zero or multiple classes).</p>
<section id="multi-classification-tasks" class="level4">
<h4 class="anchored" data-anchor-id="multi-classification-tasks">Multi-classification tasks</h4>
<p>For multi-classification tasks, a sensible loss function would be <a href="https://ohmeow.com/posts/2020/04/04/understanding-cross-entropy-loss.html">cross entropy loss</a> (<code>nn.CrossEntropyLoss</code>) and <a href="https://ohmeow.com/what-is/a-metric#Metrics-to-use-based-on-task">useful metrics</a> are likely to include error rate, accuracy, F1, recall, and/or precision depending on your business objectices and the make up of your dataset. For example, if you’re dealing with a highly imbalanced dataset, choosing accuracy would lead to an inflated sense of model performance since it may be learning to just predict the most common class.</p>
<div class="callout callout-style-default 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">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>What if you need to predict “None”? This is more real world and covered nicely in Zach Mueller’s <a href="https://walkwithfastai.com/Unknown_Labels">Recognizing Unknown Images (or the Unknown Label problem)</a>.</p>
</div>
</div>
</section>
<section id="multi-label-tasks" class="level4">
<h4 class="anchored" data-anchor-id="multi-label-tasks">Multi-label tasks</h4>
<p>For multi-label tasks, a sensible loss function would be binary cross entropy loss (BCE) (<code>nn.BCEWithLogitsLoss</code>) and useful metrics are likely to include F1, recall, and/or precision depending on your business objectices and the make up of your dataset. Notice that I didn’t include error rate, or its opposite accuracy, as their datasets are generally highly imbalanced.</p>
</section>
</section>
<section id="what-if-our-input-is-categorical" class="level3">
<h3 class="anchored" data-anchor-id="what-if-our-input-is-categorical">What if our <strong>input</strong> is categorical?</h3>
<p>Categorical inputs are generally represented by an <strong>embedding</strong> (e.g., a vector of numbers). <strong><em>Why?</em></strong> Mostly because it gives your model the ability to provide a more complex representation of your category than a single numer would.</p>
<p>For example, imagine that one of your inputs is day of week (e.g., Sunday, Monday, etc.) … what does that mean? When combined with other inputs, its likely that the meaning of it is going to be much more nuanced than a single number can represent, and so we’d like to use multiple learned numbers. This is what an embedding is.</p>
</section>
</section>
<section id="continuous-datatypes" class="level2">
<h2 class="anchored" data-anchor-id="continuous-datatypes">Continuous datatypes</h2>
<p><strong><em>Continuous</em></strong> data is numerical that represents a quantity such as age, salary, prices, etc…</p>
<section id="what-if-our-target-is-continuous" class="level3">
<h3 class="anchored" data-anchor-id="what-if-our-target-is-continuous">What if our <strong>target</strong> is continuous?</h3>
<p>If your target/labels are continuous, then you have a regression problem and the most likely loss function you would choose would be mean-square-error loss (MSE) (<code>nn.MSELoss</code>) and your metric MSE as well</p>
<blockquote class="blockquote">
<p>“… MSE is already a a useful metric for this task (although its’ probably more interpretable after we take the square root)” … the <strong>RMSE</strong> (% fn 3 %}</p>
</blockquote>
<div class="callout callout-style-default 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">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>For tasks that predict a continuous number, consider using <code>y_range</code> to constrain the network to predicting a value in the known range of valid values.</p>
</div>
</div>
</section>
<section id="what-if-our-input-is-continuous" class="level3">
<h3 class="anchored" data-anchor-id="what-if-our-input-is-continuous">What if our <strong>input</strong> is continuous?</h3>
<p>In many cases there isn’t anything special you need to do, in others, it makes sense to scale these numbers so they are in the same range (usually 0 to 1) as the rest of your continuous inputs. This process is called <strong>normalization</strong>. The reason you would want to do this is so continuous values with bigger range of values (say 1000) don’t drown out those with a smaller range (say 5) during model training.</p>
</section>
<section id="normalization" class="level3">
<h3 class="anchored" data-anchor-id="normalization">Normalization</h3>
<div class="callout callout-style-default 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">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>“When training a model, if helps if your input data is <em>normalizaed</em> - that is, has a mean of 0 and a standard deviation of 1.</p>
</div>
</div>
<p>See <a href="https://towardsdatascience.com/how-to-calculate-the-mean-and-standard-deviation-normalizing-datasets-in-pytorch-704bd7d05f4c">How To Calculate the Mean and Standard Deviation — Normalizing Datasets in Pytorch</a></p>
<div id="cell-13" class="cell" data-outputid="9b747454-1993-4c03-9e16-555fada30af7" data-vscode="{&quot;languageId&quot;:&quot;python&quot;}">
<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="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> torch</span>
<span id="cb1-2"></span>
<span id="cb1-3"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Example 1'</span>)</span>
<span id="cb1-4">nums <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> torch.tensor([<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;">50</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span>], dtype<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;">float</span>)</span>
<span id="cb1-5"><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'Some raw values: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>nums<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="cb1-6"></span>
<span id="cb1-7"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># 1. calculate their mean and standard deviation</span></span>
<span id="cb1-8">m <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> nums.mean()</span>
<span id="cb1-9">std <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> nums.std()</span>
<span id="cb1-10"><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'Their mean is </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>m<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;"> and their standard deviation is </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>std<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="cb1-11"></span>
<span id="cb1-12"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># 2. normalize their values </span></span>
<span id="cb1-13">normalized <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (nums <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> m) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> std</span>
<span id="cb1-14"><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'Here are their values after normalization: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>normalized<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="cb1-15"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">''</span>)</span>
<span id="cb1-16"></span>
<span id="cb1-17"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Example 2'</span>)</span>
<span id="cb1-18">nums <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> torch.tensor([<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;">5000</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10000</span>], dtype<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;">float</span>)</span>
<span id="cb1-19"><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'Some raw values: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>nums<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="cb1-20"></span>
<span id="cb1-21"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># 1. calculate their mean and standard deviation</span></span>
<span id="cb1-22">m <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> nums.mean()</span>
<span id="cb1-23">std <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> nums.std()</span>
<span id="cb1-24"><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'Their mean is </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>m<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;"> and their standard deviation is </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>std<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="cb1-25"></span>
<span id="cb1-26"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># 2. normalize their values </span></span>
<span id="cb1-27">normalized <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (nums <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> m) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> std</span>
<span id="cb1-28"><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'Here are their values after normalization: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>normalized<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="cb1-29"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">''</span>)</span></code></pre></div>
<div class="cell-output cell-output-stdout">
<pre><code>Example 1
Some raw values: tensor([  0.,  50., 100.], dtype=torch.float64)
Their mean is 50.0 and their standard deviation is 50.0
Here are their values after normalization: tensor([-1.,  0.,  1.], dtype=torch.float64)

Example 2
Some raw values: tensor([    0.,  5000., 10000.], dtype=torch.float64)
Their mean is 5000.0 and their standard deviation is 5000.0
Here are their values after normalization: tensor([-1.,  0.,  1.], dtype=torch.float64)
</code></pre>
</div>
</div>
<p>fastai supplies a <code>Normalize</code> transform you can use to do this … “it acts on a whole mini-batch at once, so you can add it to the <code>batch_tfms</code> secion of your data block … you need to pass to this transform the mean and standard deviation that you want to use. If you don’t,”fastai will automatically calculate them from a single batch of your data). p.241</p>
<div class="callout callout-style-default 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">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>“This means that when you distribute a model, you need to also distribute the statistics used for normalization.” (p.242)</p>
</div>
</div>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>“… if you’re using a model that someon else has trained, make sure you find out what normalization statistics they used and match them.” (p.242)</p>
</div>
</div>
</section>
</section>
<section id="resnets" class="level2">
<h2 class="anchored" data-anchor-id="resnets">ResNets</h2>
<section id="what-is-a-resnet-why-use-it-for-computer-vision-tasks" class="level3">
<h3 class="anchored" data-anchor-id="what-is-a-resnet-why-use-it-for-computer-vision-tasks">What is a ResNet &amp; Why use it for computer vision tasks?</h3>
<p>A <strong>ResNet</strong> is a model architecture that has proven to work well in CV tasks. Several variants exist with different numbers of layers with the larger architectures taking longer to train and more prone to overfitting especially with smaller datasets.</p>
<p>The number represents the number of layers in this particular ResNet variant … “(other options are 18, 50, 101, and 152) … model architectures with more layers take longer to train and are more prone to overfitting … on the other hand, when using more data, they can be qite a bit more accurate.”</p>
<section id="what-other-things-can-use-images-recognizers-for-besides-image-tasks" class="level4">
<h4 class="anchored" data-anchor-id="what-other-things-can-use-images-recognizers-for-besides-image-tasks">What other things can use images recognizers for besides image tasks?</h4>
<p>Sound, time series, malware classification … “a good rule of thumb for converting a dataset into an image representation: if the human eye can recognize categories from the images, then a deep learning model should be able to do so too.”</p>
</section>
<section id="how-does-it-fare-against-more-recent-architectures-like-vision-transformers" class="level4">
<h4 class="anchored" data-anchor-id="how-does-it-fare-against-more-recent-architectures-like-vision-transformers">How does it fare against more recent architectures like vision transformers?</h4>
<p>Pretty well apparently (at least at the time this post was written) …</p>
<blockquote class="twitter-tweet blockquote" data-theme="dark">
<p lang="en" dir="ltr">
I'm pleased to announce that the 'ResNet strikes back' paper is now on arxiv! Moving the baseline forward to 80.4% top-1 for a vanilla ResNet-50 arch w/ better training recipes. No extra data, no distillation. <a href="https://t.co/WP3UDXfV0r">https://t.co/WP3UDXfV0r</a>
</p>
— Ross Wightman (<span class="citation" data-cites="wightmanr">@wightmanr</span>) <a href="https://twitter.com/wightmanr/status/1444852719773122565?ref_src=twsrc%5Etfw">October 4, 2021</a>
</blockquote>
<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
</section>
</section>
<section id="best-practices" class="level3">
<h3 class="anchored" data-anchor-id="best-practices">Best practices</h3>
<div class="callout callout-style-default callout-tip 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">
Tip
</div>
</div>
<div class="callout-body-container callout-body">
<p>Start with a smaller ResNet (like 18 or 34) and move up as needed.</p>
</div>
</div>
<div class="callout callout-style-default 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">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>If you have a lot of data, the bigger resnets will likely give you better results.</p>
</div>
</div>
</section>
<section id="an-example" class="level3">
<h3 class="anchored" data-anchor-id="an-example">An example</h3>
<section id="step-1-build-our-dataloaders" class="level4">
<h4 class="anchored" data-anchor-id="step-1-build-our-dataloaders">Step 1: Build our DataLoaders</h4>
<div id="cell-16" class="cell" data-outputid="7c94f250-1dd0-4e44-d946-1a6fd8dcd745" data-vscode="{&quot;languageId&quot;:&quot;python&quot;}">
<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">path <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> untar_data(URLs.PETS)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'images'</span></span>
<span id="cb3-2"></span>
<span id="cb3-3"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> is_cat(x): </span>
<span id="cb3-4">  <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> x[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>].isupper()                  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># if filename is Capitalized, its a cat image</span></span>
<span id="cb3-5"></span>
<span id="cb3-6">dls <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> ImageDataLoaders.from_name_func(</span>
<span id="cb3-7">    path,                                <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># where our image are</span></span>
<span id="cb3-8">    get_image_files(path),               <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># how to build our inputs (our x)</span></span>
<span id="cb3-9">    label_func<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>is_cat,                   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># how to build our labels (our y)</span></span>
<span id="cb3-10">    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>,                       <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># how to build our validation set</span></span>
<span id="cb3-11">    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;">224</span>),               <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># things we want to do to each image when we fetch it</span></span>
<span id="cb3-12">    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 class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># for reproducibility</span></span>
<span id="cb3-13">)</span></code></pre></div>
</div>
<p><strong>Why do we make images 224x224 pixels?</strong></p>
<p>“This is the standard size for historical reasons (old pretrained models require this size exactly) … If you increase the size, you’ll often get a model with better results since it will be able to focus on more details.”</p>
<div class="callout callout-style-default callout-tip 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">
Tip
</div>
</div>
<div class="callout-body-container callout-body">
<p>Train on progressively larger image sizes using the weights trained on smaller sizes as a kind of pretrained model.</p>
</div>
</div>
</section>
<section id="step-2-build-our-cnn_learner" class="level4">
<h4 class="anchored" data-anchor-id="step-2-build-our-cnn_learner">Step 2: Build our <code>cnn_learner</code></h4>
<div id="cell-19" class="cell" data-outputid="65ca78ab-9fdd-4283-c8d5-cc3026f24940" data-vscode="{&quot;languageId&quot;:&quot;python&quot;}">
<div class="sourceCode cell-code" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb4-1">learn <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> cnn_learner(dls, resnet18, metrics<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>error_rate)</span></code></pre></div>
</div>
</section>
<section id="step-3-train" class="level4">
<h4 class="anchored" data-anchor-id="step-3-train">Step 3: Train</h4>
<div id="cell-21" class="cell" data-outputid="c35f0dd7-aa4b-47ed-e702-668516673ed2" data-vscode="{&quot;languageId&quot;:&quot;python&quot;}">
<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">learn.fine_tune(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span></code></pre></div>
<div class="cell-output cell-output-display">
<table class="dataframe caption-top table table-sm table-striped small" data-quarto-postprocess="true" 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.149967</td>
<td>0.042716</td>
<td>0.015562</td>
<td>01:16</td>
</tr>
</tbody>
</table>
</div>
<div class="cell-output cell-output-display">
<table class="dataframe caption-top table table-sm table-striped small" data-quarto-postprocess="true" 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.054710</td>
<td>0.021014</td>
<td>0.008119</td>
<td>01:07</td>
</tr>
</tbody>
</table>
</div>
</div>
</section>
</section>
</section>
<section id="visualizing-what-a-nn-is-learning" class="level2">
<h2 class="anchored" data-anchor-id="visualizing-what-a-nn-is-learning">Visualizing what a NN is learning</h2>
<section id="why-is-it-important" class="level3">
<h3 class="anchored" data-anchor-id="why-is-it-important">Why is it important?</h3>
<p>Because it allows you to know both what your NN is doing/learning and whether it is learning anything at all. The former is helpful because it gives you confidence that your model is learning to look at the right information and insights on how to improve it, the later because a model that isn’t learning anything (e.g., able to update its parameters so as to improve itself) isn’t a helpful or useful model.</p>
<div class="callout callout-style-default callout-tip 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">
Tip
</div>
</div>
<div class="callout-body-container callout-body">
<p>Learn how to visualize and understand your activations and gradients</p>
</div>
</div>
</section>
<section id="computer-vision-models" class="level3">
<h3 class="anchored" data-anchor-id="computer-vision-models">Computer vision models</h3>
<p>The top of this image is a visualization of the weights (what the model is learning), and the one below is a visualization of the activations, in particular, the parts of training images that most strongly match each set of weights above.</p>
<p><img src="https://github.com/fastai/fastbook/raw/e57e3155824c81a54f915edf9505f64d5ccdad84/images/layer1.png" class="img-fluid"></p>
<div class="callout callout-style-default callout-tip 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">
Tip
</div>
</div>
<div class="callout-body-container callout-body">
<p>This kind of visualization is particularly helpful in transfer learning as it allows us to infer which layers may require more or less training for our task. For example, the layer above probably requires little to no training as it looks to be identifying edges and gradients, thing likely helpful and necessary for all computer vision tasks.</p>
</div>
</div>
<section id="examples-1" class="level4">
<h4 class="anchored" data-anchor-id="examples-1">Examples</h4>
<p><strong>Vectors into 2D grayscale images (MNIST)</strong></p>
<p>*Courtesy of Abishek Thakur’s, “Approaching (almost) any Machine Learning Problem”</p>
<div id="cell-23" class="cell" data-outputid="06cb9cfc-db2f-4343-a875-ed564c9ab7fc" data-vscode="{&quot;languageId&quot;:&quot;python&quot;}">
<div class="sourceCode cell-code" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb6-1">inputs, targets <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> datasets.fetch_openml(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'mnist_784'</span>, version<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>, return_X_y<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>, as_frame<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="cb6-2">targets <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> targets.astype(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>)</span>
<span id="cb6-3"></span>
<span id="cb6-4">inputs.shape, targets.shape <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># always helpful to see the shape of things</span></span></code></pre></div>
<div class="cell-output cell-output-display" data-execution_count="7">
<pre><code>((70000, 784), (70000,))</code></pre>
</div>
</div>
<div id="cell-24" class="cell" data-outputid="d8b09f44-1fc4-46b7-a841-ab372d2e0023" data-vscode="{&quot;languageId&quot;:&quot;python&quot;}">
<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"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Here we are using a numpy array, but if you're using Pytorch, you could use either .view or .reshape</span></span>
<span id="cb8-2"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># see https://stackoverflow.com/questions/49643225/whats-the-difference-between-reshape-and-view-in-pytorch</span></span>
<span id="cb8-3">images <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> inputs.reshape((<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;">28</span>,<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">28</span>))</span>
<span id="cb8-4"></span>
<span id="cb8-5"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(images.shape)</span>
<span id="cb8-6">plt.imshow(images[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>], 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;">'gray'</span>)</span></code></pre></div>
<div class="cell-output cell-output-stdout">
<pre><code>(70000, 28, 28)</code></pre>
</div>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://ohmeow.com/posts/2020-11-06-ajtfb-chapter-1_files/figure-html/cell-9-output-2.png" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
<p><strong>Vectors as clusters (MNIST)</strong></p>
<p>*Courtesy of Abishek Thakur’s, “Approaching (almost) any Machine Learning Problem”</p>
<div id="cell-26" class="cell" data-outputid="dc76ea93-22b5-4350-9188-45db3ba82be4" data-vscode="{&quot;languageId&quot;:&quot;python&quot;}">
<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">tsne <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> manifold.TSNE(n_components<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>, random_state<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="cb10-2">transformed_data <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tsne.fit_transform(inputs[:<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1000</span>]) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># reduces dimensionality of each vector to 2</span></span></code></pre></div>
<div class="cell-output cell-output-stderr">
<pre><code>/usr/local/lib/python3.7/dist-packages/sklearn/manifold/_t_sne.py:783: FutureWarning: The default initialization in TSNE will change from 'random' to 'pca' in 1.2.
  FutureWarning,
/usr/local/lib/python3.7/dist-packages/sklearn/manifold/_t_sne.py:793: FutureWarning: The default learning rate in TSNE will change from 200.0 to 'auto' in 1.2.
  FutureWarning,</code></pre>
</div>
</div>
<div id="cell-27" class="cell" data-outputid="7c102590-29d8-4d01-f46f-be0e7abd4186" data-vscode="{&quot;languageId&quot;:&quot;python&quot;}">
<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">cluster_data <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> np.column_stack((transformed_data, targets[:<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1000</span>]))</span>
<span id="cb12-2">cluster_data.shape <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># transformed_data 2 dims (call them x and y) + targets 1 dim = 3</span></span></code></pre></div>
<div class="cell-output cell-output-display" data-execution_count="10">
<pre><code>(1000, 3)</code></pre>
</div>
</div>
<div id="cell-28" class="cell" data-outputid="e85efd0a-fe92-46f2-e3f2-00942ebf52d4" data-vscode="{&quot;languageId&quot;:&quot;python&quot;}">
<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">tsne_df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> pd.DataFrame(cluster_data, columns<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'x'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'y'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'targets'</span>])</span>
<span id="cb14-2"><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;">len</span>(tsne_df))</span>
<span id="cb14-3">tsne_df.head(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)</span></code></pre></div>
<div class="cell-output cell-output-stdout">
<pre><code>1000</code></pre>
</div>
<div class="cell-output cell-output-display" data-execution_count="11">

  <div id="df-e67f81c6-d022-4177-a2c5-81373d9c5324">
    <div class="colab-df-container">
      <div>


<table class="dataframe caption-top table table-sm table-striped small" data-quarto-postprocess="true" data-border="1">
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th">x</th>
<th data-quarto-table-cell-role="th">y</th>
<th data-quarto-table-cell-role="th">targets</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td data-quarto-table-cell-role="th">0</td>
<td>22.735518</td>
<td>14.271368</td>
<td>5.0</td>
</tr>
<tr class="even">
<td data-quarto-table-cell-role="th">1</td>
<td>45.913292</td>
<td>0.439934</td>
<td>0.0</td>
</tr>
</tbody>
</table>

</div>
      <button class="colab-df-convert" onclick="convertToInteractive('df-e67f81c6-d022-4177-a2c5-81373d9c5324')" title="Convert this dataframe to an interactive table." style="display:none;">
        
  <svg xmlns="http://www.w3.org/2000/svg" height="24px" viewbox="0 0 24 24" width="24px">
    <path d="M0 0h24v24H0V0z" fill="none"></path>
    <path d="M18.56 5.44l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94zm-11 1L8.5 8.5l.94-2.06 2.06-.94-2.06-.94L8.5 2.5l-.94 2.06-2.06.94zm10 10l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94z"></path><path d="M17.41 7.96l-1.37-1.37c-.4-.4-.92-.59-1.43-.59-.52 0-1.04.2-1.43.59L10.3 9.45l-7.72 7.72c-.78.78-.78 2.05 0 2.83L4 21.41c.39.39.9.59 1.41.59.51 0 1.02-.2 1.41-.59l7.78-7.78 2.81-2.81c.8-.78.8-2.07 0-2.86zM5.41 20L4 18.59l7.72-7.72 1.47 1.35L5.41 20z"></path>
  </svg>
      </button>
      
  <style>
    .colab-df-container {
      display:flex;
      flex-wrap:wrap;
      gap: 12px;
    }

    .colab-df-convert {
      background-color: #E8F0FE;
      border: none;
      border-radius: 50%;
      cursor: pointer;
      display: none;
      fill: #1967D2;
      height: 32px;
      padding: 0 0 0 0;
      width: 32px;
    }

    .colab-df-convert:hover {
      background-color: #E2EBFA;
      box-shadow: 0px 1px 2px rgba(60, 64, 67, 0.3), 0px 1px 3px 1px rgba(60, 64, 67, 0.15);
      fill: #174EA6;
    }

    [theme=dark] .colab-df-convert {
      background-color: #3B4455;
      fill: #D2E3FC;
    }

    [theme=dark] .colab-df-convert:hover {
      background-color: #434B5C;
      box-shadow: 0px 1px 3px 1px rgba(0, 0, 0, 0.15);
      filter: drop-shadow(0px 1px 2px rgba(0, 0, 0, 0.3));
      fill: #FFFFFF;
    }
  </style>

      <script>
        const buttonEl =
          document.querySelector('#df-e67f81c6-d022-4177-a2c5-81373d9c5324 button.colab-df-convert');
        buttonEl.style.display =
          google.colab.kernel.accessAllowed ? 'block' : 'none';

        async function convertToInteractive(key) {
          const element = document.querySelector('#df-e67f81c6-d022-4177-a2c5-81373d9c5324');
          const dataTable =
            await google.colab.kernel.invokeFunction('convertToInteractive',
                                                     [key], {});
          if (!dataTable) return;

          const docLinkHtml = 'Like what you see? Visit the ' +
            '<a target="_blank" href=https://colab.research.google.com/notebooks/data_table.ipynb>data table notebook</a>'
            + ' to learn more about interactive tables.';
          element.innerHTML = '';
          dataTable['output_type'] = 'display_data';
          await google.colab.output.renderOutput(dataTable, element);
          const docLink = document.createElement('div');
          docLink.innerHTML = docLinkHtml;
          element.appendChild(docLink);
        }
      </script>
    </div>
  </div>
  
</div>
</div>
<div id="cell-29" class="cell" data-outputid="4ee7b553-f4e1-4bfd-ec83-fda51f50d789" data-vscode="{&quot;languageId&quot;:&quot;python&quot;}">
<div class="sourceCode cell-code" id="cb16" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb16-1">viz <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> sns.FacetGrid(tsne_df, hue<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'targets'</span>, height<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="cb16-2">viz.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">map</span>(plt.scatter, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'x'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'y'</span>).add_legend()</span></code></pre></div>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://ohmeow.com/posts/2020-11-06-ajtfb-chapter-1_files/figure-html/cell-13-output-1.png" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
</section>
</section>
</section>
<section id="resources" class="level2">
<h2 class="anchored" data-anchor-id="resources">Resources</h2>
<ol type="1">
<li><p>https://book.fast.ai - The book’s website; it’s updated regularly with new content and recommendations from everything to GPUs to use, how to run things locally and on the cloud, etc…</p></li>
<li><p>https://course.fast.ai/datasets - A variety of slimmed down datasets you can use for various DL tasks that support “rapid prototyping and experimentation.”</p></li>
<li><p>https://huggingface.co/docs/datasets/ - Serves a similar purpose to the fastai datasets but for the NLP domain. Includes metrics and full/sub-set datasets that you can use to benchmark your results against the top guns of deep learning.</p></li>
</ol>
<div class="callout callout-style-default callout-important 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">
Important
</div>
</div>
<div class="callout-body-container callout-body">
<p>Start with a smaller dataset and scale up to full size to accelerate modeling!</p>
</div>
</div>


</section>

 ]]></description>
  <category>fastai</category>
  <category>fastbook</category>
  <guid>https://ohmeow.com/posts/2020-11-06-ajtfb-chapter-1.html</guid>
  <pubDate>Fri, 06 Nov 2020 08:00:00 GMT</pubDate>
  <media:content url="https://ohmeow.com/posts/images/fastbook.jpg" medium="image" type="image/jpeg"/>
</item>
<item>
  <title>Summarization with blurr</title>
  <dc:creator>Wayde Gilliam</dc:creator>
  <link>https://ohmeow.com/posts/2020-05-23-text-generation-with-blurr.html</link>
  <description><![CDATA[ 




<div id="cell-1" class="cell" data-outputid="3ac2d826-5cf1-4e6b-c64f-6e996e2be933" data-execution_count="1">
<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;"># only run this cell if you are in collab</span></span>
<span id="cb1-2"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># !pip install transformers -Uqq</span></span>
<span id="cb1-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># !pip install datasets -Uqq</span></span>
<span id="cb1-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># !pip install bert-score -Uqq</span></span>
<span id="cb1-5"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># !pip install sacremoses</span></span>
<span id="cb1-6"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># !pip install ohmeow-blurr -Uqq</span></span></code></pre></div>
<div class="cell-output cell-output-stdout">
<pre><code>Requirement already satisfied: sacremoses in /usr/local/lib/python3.7/dist-packages (0.0.53)
Requirement already satisfied: tqdm in /usr/local/lib/python3.7/dist-packages (from sacremoses) (4.64.0)
Requirement already satisfied: joblib in /usr/local/lib/python3.7/dist-packages (from sacremoses) (1.1.0)
Requirement already satisfied: regex in /usr/local/lib/python3.7/dist-packages (from sacremoses) (2019.12.20)
Requirement already satisfied: click in /usr/local/lib/python3.7/dist-packages (from sacremoses) (7.1.2)
Requirement already satisfied: six in /usr/local/lib/python3.7/dist-packages (from sacremoses) (1.15.0)</code></pre>
</div>
</div>
<div id="cell-2" class="cell" data-outputid="a691ab48-3e25-442e-9c8e-79afefa3fd47" data-execution_count="2">
<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> datasets</span>
<span id="cb3-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> pandas <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> pd</span>
<span id="cb3-3"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> fastai.text.<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-4"><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> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span></span>
<span id="cb3-5"></span>
<span id="cb3-6"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> blurr.text.data.<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-7"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> blurr.text.modeling.<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-8"></span>
<span id="cb3-9"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> nltk</span>
<span id="cb3-10">nltk.download(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'punkt'</span>, quiet<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 class="cell-output cell-output-display" data-execution_count="2">
<pre><code>True</code></pre>
</div>
</div>
<section id="data-preparation" class="level2">
<h2 class="anchored" data-anchor-id="data-preparation">Data Preparation</h2>
<p>We’re going to use to use the <a href="https://huggingface.co/datasets">datasets</a> library from huggingface to grab your raw data. This package gives you access to all kinds of NLP related datasets, explanations of each, and various task specific metrics to use in evaluating your model. The best part being everything comes down to you in JSON! This makes it a breeze to get up and running quickly!</p>
<p>We’ll just use a subset of the training set to build both our training and validation DataLoaders</p>
<div id="cell-6" class="cell" data-outputid="8a736f83-88e1-4373-bba3-145403175329" data-execution_count="3">
<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">raw_data <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> datasets.load_dataset(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'cnn_dailymail'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'3.0.0'</span>, split<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'train[:1%]'</span>)</span></code></pre></div>
<div class="cell-output cell-output-stderr">
<pre><code>Reusing dataset cnn_dailymail (/root/.cache/huggingface/datasets/cnn_dailymail/3.0.0/3.0.0/1b3c71476f6d152c31c1730e83ccb08bcf23e348233f4fcc11e182248e6bf7de)</code></pre>
</div>
</div>
<div id="cell-7" class="cell" data-outputid="2bd4fdb5-f195-4e5f-d462-19a51e668018" data-execution_count="4">
<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">df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> pd.DataFrame(raw_data)</span>
<span id="cb7-2">df.head()</span></code></pre></div>
<div class="cell-output cell-output-display" data-execution_count="4">

  <div id="df-a29154ff-c887-4abf-8a43-9c0b81d21357">
    <div class="colab-df-container">
      <div>


<table class="dataframe caption-top table table-sm table-striped small" data-quarto-postprocess="true" data-border="1">
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th">article</th>
<th data-quarto-table-cell-role="th">highlights</th>
<th data-quarto-table-cell-role="th">id</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td data-quarto-table-cell-role="th">0</td>
<td>LONDON, England (Reuters) -- Harry Potter star Daniel Radcliffe gains access to a reported £20 million ($41.1 million) fortune as he turns 18 on Monday, but he insists the money won't cast a spell on him. Daniel Radcliffe as Harry Potter in "Harry Potter and the Order of the Phoenix" To the disappointment of gossip columnists around the world, the young actor says he has no plans to fritter his cash away on fast cars, drink and celebrity parties. "I don't plan to be one of those people who, as soon as they turn 18, suddenly buy themselves a massive sports car collection or something simila...</td>
<td>Harry Potter star Daniel Radcliffe gets £20M fortune as he turns 18 Monday .\nYoung actor says he has no plans to fritter his cash away .\nRadcliffe's earnings from first five Potter films have been held in trust fund .</td>
<td>42c027e4ff9730fbb3de84c1af0d2c506e41c3e4</td>
</tr>
<tr class="even">
<td data-quarto-table-cell-role="th">1</td>
<td>Editor's note: In our Behind the Scenes series, CNN correspondents share their experiences in covering news and analyze the stories behind the events. Here, Soledad O'Brien takes users inside a jail where many of the inmates are mentally ill. An inmate housed on the "forgotten floor," where many mentally ill inmates are housed in Miami before trial. MIAMI, Florida (CNN) -- The ninth floor of the Miami-Dade pretrial detention facility is dubbed the "forgotten floor." Here, inmates with the most severe mental illnesses are incarcerated until they're ready to appear in court. Most often, they...</td>
<td>Mentally ill inmates in Miami are housed on the "forgotten floor"\nJudge Steven Leifman says most are there as a result of "avoidable felonies"\nWhile CNN tours facility, patient shouts: "I am the son of the president"\nLeifman says the system is unjust and he's fighting for change .</td>
<td>ee8871b15c50d0db17b0179a6d2beab35065f1e9</td>
</tr>
<tr class="odd">
<td data-quarto-table-cell-role="th">2</td>
<td>MINNEAPOLIS, Minnesota (CNN) -- Drivers who were on the Minneapolis bridge when it collapsed told harrowing tales of survival. "The whole bridge from one side of the Mississippi to the other just completely gave way, fell all the way down," survivor Gary Babineau told CNN. "I probably had a 30-, 35-foot free fall. And there's cars in the water, there's cars on fire. The whole bridge is down." He said his back was injured but he determined he could move around. "I realized there was a school bus right next to me, and me and a couple of other guys went over and started lifting the kids off t...</td>
<td>NEW: "I thought I was going to die," driver says .\nMan says pickup truck was folded in half; he just has cut on face .\nDriver: "I probably had a 30-, 35-foot free fall"\nMinnesota bridge collapsed during rush hour Wednesday .</td>
<td>06352019a19ae31e527f37f7571c6dd7f0c5da37</td>
</tr>
<tr class="even">
<td data-quarto-table-cell-role="th">3</td>
<td>WASHINGTON (CNN) -- Doctors removed five small polyps from President Bush's colon on Saturday, and "none appeared worrisome," a White House spokesman said. The polyps were removed and sent to the National Naval Medical Center in Bethesda, Maryland, for routine microscopic examination, spokesman Scott Stanzel said. Results are expected in two to three days. All were small, less than a centimeter [half an inch] in diameter, he said. Bush is in good humor, Stanzel said, and will resume his activities at Camp David. During the procedure Vice President Dick Cheney assumed presidential power. Bu...</td>
<td>Five small polyps found during procedure; "none worrisome," spokesman says .\nPresident reclaims powers transferred to vice president .\nBush undergoes routine colonoscopy at Camp David .</td>
<td>24521a2abb2e1f5e34e6824e0f9e56904a2b0e88</td>
</tr>
<tr class="odd">
<td data-quarto-table-cell-role="th">4</td>
<td>(CNN) -- The National Football League has indefinitely suspended Atlanta Falcons quarterback Michael Vick without pay, officials with the league said Friday. NFL star Michael Vick is set to appear in court Monday. A judge will have the final say on a plea deal. Earlier, Vick admitted to participating in a dogfighting ring as part of a plea agreement with federal prosecutors in Virginia. "Your admitted conduct was not only illegal, but also cruel and reprehensible. Your team, the NFL, and NFL fans have all been hurt by your actions," NFL Commissioner Roger Goodell said in a letter to Vick....</td>
<td>NEW: NFL chief, Atlanta Falcons owner critical of Michael Vick's conduct .\nNFL suspends Falcons quarterback indefinitely without pay .\nVick admits funding dogfighting operation but says he did not gamble .\nVick due in federal court Monday; future in NFL remains uncertain .</td>
<td>7fe70cc8b12fab2d0a258fababf7d9c6b5e1262a</td>
</tr>
</tbody>
</table>

</div>
      <button class="colab-df-convert" onclick="convertToInteractive('df-a29154ff-c887-4abf-8a43-9c0b81d21357')" title="Convert this dataframe to an interactive table." style="display:none;">
        
  <svg xmlns="http://www.w3.org/2000/svg" height="24px" viewbox="0 0 24 24" width="24px">
    <path d="M0 0h24v24H0V0z" fill="none"></path>
    <path d="M18.56 5.44l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94zm-11 1L8.5 8.5l.94-2.06 2.06-.94-2.06-.94L8.5 2.5l-.94 2.06-2.06.94zm10 10l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94z"></path><path d="M17.41 7.96l-1.37-1.37c-.4-.4-.92-.59-1.43-.59-.52 0-1.04.2-1.43.59L10.3 9.45l-7.72 7.72c-.78.78-.78 2.05 0 2.83L4 21.41c.39.39.9.59 1.41.59.51 0 1.02-.2 1.41-.59l7.78-7.78 2.81-2.81c.8-.78.8-2.07 0-2.86zM5.41 20L4 18.59l7.72-7.72 1.47 1.35L5.41 20z"></path>
  </svg>
      </button>
      
  <style>
    .colab-df-container {
      display:flex;
      flex-wrap:wrap;
      gap: 12px;
    }

    .colab-df-convert {
      background-color: #E8F0FE;
      border: none;
      border-radius: 50%;
      cursor: pointer;
      display: none;
      fill: #1967D2;
      height: 32px;
      padding: 0 0 0 0;
      width: 32px;
    }

    .colab-df-convert:hover {
      background-color: #E2EBFA;
      box-shadow: 0px 1px 2px rgba(60, 64, 67, 0.3), 0px 1px 3px 1px rgba(60, 64, 67, 0.15);
      fill: #174EA6;
    }

    [theme=dark] .colab-df-convert {
      background-color: #3B4455;
      fill: #D2E3FC;
    }

    [theme=dark] .colab-df-convert:hover {
      background-color: #434B5C;
      box-shadow: 0px 1px 3px 1px rgba(0, 0, 0, 0.15);
      filter: drop-shadow(0px 1px 2px rgba(0, 0, 0, 0.3));
      fill: #FFFFFF;
    }
  </style>

      <script>
        const buttonEl =
          document.querySelector('#df-a29154ff-c887-4abf-8a43-9c0b81d21357 button.colab-df-convert');
        buttonEl.style.display =
          google.colab.kernel.accessAllowed ? 'block' : 'none';

        async function convertToInteractive(key) {
          const element = document.querySelector('#df-a29154ff-c887-4abf-8a43-9c0b81d21357');
          const dataTable =
            await google.colab.kernel.invokeFunction('convertToInteractive',
                                                     [key], {});
          if (!dataTable) return;

          const docLinkHtml = 'Like what you see? Visit the ' +
            '<a target="_blank" href=https://colab.research.google.com/notebooks/data_table.ipynb>data table notebook</a>'
            + ' to learn more about interactive tables.';
          element.innerHTML = '';
          dataTable['output_type'] = 'display_data';
          await google.colab.output.renderOutput(dataTable, element);
          const docLink = document.createElement('div');
          docLink.innerHTML = docLinkHtml;
          element.appendChild(docLink);
        }
      </script>
    </div>
  </div>
  
</div>
</div>
<p>We begin by getting our hugginface objects needed for this task (e.g., the architecture, tokenizer, config, and model). We’ll use blurr’s <code>get_hf_objects</code> helper method here.</p>
<div id="cell-9" class="cell" data-outputid="57bf4163-1a4d-46e4-fedf-bb7d5d3d07f0" data-execution_count="5">
<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">pretrained_model_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;">"facebook/bart-large-cnn"</span></span>
<span id="cb8-2">hf_arch, hf_config, hf_tokenizer, hf_model <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> get_hf_objects(pretrained_model_name, model_cls<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>BartForConditionalGeneration)</span>
<span id="cb8-3"></span>
<span id="cb8-4">hf_arch, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">type</span>(hf_config), <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">type</span>(hf_tokenizer), <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">type</span>(hf_model)</span></code></pre></div>
<div class="cell-output cell-output-display" data-execution_count="5">
<pre><code>('bart',
 transformers.models.bart.configuration_bart.BartConfig,
 transformers.models.bart.tokenization_bart_fast.BartTokenizerFast,
 transformers.models.bart.modeling_bart.BartForConditionalGeneration)</code></pre>
</div>
</div>
<p>Next we need to build out our DataBlock. Remember tha a DataBlock is a blueprint describing how to move your raw data into something modelable. That blueprint is executed when we pass it a data source, which in our case, will be the DataFrame we created above. We’ll use a random subset to get things moving along a bit faster for the demo as well.</p>
<p>Notice that the blurr DataBlock as been dramatically simplified given the shift to on-the-fly batch-time tokenization. All we need is to define a single <code>Seq2SeqBatchTokenizeTransform</code> instance, optionally passing a list to any of the tokenization arguments to differentiate the values for the input and summary sequences. In addition to specifying a custom max length for the inputs, we can also do the same for the output sequences … and with the latest release of blurr, we can even customize the text generation by passing in <code>text_gen_kwargs</code>.</p>
<p>We pass <code>noop</code> as a type transform for our targets because everything is already handled by the batch transform now.</p>
<div id="cell-11" class="cell" data-outputid="dd3f5033-53a8-4bf2-f807-b7c9ed0ce9d3" data-execution_count="6">
<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">text_gen_kwargs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> default_text_gen_kwargs(hf_config, hf_model, task<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'summarization'</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> text_gen_kwargs</span></code></pre></div>
<div class="cell-output cell-output-display" data-execution_count="6">
<pre><code>{'bad_words_ids': None,
 'bos_token_id': 0,
 'decoder_start_token_id': 2,
 'diversity_penalty': 0.0,
 'do_sample': False,
 'early_stopping': True,
 'encoder_no_repeat_ngram_size': 0,
 'eos_token_id': 2,
 'exponential_decay_length_penalty': None,
 'forced_bos_token_id': 0,
 'forced_eos_token_id': 2,
 'length_penalty': 2.0,
 'max_length': 142,
 'min_length': 56,
 'no_repeat_ngram_size': 3,
 'num_beam_groups': 1,
 'num_beams': 4,
 'num_return_sequences': 1,
 'output_attentions': False,
 'output_hidden_states': False,
 'output_scores': False,
 'pad_token_id': 1,
 'remove_invalid_values': False,
 'repetition_penalty': 1.0,
 'return_dict_in_generate': False,
 'temperature': 1.0,
 'top_k': 50,
 'top_p': 1.0,
 'typical_p': 1.0,
 'use_cache': True}</code></pre>
</div>
</div>
<div id="cell-12" class="cell" data-execution_count="7">
<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">hf_batch_tfm <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> Seq2SeqBatchTokenizeTransform(</span>
<span id="cb12-2">    hf_arch, hf_config, hf_tokenizer, hf_model, max_length<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;">256</span>, max_tgt_length<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;">130</span>, text_gen_kwargs<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>text_gen_kwargs</span>
<span id="cb12-3">)</span>
<span id="cb12-4"></span>
<span id="cb12-5">blocks <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (Seq2SeqTextBlock(batch_tokenize_tfm<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>hf_batch_tfm), noop)</span>
<span id="cb12-6">dblock <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> DataBlock(blocks<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>blocks, get_x<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>ColReader(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'article'</span>), get_y<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>ColReader(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'highlights'</span>), splitter<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>RandomSplitter())</span></code></pre></div>
</div>
<div id="cell-13" class="cell" data-execution_count="8">
<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">dls <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> dblock.dataloaders(df, 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></code></pre></div>
</div>
<div id="cell-14" class="cell" data-outputid="0cb4e60e-9ec6-4da6-fb8d-45abbc8fca49" data-execution_count="9">
<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"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(dls.train.items), <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(dls.valid.items)</span></code></pre></div>
<div class="cell-output cell-output-display" data-execution_count="9">
<pre><code>(2297, 574)</code></pre>
</div>
</div>
<p>It’s always a good idea to check out a batch of data and make sure the shapes look right.</p>
<div id="cell-16" class="cell" data-outputid="740b2d02-e8fe-401b-8dce-6c5119509fe7" data-execution_count="10">
<div class="sourceCode cell-code" id="cb16" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb16-1">b <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> dls.one_batch()</span>
<span id="cb16-2"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(b), b[<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;">'input_ids'</span>].shape, b[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>].shape</span></code></pre></div>
<div class="cell-output cell-output-display" data-execution_count="10">
<pre><code>(2, torch.Size([2, 256]), torch.Size([2, 66]))</code></pre>
</div>
</div>
<p>Even better, we can take advantage of blurr’s TypeDispatched version of <code>show_batch</code> to look at things a bit more intuitively. We pass in the <code>dls</code> via the <code>dataloaders</code> argument so we can access all tokenization/modeling configuration stored in our batch transform above.</p>
<div id="cell-18" class="cell" data-outputid="67b5a2d7-81bc-4cae-c5af-147fd7e1c2c8" data-execution_count="11">
<div class="sourceCode cell-code" id="cb18" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb18-1">dls.show_batch(dataloaders<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>dls, 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;">2</span>)</span></code></pre></div>
<div class="cell-output cell-output-display">
<table class="dataframe caption-top table table-sm table-striped small" data-quarto-postprocess="true" data-border="1">
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th">text</th>
<th data-quarto-table-cell-role="th">target</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td data-quarto-table-cell-role="th">0</td>
<td>&lt;s&gt; You wanted to know more about greenwashing, and Scot Case, from environmental marketing firm TerraChoice, answered. Greenwashing expert Scot Case of TerraChoice. "Why are green products often more expensive than ones that don't say they are green or environmentally friendly? Is it just because green has become a new form of 'premium brand'? Isn't this bad news if we want to make more people environmentally aware when they go shopping?" Harriet Gladwell. Case: First, it should be noted that not all greener products are more expensive. The remanufactured toner cartridges I purchase at a nationwide office-supply store, for example, carry the same warranty as other cartridges at a 30-percent lower cost. This greener option is less expensive because the manufacturer avoids the cost of manufacturing the plastic and electronic components. They simply reuse the parts from recycled cartridges. There are also greener products that do not cost extra. There are cleaning products and paints, for example, that have been certified as meeting tough environmental standards by EcoLogo or Green Seal that deliver the same high-quality performance one expects without costing any extra. Other greener products might be slightly more expensive initially, but generate substantial savings for the consumer. Energy-efficient compact fluorescent lightbul&lt;/s&gt;</td>
<td>Scot Case answers your questions on greenwashing.\nHas green become a new form of "premium brand"?\nWhat green words and phrases should raise a red flag?\nClick here to read more answers to your questions.</td>
</tr>
<tr class="even">
<td data-quarto-table-cell-role="th">1</td>
<td>&lt;s&gt; (CNN) -- Commentators who have watched the conflict in Northern Ireland play out for decades call the peace process a miracle. Various leaders negotiated for years to bring an end to Northern Ireland's "troubles." Culminating in a power sharing deal between Ulster's unionists, led by Ian Paisley, and Sinn Fein, the political arm of the IRA (nationalists), led by Gerry Adams, the road to peace has been a torturous one characterized by violence, set-backs and numerous false starts. Only recently the Ulster Defence Association, Northern Ireland's largest loyalist group, said it will cease to be an armed paramilitary group, starting at midnight on November 11, saying the "war is over." "All weaponry will be put beyond use," Colin Halliday of the Ulster Political Research Group, which is linked to the group, said in a speech in Belfast aired by RTE, Ireland's state-owned broadcaster. "The struggle to maintain the union is on a new and more complex battlefield." The Irish Republican Army (IRA) disarmed two years ago, helping to restore the province's government in Belfast. Irish Prime Minister Bertie Ahern said the most recent moves of groups to disarm was "significant and hopefully signals a further step&lt;/s&gt;</td>
<td>Some commentators have called the peace process in Northern Ireland a "miracle"\nIt culminated in a power sharing deal between the Ulster's unionists and Sinn Fein.\nPeace and prosperity would not have occurred without diplomacy.</td>
</tr>
</tbody>
</table>
</div>
</div>
</section>
<section id="training" class="level2">
<h2 class="anchored" data-anchor-id="training">Training</h2>
<p>We’ll prepare our BART model for training by wrapping it in blurr’s <code>BaseModelWrapper</code> object and using the callback, <code>BaseModelCallback</code>, as usual. A new <code>Seq2SeqMetricsCallback</code> object allows us to specify Seq2Seq metrics we want to use, things like rouge and bertscore for tasks like summarization as well as metrics such as meteor, bleu, and sacrebleu for translations tasks. Using huggingface’s metrics library is as easy as specifying a metrics configuration such as below.</p>
<p>Once we have everything in place, we’ll freeze our model so that only the last layer group’s parameters of trainable. See <a href="https://docs.fast.ai/basic_train.html#Discriminative-layer-training">here</a> for our discriminitative learning rates work in fastai.</p>
<p><strong>Note:</strong> This has been tested with ALOT of other Seq2Seq models; see the docs for more information.</p>
<div id="cell-21" class="cell" data-execution_count="12">
<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">seq2seq_metrics <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {</span>
<span id="cb19-2">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'rouge'</span>: {</span>
<span id="cb19-3">            <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'compute_kwargs'</span>: { <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'rouge_types'</span>: [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"rouge1"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"rouge2"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"rougeL"</span>], <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'use_stemmer'</span>: <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span> },</span>
<span id="cb19-4">            <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'returns'</span>: [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"rouge1"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"rouge2"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"rougeL"</span>]</span>
<span id="cb19-5">        },</span>
<span id="cb19-6">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'bertscore'</span>: {</span>
<span id="cb19-7">            <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'compute_kwargs'</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;">'en'</span> },</span>
<span id="cb19-8">            <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'returns'</span>: [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"precision"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"recall"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"f1"</span>]</span>
<span id="cb19-9">        }</span>
<span id="cb19-10">    }</span></code></pre></div>
</div>
<div id="cell-22" class="cell" data-execution_count="13">
<div class="sourceCode cell-code" id="cb20" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb20-1">model <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> BaseModelWrapper(hf_model)</span>
<span id="cb20-2">learn_cbs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [BaseModelCallback]</span>
<span id="cb20-3">fit_cbs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [Seq2SeqMetricsCallback(custom_metrics<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>seq2seq_metrics)]</span>
<span id="cb20-4"></span>
<span id="cb20-5">learn <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> Learner(dls, </span>
<span id="cb20-6">                model,</span>
<span id="cb20-7">                opt_func<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>ranger,</span>
<span id="cb20-8">                loss_func<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>CrossEntropyLossFlat(),</span>
<span id="cb20-9">                cbs<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>learn_cbs,</span>
<span id="cb20-10">                splitter<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>partial(blurr_seq2seq_splitter, arch<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>hf_arch)).to_fp16()</span>
<span id="cb20-11"></span>
<span id="cb20-12">learn.create_opt() </span>
<span id="cb20-13">learn.freeze()</span></code></pre></div>
</div>
<p>Still experimenting with how to use fastai’s learning rate finder for these kinds of models. If you all have any suggestions or interesting insights to share, please let me know. We’re only going to train the frozen model for one epoch for this demo, but feel free to progressively unfreeze the model and train the other layers to see if you can best my results below.</p>
<div id="cell-24" class="cell" data-outputid="593f1808-246a-443f-e496-b3fd4b55b582" data-execution_count="14">
<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">learn.lr_find()</span></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-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-display" data-execution_count="14">
<pre><code>SuggestedLRs(valley=9.120108734350652e-05)</code></pre>
</div>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://ohmeow.com/posts/2020-05-23-text-generation-with-blurr_files/figure-html/cell-15-output-4.png" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
<p>It’s also not a bad idea to run a batch through your model and make sure the shape of what goes in, and comes out, looks right.</p>
<div id="cell-26" class="cell" data-outputid="ea067053-77fe-4579-b31b-081255c47214" data-execution_count="15">
<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">b <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> dls.one_batch()</span>
<span id="cb23-2">preds <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> learn.model(b[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>])</span>
<span id="cb23-3"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(preds),preds[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>], preds[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>].shape</span></code></pre></div>
<div class="cell-output cell-output-display" data-execution_count="15">
<pre><code>(3,
 tensor(3.7155, device='cuda:0', grad_fn=&lt;NllLossBackward0&gt;),
 torch.Size([2, 60, 50264]))</code></pre>
</div>
</div>
<div id="cell-27" class="cell" data-outputid="2b81f845-db0d-4e24-cbd0-afbcac35f705" data-execution_count="16">
<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">learn.fit_one_cycle(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, lr_max<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;">3e-5</span>, cbs<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>fit_cbs)</span></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-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-quarto-postprocess="true" 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">rouge1</th>
<th data-quarto-table-cell-role="th">rouge2</th>
<th data-quarto-table-cell-role="th">rougeL</th>
<th data-quarto-table-cell-role="th">bertscore_precision</th>
<th data-quarto-table-cell-role="th">bertscore_recall</th>
<th data-quarto-table-cell-role="th">bertscore_f1</th>
<th data-quarto-table-cell-role="th">time</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>0</td>
<td>1.717729</td>
<td>1.666989</td>
<td>0.390802</td>
<td>0.173328</td>
<td>0.270079</td>
<td>0.881220</td>
<td>0.898129</td>
<td>0.889528</td>
<td>16:32</td>
</tr>
</tbody>
</table>
</div>
<div class="cell-output cell-output-display">
<script type="application/vnd.jupyter.widget-view+json">
{"model_id":"d3714713b90146089001d89fc98f6f43","version_major":2,"version_minor":0,"quarto_mimetype":"application/vnd.jupyter.widget-view+json"}
</script>
</div>
<div class="cell-output cell-output-display">
<script type="application/vnd.jupyter.widget-view+json">
{"model_id":"48d126d3054349cb85f3c02c25880cdb","version_major":2,"version_minor":0,"quarto_mimetype":"application/vnd.jupyter.widget-view+json"}
</script>
</div>
<div class="cell-output cell-output-display">
<script type="application/vnd.jupyter.widget-view+json">
{"model_id":"a92845f968c1478db79dcb443ab00b12","version_major":2,"version_minor":0,"quarto_mimetype":"application/vnd.jupyter.widget-view+json"}
</script>
</div>
<div class="cell-output cell-output-display">
<script type="application/vnd.jupyter.widget-view+json">
{"model_id":"797f396dc0f645edbeabfe96abdb1b6f","version_major":2,"version_minor":0,"quarto_mimetype":"application/vnd.jupyter.widget-view+json"}
</script>
</div>
</div>
<p>And now we can look at the generated predictions using our <code>text_gen_kwargs</code> above</p>
<div id="cell-29" class="cell" data-outputid="3fb91e74-f01c-4c56-9003-158853429b13" data-execution_count="17">
<div class="sourceCode cell-code" id="cb26" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb26-1">learn.show_results(learner<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>learn, 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;">2</span>)</span></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-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-display">
<table class="dataframe caption-top table table-sm table-striped small" data-quarto-postprocess="true" data-border="1">
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th">text</th>
<th data-quarto-table-cell-role="th">target</th>
<th data-quarto-table-cell-role="th">prediction</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td data-quarto-table-cell-role="th">0</td>
<td>(CNN) -- To some, she was a lifelong role model. Others call Pakistan's former prime minister and the first female prime minister of any Muslim nation a source of inspiration to women everywhere. One I-Reporter acknowledges, "I never was a political supporter of Benazir Bhutto but now after her death I feel that her loss is a loss for Pakistan, not just her political supporters." Anthony G. Moore photographed Benazir Bhutto with her husband Asif Ali Zardari in New York in 2006. Benazir Bhutto was assassinated during a suicide bombing on December 27, 2007, and I-Reporters from all over the world responded with their memories and condolences. Below are selections, some of which have been edited for length and clarity. Farhad Sethi of Lahore, Pakistan Breathing in the air of grief and sadness, the nation suffers the loss of our beloved leader Benazir Bhutto, an institution in herself withstanding pressures at times when suicide bombing has become an unstoppable enigma. A sniper pierced a bullet through her neck and our enthusiastic leader couldn't even make it to the hospital, her last words God knows what were they but her face and inspirational personality will always be remembered. A</td>
<td>Former Pakistani Prime Minister Benazir Bhutto is assassinated.\nI-Reporters from around the world offer condolences, memories.\n"We Pakistanis are proud to acknowledge her," says one I-Reporter.\nI-Report: Share your memories, condolences, photos of Benazir Bhutto.</td>
<td>[ Benazir Bhutto was assassinated during a suicide bombing on December 27, 2007 .\nI-Reporters from all over the world responded with their memories and condolences .\n"Her loss is a loss for Pakistan, not just her political supporters," one I-Reporter said ., Men's college basketball season comes to an end with the NCAA Tournament .\nDuke University in Durham, North Carolina, and the University of North Carolina in Chapel Hill are two of the top basketball towns .\nCollege basketball is deeply rooted in North Carolina culture, thanks to the success of the two universities .\nNorth Carolina and Duke fans are passionate and passionate about the sport .\nThe sport has its roots in the YMCA, where James Naismith invented basketball .]</td>
</tr>
</tbody>
</table>
</div>
</div>
<p>Even better though, blurr augments the fastai Learner with a <code>blurr_summarize</code> method that allows you to use huggingface’s <code>PreTrainedModel.generate</code> method to create something more human-like.</p>
<div id="cell-31" class="cell" data-execution_count="18">
<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">test_article <span 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="cb27-2"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">The past 12 months have been the worst for aviation fatalities so far this decade - with the total of number of people killed if airline </span></span>
<span id="cb27-3"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">crashes reaching 1,050 even before the Air Asia plane vanished. Two incidents involving Malaysia Airlines planes - one over eastern Ukraine and the other in the Indian Ocean - led to the deaths of 537 people, while an Air Algerie crash in Mali killed 116 and TransAsia Airways crash in Taiwan killed a further 49 people. The remaining 456 fatalities were largely in incidents involving small commercial planes or private aircraft operating on behalf of companies, governments or organisations. Despite 2014 having the highest number of fatalities so far this decade, the total number of crashes was in fact the lowest since the first commercial jet airliner took off in 1949 - totalling just 111 across the whole world over the past 12 months. The all-time deadliest year for aviation was 1972 when a staggering 2,429 people were killed in a total of 55 plane crashes - including the crash of Aeroflot Flight 217, which killed 174 people in Russia, and Convair 990 Coronado, which claimed 155 lives in Spain. However this year's total death count of 1,212, including those presumed dead on board the missing Air Asia flight, marks a significant rise on the very low 265 fatalities in 2013 - which led to it being named the safest year in aviation since the end of the Second World War. Scroll down for videos. Deadly: The past 12 months have been the worst for aviation fatalities so far this decade - with the total of number of people killed if airline crashes reaching 1,158 even before the Air Asia plane (pictured) vanished. Fatal: Two incidents involving Malaysia Airlines planes - one over eastern Ukraine (pictured) and the other in the Indian Ocean - led to the deaths of 537 people. Surprising: Despite 2014 having the highest number of fatalities so far this decade, the total number of crashes was in fact the lowest since the first commercial jet airliner took off in 1949. 2014 has been a horrific year for Malaysia-based airlines, with 537 people dying on Malaysia Airlines planes, and a further 162 people missing and feared dead in this week's Air Asia incident. In total more than half the people killed in aviation incidents this year had been flying on board Malaysia-registered planes. In January a total of 12 people lost their lives in five separate incidents, while the same number of crashes in February killed 107. </span></span>
<span id="cb27-4"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"""</span></span></code></pre></div>
</div>
<p>We can override the <code>text_gen_kwargs</code> we specified for our <code>DataLoaders</code> when we generate text using blurr’s <code>Learner.blurr_generate</code> method</p>
<div id="cell-33" class="cell" data-outputid="9047bf01-481a-43fc-d7d1-7dd323ba6aad" data-execution_count="19">
<div class="sourceCode cell-code" id="cb28" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb28-1">outputs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> learn.blurr_summarize(test_article, early_stopping<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_beams<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>, num_return_sequences<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="cb28-2"></span>
<span id="cb28-3"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> idx, 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;">enumerate</span>(outputs):</span>
<span id="cb28-4">    <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'=== Prediction </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>idx<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="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="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>o<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></code></pre></div>
<div class="cell-output cell-output-stdout">
<pre><code>=== Prediction 1 ===
{'summary_texts': [' 2014 has been worst year for aviation fatalities so far this decade - with 1,158 deaths .\nTotal death count of 1,212, including those presumed dead on board missing Air Asia flight, marks a significant rise on the very low 265 fatalities in 2013 .\nThe total number of crashes was in fact the lowest since the first commercial jet airliner took off in 1949 - totalling just 111 across the whole world over the past 12 months .\nTwo incidents involving Malaysia Airlines planes - one over eastern Ukraine and the other in the Indian Ocean - led to the deaths of 537 people .', ' 2014 has been worst year for aviation fatalities so far this decade - with 1,158 deaths .\nTotal death count of 1,212, including those presumed dead on board missing Air Asia flight, marks a significant rise on the very low 265 fatalities in 2013 .\nThe total number of crashes was in fact the lowest since the first commercial jet airliner took off in 1949 - totalling just 111 across the whole world over the past 12 months .\n2014 has been a horrific year for Malaysia-based airlines, with 537 people dying on Malaysia Airlines planes .', ' 2014 has been worst year for aviation fatalities so far this decade - with 1,158 deaths .\nTotal death count of 1,212, including those presumed dead on board missing Air Asia flight, marks a significant rise on the very low 265 fatalities in 2013 .\nThe total number of crashes was in fact the lowest since the first commercial jet airliner took off in 1949 - totalling just 111 across the whole world over the past 12 months .']}
</code></pre>
</div>
</div>
<p>What about inference? Easy!</p>
<div id="cell-35" class="cell" data-execution_count="20">
<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">learn.metrics <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="cb30-2">learn.export(fname<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'ft_cnndm_export.pkl'</span>)</span></code></pre></div>
</div>
<div id="cell-36" class="cell" data-outputid="82239158-d744-4ebb-a567-d77f5e1a2d7a" data-execution_count="21">
<div class="sourceCode cell-code" id="cb31" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb31-1">inf_learn <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> load_learner(fname<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'ft_cnndm_export.pkl'</span>)</span>
<span id="cb31-2">inf_learn.blurr_summarize(test_article)</span></code></pre></div>
<div class="cell-output cell-output-display" data-execution_count="21">
<pre><code>[{'summary_texts': ' 2014 has been worst year for aviation fatalities so far this decade - with 1,158 deaths .\nTotal death count of 1,212, including those presumed dead on board missing Air Asia flight, marks a significant rise on the very low 265 fatalities in 2013 .\nThe total number of crashes was in fact the lowest since the first commercial jet airliner took off in 1949 - totalling just 111 across the whole world over the past 12 months .\nTwo incidents involving Malaysia Airlines planes - one over eastern Ukraine and the other in the Indian Ocean - led to the deaths of 537 people .'}]</code></pre>
</div>
</div>
</section>
<section id="thats-it" class="level2">
<h2 class="anchored" data-anchor-id="thats-it">That’s it</h2>
<p><a href="https://ohmeow.github.io/blurr/">blurr</a> supports a number of huggingface transformer model tasks in addition to summarization (e.g., sequence classification , token classification, and question/answering, causal language modeling, and transation). The docs include examples for each of these tasks if you’re curious to learn more.</p>
<p>For more information about ohmeow or to get in contact with me, head over to <a href="ohmeow.com">ohmeow.com</a> for all the details.</p>
<p>Thanks!</p>


</section>

 ]]></description>
  <category>fastai</category>
  <category>huggingface</category>
  <category>blurr</category>
  <category>summarization</category>
  <category>text generation</category>
  <guid>https://ohmeow.com/posts/2020-05-23-text-generation-with-blurr.html</guid>
  <pubDate>Sat, 23 May 2020 07:00:00 GMT</pubDate>
  <media:content url="https://ohmeow.com/posts/images/blurr-logo-small.png" medium="image" type="image/png" height="250" width="127"/>
</item>
</channel>
</rss>
