<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ fastai,  - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ fastai,  - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Fri, 26 Jun 2026 22:47:44 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/fastai/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ How to Use Fast.ai – A Beginner-Friendly Gateway to Deep Learning ]]>
                </title>
                <description>
                    <![CDATA[ Fast.ai is a user-friendly library that brings the power of deep learning to your fingertips, regardless of your skill level. Let’s learn how it works. Have you ever felt curious about deep learning but found the technical complexity overwhelming? Fa... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-use-fast-ai-for-beginners/</link>
                <guid isPermaLink="false">66d035eeec0a2e1087e82425</guid>
                
                    <category>
                        <![CDATA[ Deep Learning ]]>
                    </category>
                
                    <category>
                        <![CDATA[ fastai,  ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Manish Shivanandhan ]]>
                </dc:creator>
                <pubDate>Fri, 02 Feb 2024 00:10:29 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/01/Untitled-design.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Fast.ai is a user-friendly library that brings the power of deep learning to your fingertips, regardless of your skill level. Let’s learn how it works.</p>
<p>Have you ever felt curious about deep learning but found the technical complexity overwhelming? <a target="_blank" href="https://fast.ai/">Fast.ai</a> is your answer.</p>
<p>Fast.ai simplifies the journey into deep learning. It makes deep learning accessible to you even if you’re not a seasoned data scientist.</p>
<p>In this article, we’ll explore what Fast.ai is, why it stands out, and how you can get started with some basic code examples.</p>
<h2 id="heading-what-is-fastai">What is Fast.ai?</h2>
<p>Fast.ai is a library built on top of PyTorch, one of the leading deep-learning frameworks.</p>
<p>It’s designed to make deep learning more approachable. The library provides high-level components that make it easy to build and train neural networks.</p>
<p>What sets Fast.ai apart is its focus on practicality and its ability to be used by people with varying levels of coding experience.</p>
<h2 id="heading-why-choose-fastai">Why Choose Fast.ai?</h2>
<h3 id="heading-user-friendly">User-Friendly</h3>
<p>The Fast.ai library simplifies the deep learning process and abstracts away many of the complex details, making it easier for users to create powerful models.</p>
<p>The <strong>f</strong><a target="_blank" href="https://docs.fast.ai/"><strong>astai</strong></a> library sits on top of popular deep-learning frameworks like PyTorch. It provides a high-level API for building and training neural networks.</p>
<p>You can also integrate other powerful models like <a target="_blank" href="https://www.freecodecamp.org/news/hugging-face-transformer-library-overview/">Hugging Face transformers</a> using Fast.ai.</p>
<h3 id="heading-practical-approach">Practical Approach</h3>
<p>Fast.ai emphasizes a practical and hands-on approach to deep learning.</p>
<p>The Fast.ai library focuses on practical usage and real-world applications, helping you learn by doing.</p>
<p>Their courses and resources are designed to help students quickly get up and running with machine learning models. These include building and training neural networks for image recognition, natural language processing, and many others.</p>
<h3 id="heading-free-courses">Free Courses</h3>
<p>Fast.ai offers <a target="_blank" href="https://course.fast.ai/">free online courses</a> that cover a wide range of deep learning topics. Fast.ai courses are a few of the best in the market and their students have gone on to become popular machine learning researchers.</p>
<p>These courses are known for their practicality, clear explanations, and use of real-world datasets. These courses are designed to be accessible to individuals with varying levels of prior AI knowledge.</p>
<p>Fast.ai also incorporates the latest developments into its courses and resources, ensuring that students have access to state-of-the-art techniques.</p>
<h2 id="heading-how-to-get-started-with-fastai">How to Get Started with Fast.ai</h2>
<p>Now that you understand what Fast.ai is, let's write some code. You can check out <a target="_blank" href="https://colab.research.google.com/">the google colab notebook</a> if you want to quickly try this example.</p>
<p><strong>Note:</strong> It is recomended that you run this code on your system since running it in colab will take a long time (30 mins approx).</p>
<p>Before using the library, you have to set up your environment. Fast.ai runs on Python and requires PyTorch.</p>
<p>You can install Fast.ai using the pip command (remove the <strong><code>!</code></strong> if you are installing it on your terminal, as the <strong><code>!</code></strong> is only for colab notebooks. Notebooks treat the code following <strong><code>!</code></strong> as shell scripts).</p>
<pre><code>!pip install fastai
</code></pre><p>We’ll go through a simple sentiment analysis example in this article, demonstrating how you can implement NLP models using the fast.ai library.</p>
<p>Let’s start with importing the library:</p>
<pre><code><span class="hljs-keyword">from</span> fastai.text.all <span class="hljs-keyword">import</span> *
</code></pre><p>This line of code imports specific functionality from the Fast.ai library for natural language processing (NLP), particularly text analysis.</p>
<p>Let me break it down for you:</p>
<p><code>from fastai.text.all</code> specifies that you want to import all components from the <code>fastai.text</code> module which contains tools and functions for working with text data.</p>
<p>By including this line at the beginning of your code, you make all the text-related functionality from the Fastai library available for your use, making it easier to perform tasks like sentiment analysis, text classification, and others.</p>
<p>Next, we’ll use the IMDB dataset, also available in Fast.ai.</p>
<pre><code>path = untar_data(URLs.IMDB)
</code></pre><p>This line of code downloads and extracts the IMDB dataset, making it ready for further processing and analysis.</p>
<p>The variable <code>path</code> will contain the local file path to the dataset, allowing you to access and work with the data in your code.</p>
<p>Next, we have to load the data. <a target="_blank" href="https://pytorch.org/tutorials/beginner/basics/data_tutorial.html">Data loaders</a> are used to efficiently load and process data during the training of a machine learning model.</p>
<p><code>TextDataLoaders</code> is a class provided by the Fast.ai library that allows you to create data loaders specifically designed for text data.</p>
<pre><code>dls = TextDataLoaders.from_folder(path, valid=<span class="hljs-string">'test'</span>)
</code></pre><p><code>from_folder(path, valid='test')</code> is a function call on the <code>TextDataLoaders</code> class. It is used to create the data loaders.</p>
<p>Here's what each argument means:</p>
<ul>
<li><code>path</code>: This is the directory path where your text data is stored. In this case, it's the <code>path</code> variable that you previously defined, which contains the local path to the IMDB dataset.</li>
<li><code>valid='test'</code>: This argument specifies which folder or subset of your data should be used for validation. In the IMDB dataset, there are typically two main subsets: <code>train</code> for training data and <code>test</code> for testing or validation data. By setting <code>valid</code> to <code>test</code>, you're indicating that the 'test' folder within the <code>path</code> directory should be used for validation. This is a common practice in machine learning to have a separate validation set to evaluate the model's performance during training.</li>
<li>The resulting <code>dls</code> variable will contain the text data loaders, which include both training and validation data splits. These data loaders can be used to load and preprocess text data batches during the training of your sentiment analysis model or any other text-based model.</li>
</ul>
<p>Now that we have the data for training, let’s train the model.</p>
<p>We will create a text classification model using the Fast.ai library, fine-tune it on the provided text data, and train it for a specified number of epochs (repetitions).</p>
<pre><code>learn = text_classifier_learner(dls, AWD_LSTM, drop_mult=<span class="hljs-number">0.5</span>, metrics=accuracy)
</code></pre><p>Let’s break down each line:</p>
<ul>
<li><code>text_classifier_learner</code> — The text classification learner is used to create a learner object for training and working with text classification models. Let’s look at the arguments.</li>
<li><code>dls</code> — This is the data loader object you previously created using <code>TextDataLoaders.from_folder()</code>. It contains the training and validation data for your text classification task.</li>
<li><code>AWD_LSTM</code> — This is a pre-defined architecture for the neural network used in text classification tasks. AWD_LSTM stands for <a target="_blank" href="https://arxiv.org/pdf/1708.02182v1.pdf">ASGD Weight-Dropped LSTM</a>. It is a type of <a target="_blank" href="https://aws.amazon.com/what-is/recurrent-neural-network/">recurrent neural network</a> (RNN) architecture that is effective for sequential data like text.</li>
<li><code>drop_mult=0.5</code> — This argument controls the amount of dropout regularization applied to the neural network. Dropout is a regularization technique used to prevent overfitting (training the model too much). <code>drop_mult=0.5</code>means that dropout will be applied at a moderate rate.</li>
<li><code>metrics=accuracy</code> — This specifies that the accuracy metric should be used to evaluate the model’s performance during training. Accuracy is a common metric for classification tasks, measuring the percentage of correctly classified examples.</li>
</ul>
<p>Now let's fine-tune the model using the loaded data.</p>
<pre><code>learn.fine_tune(<span class="hljs-number">1</span>)
</code></pre><ul>
<li><code>learn.fine_tune(1)</code> — This line of code fine-tunes the text classification model. </li>
<li><code>1</code> — The parameter <code>1</code> is the number of epochs for which the model will be trained. An epoch is one pass through the entire training dataset. Training for multiple epochs allows the model to learn from the data multiple times, here for simplicity’s sake we use 1.</li>
</ul>
<p>In summary, these lines of code create a text classification model, load your text data, fine-tune the model on the data for four epochs using a specified learning rate, and use accuracy as the metric to evaluate the model’s performance.</p>
<p>The resulting <code>learn</code> object represents your trained text classification model, which can be used to make predictions on new text data.</p>
<p>We are done. Now our model is ready to start predicting the sentiments of the text.</p>
<p>Let’s test the model with a movie review.</p>
<pre><code>learn.predict(<span class="hljs-string">"I really loved that movie, it was awesome!"</span>)
</code></pre><p>And here is the result.</p>
<pre><code>(<span class="hljs-string">'pos'</span>, tensor(<span class="hljs-number">1</span>), tensor([<span class="hljs-number">0.4885</span>, <span class="hljs-number">0.5115</span>]))
</code></pre><p>The <code>pos</code>says the given sentence is a positive sentence. The next array says how confident the model is in predicting whether the given sentence is positive or negative. This confidence score can be improved by increasing the number of epochs (which will take a long time to train, unless you have a powerful computer).</p>
<p>Hope this helps you to understand how to work with the Fast.ai library. I personally prefer to use <a target="_blank" href="https://huggingface.co/">Huggingface</a> for most use cases, but if I have to train models from scratch, Fast.ai would be my first choice.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Fast.ai offers a fantastic starting point for anyone interested in deep learning. Its simplicity and practicality make it a valuable tool for both beginners and experienced practitioners.</p>
<p>Using Fast.ai, you’ll discover that deep learning is not as daunting as it seems. Whether you’re a student, a developer, or a curious learner, Fast.ai can be your gateway to the fascinating world of artificial intelligence. So, get started, experiment, and enjoy the journey into deep learning with Fast.ai.</p>
<p>If you are a student of AI, subscribe to <strong><a target="_blank" href="https://www.turingtalks.ai/">turingtalks.ai</a></strong> to learn practical concepts on general machine learning and NLP. You can also <a target="_blank" href="https://manishmshiva.com/"><strong>visit my website</strong></a> to get in touch with me.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Deploy a TensorFlow Model as a RESTful API Service ]]>
                </title>
                <description>
                    <![CDATA[ By Neil Ruaro If you're like I am, then you've probably watched and read a number of tutorials on creating machine learning models with TensorFlow, PyTorch, Scikit-Learn or any other framework out there.  But there is one thing that these tutorials t... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/deploy-an-ml-model-using-fastapi-and-docker/</link>
                <guid isPermaLink="false">66d46040b6b7f664236cbe0c</guid>
                
                    <category>
                        <![CDATA[ deployment ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Docker ]]>
                    </category>
                
                    <category>
                        <![CDATA[ fastai,  ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Machine Learning ]]>
                    </category>
                
                    <category>
                        <![CDATA[ REST API ]]>
                    </category>
                
                    <category>
                        <![CDATA[ TensorFlow ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Mon, 07 Mar 2022 14:58:44 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/03/deploying-tensorflow-heroku-docker.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Neil Ruaro</p>
<p>If you're like I am, then you've probably watched and read a number of tutorials on creating machine learning models with TensorFlow, PyTorch, Scikit-Learn or any other framework out there. </p>
<p>But there is one thing that these tutorials tend to miss out on, and that's model deployment.</p>
<p>In this tutorial, I'll discuss on how to deploy a CNN TensorFlow model that classifies food images to Heroku using FastAPI and Docker.</p>
<h3 id="heading-tech-well-be-using">Tech We'll Be Using</h3>
<p>If you're unfamiliar, FastAPI is a Python web framework for creating fast API applications. And in my opinion, it is the easiest to learn out of all the Python web frameworks out there. </p>
<p>FastAPI also has default integration with swagger documentation and makes it easy to configure and update.</p>
<p>Docker, on the other hand, is an industry staple in software engineering, as it is one of the most popular containerization softwares out there. Docker is used for developing, deploying, and managing applications in virtualized environments called containers.</p>
<p>The main selling point of using Docker is that it solves the problem "it works on my machine, why not in yours?". Coincidentally, I actually faced this exact issue working on this very project, ultimately fixing it when I decided to use Docker.</p>
<p>Heroku, lastly, is a cloud platform where you can deploy, manage, and scale web applications. It works with back-end applications, front-end applications, or full-stack applications.</p>
<h2 id="heading-prerequisuites">Prerequisuites</h2>
<p>Before we begin, you'll first need the following:</p>
<ol>
<li>A Docker account</li>
<li>A Heroku account, and the Heroku CLI</li>
<li>A Python installation</li>
</ol>
<h2 id="heading-the-application-were-building">The Application We're Building</h2>
<p>We're going to be building a RESTful API service for a TensorFlow CNN model that classifies food images. </p>
<p>After building the API service, I'll show you how to dockerize the application, and then deploy it to Heroku.</p>
<h2 id="heading-how-to-download-the-necessities">How to Download the Necessities</h2>
<p>You'll first need to clone the GitHub repository at this <a target="_blank" href="https://github.com/eRuaro/food-vision-api">link</a>.</p>
<p><code>git clone https://github.com/eRuaro/food-vision-api.git</code></p>
<p>There are two branches in this repository – you'll use the <code>start-here</code> branch as <code>main</code> is the completed branch.</p>
<p>Once you've gotten the cloned repository, you'll need to download <a target="_blank" href="https://docs.docker.com/get-docker/">Docker</a> to your local system, and the <a target="_blank" href="https://devcenter.heroku.com/articles/heroku-cli">Heroku CLI</a> as well.</p>
<p>You must also install the following packages on pip:</p>
<ol>
<li>FastAPI</li>
<li>TensorFlow</li>
<li>Numpy</li>
<li>Uvicorn</li>
<li>Image</li>
</ol>
<p>To do so, create a <code>requirements.txt</code> file on the <code>start-here</code> branch, and put in the following. Note that you can use any other version of the listed packages below, as long as they still work together.</p>
<pre><code>fastapi==<span class="hljs-number">0.73</span><span class="hljs-number">.0</span>
numpy==<span class="hljs-number">1.19</span><span class="hljs-number">.5</span>
uvicorn==<span class="hljs-number">0.15</span><span class="hljs-number">.0</span>
image==<span class="hljs-number">1.5</span><span class="hljs-number">.33</span>
tensorflow-cpu==<span class="hljs-number">2.7</span><span class="hljs-number">.0</span>
</code></pre><p>After which you can install the packages using the command<br><code>pip install -r requirements.txt</code>.</p>
<p>Currently our <code>start-here</code> branch has the saved model file, as well as the Jupyter notebook used in creating the model. The notebook also has the code that implements our API feature. That is, it implements predicting the food class of an image based on its URL link.</p>
<h2 id="heading-brief-introduction-to-fastapi">Brief introduction to FastAPI</h2>
<p>With that in mind, let's start writing the code! In the root directory, create a <code>main.py</code> file. In that file, add the following lines of code:</p>
<pre><code><span class="hljs-keyword">from</span> fastapi <span class="hljs-keyword">import</span> FastAPI
<span class="hljs-keyword">from</span> fastapi.middleware.cors <span class="hljs-keyword">import</span> CORSMiddleware
<span class="hljs-keyword">from</span> uvicorn <span class="hljs-keyword">import</span> run
<span class="hljs-keyword">import</span> os

app = FastAPI()

origins = [<span class="hljs-string">"*"</span>]
methods = [<span class="hljs-string">"*"</span>]
headers = [<span class="hljs-string">"*"</span>]

app.add_middleware(
    CORSMiddleware, 
    allow_origins = origins,
    allow_credentials = True,
    allow_methods = methods,
    allow_headers = headers    
)

@app.get(<span class="hljs-string">"/"</span>)
<span class="hljs-keyword">async</span> def root():
    <span class="hljs-keyword">return</span> {<span class="hljs-string">"message"</span>: <span class="hljs-string">"Welcome to the Food Vision API!"</span>}

<span class="hljs-keyword">if</span> __name == <span class="hljs-string">"__main__"</span>:
    port = int(os.environ.get(<span class="hljs-string">'PORT'</span>, <span class="hljs-number">5000</span>))
    run(app, host=<span class="hljs-string">"0.0.0.0"</span>, port=port)
</code></pre><p>Running the command <code>python -m uvicorn main:app --reload</code> will run the app, and will listen to changes we make on the server. </p>
<p>Alternatively, you can use <code>python main.py</code> and it will run the app on port 5000, courtesy of the last 3 lines of code. However, this won't let the app listen to changes we make, so you'll have to re-run the app every time you want to see your changes.</p>
<p>We also added the <code>CORSMiddleware</code> which essentially allows us to access the API in a different host. That is, we can extend the app further by creating a front-end interface for it. We won't cover that in this article but I put it here just in case you want to create a front-end to interact with the API as well.</p>
<p>Going to the port where the app is running, you'll get this.</p>
<pre><code>{
    <span class="hljs-string">"message"</span>: <span class="hljs-string">"Welcome to the Food Vision API!"</span>
}
</code></pre><p>The command <code>python -m uvicorn main:app --reload</code> refers to the following:</p>
<pre><code>main -&gt; The file main.py
app -&gt; The object created inside <span class="hljs-keyword">of</span> main.py <span class="hljs-keyword">with</span> the line app = FastAPI()
--reload -&gt; Make the server restart after code changes
</code></pre><p>Let's dissect the code we've written so far.</p>
<pre><code>@app.get(<span class="hljs-string">"/"</span>)
<span class="hljs-keyword">async</span> def root():
    <span class="hljs-keyword">return</span> {<span class="hljs-string">"message"</span>: <span class="hljs-string">"Welcome to the Food Vision API!"</span>}
</code></pre><p><code>@app</code> is needed for FastAPI commands. The <code>get</code> is an HTTP method, while the <code>"/"</code> is the URL path of that specific API request. Below that we call a function that will return something. Here we just return a simple <code>json</code> message.</p>
<p>That is, we have a template for writing API endpoints with FastAPI.</p>
<pre><code>@app.http_method(<span class="hljs-string">"url_path"</span>)
<span class="hljs-keyword">async</span> def functionName():
    <span class="hljs-keyword">return</span> something
</code></pre><h2 id="heading-how-to-write-the-api-functionality">How to Write the API Functionality</h2>
<p>Let's write the main API functionality, that is, taking a food image URL from the internet, and predicting the name of that food. </p>
<p>First, let's extend the code that we wrote earlier, import all the required functions that we'll use, and load the model itself.</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> fastapi <span class="hljs-keyword">import</span> FastAPI
<span class="hljs-keyword">from</span> tensorflow.keras.models <span class="hljs-keyword">import</span> load_model
<span class="hljs-keyword">from</span> tensorflow.keras.utils <span class="hljs-keyword">import</span> get_file 
<span class="hljs-keyword">from</span> tensorflow.keras.utils <span class="hljs-keyword">import</span> load_img 
<span class="hljs-keyword">from</span> tensorflow.keras.utils <span class="hljs-keyword">import</span> img_to_array
<span class="hljs-keyword">from</span> tensorflow <span class="hljs-keyword">import</span> expand_dims
<span class="hljs-keyword">from</span> tensorflow.nn <span class="hljs-keyword">import</span> softmax
<span class="hljs-keyword">from</span> numpy <span class="hljs-keyword">import</span> argmax
<span class="hljs-keyword">from</span> numpy <span class="hljs-keyword">import</span> max
<span class="hljs-keyword">from</span> numpy <span class="hljs-keyword">import</span> array
<span class="hljs-keyword">from</span> json <span class="hljs-keyword">import</span> dumps
<span class="hljs-keyword">from</span> uvicorn <span class="hljs-keyword">import</span> run
<span class="hljs-keyword">import</span> os

app = FastAPI()
model_dir = <span class="hljs-string">"food-vision-model.h5"</span>
model = load_model(model_dir)

...
...
...

<span class="hljs-keyword">if</span> __name == <span class="hljs-string">"__main__"</span>:
    port = int(os.environ.get(<span class="hljs-string">'PORT'</span>, <span class="hljs-number">5000</span>))
    run(app, host=<span class="hljs-string">"0.0.0.0"</span>, port=port)
</code></pre>
<p>After loading in the model, let's add in the food classes that we have, which are based on the Food 101 dataset.</p>
<pre><code class="lang-python">class_predictions = array([
    <span class="hljs-string">'apple pie'</span>,
    <span class="hljs-string">'baby back ribs'</span>,
    <span class="hljs-string">'baklava'</span>,
    <span class="hljs-string">'beef carpaccio'</span>,
    <span class="hljs-string">'beef tartare'</span>,
    <span class="hljs-string">'beet salad'</span>,
    <span class="hljs-string">'beignets'</span>,
    <span class="hljs-string">'bibimbap'</span>,
    <span class="hljs-string">'bread pudding'</span>,
    <span class="hljs-string">'breakfast burrito'</span>,
    <span class="hljs-string">'bruschetta'</span>,
    <span class="hljs-string">'caesar salad'</span>,
    <span class="hljs-string">'cannoli'</span>,
    <span class="hljs-string">'caprese salad'</span>,
    <span class="hljs-string">'carrot cake'</span>,
    <span class="hljs-string">'ceviche'</span>,
    <span class="hljs-string">'cheesecake'</span>,
    <span class="hljs-string">'cheese plate'</span>,
    <span class="hljs-string">'chicken curry'</span>,
    <span class="hljs-string">'chicken quesadilla'</span>,
    <span class="hljs-string">'chicken wings'</span>,
    <span class="hljs-string">'chocolate cake'</span>,
    <span class="hljs-string">'chocolate mousse'</span>,
    <span class="hljs-string">'churros'</span>,
    <span class="hljs-string">'clam chowder'</span>,
    <span class="hljs-string">'club sandwich'</span>,
    <span class="hljs-string">'crab cakes'</span>,
    <span class="hljs-string">'creme brulee'</span>,
    <span class="hljs-string">'croque madame'</span>,
    <span class="hljs-string">'cup cakes'</span>,
    <span class="hljs-string">'deviled eggs'</span>,
    <span class="hljs-string">'donuts'</span>,
    <span class="hljs-string">'dumplings'</span>,
    <span class="hljs-string">'edamame'</span>,
    <span class="hljs-string">'eggs benedict'</span>,
    <span class="hljs-string">'escargots'</span>,
    <span class="hljs-string">'falafel'</span>,
    <span class="hljs-string">'filet mignon'</span>,
    <span class="hljs-string">'fish and chips'</span>,
    <span class="hljs-string">'foie gras'</span>,
    <span class="hljs-string">'french fries'</span>,
    <span class="hljs-string">'french onion soup'</span>,
    <span class="hljs-string">'french toast'</span>,
    <span class="hljs-string">'fried calamari'</span>,
    <span class="hljs-string">'fried rice'</span>,
    <span class="hljs-string">'frozen yogurt'</span>,
    <span class="hljs-string">'garlic bread'</span>,
    <span class="hljs-string">'gnocchi'</span>,
    <span class="hljs-string">'greek salad'</span>,
    <span class="hljs-string">'grilled cheese sandwich'</span>,
    <span class="hljs-string">'grilled salmon'</span>,
    <span class="hljs-string">'guacamole'</span>,
    <span class="hljs-string">'gyoza'</span>,
    <span class="hljs-string">'hamburger'</span>,
    <span class="hljs-string">'hot and sour soup'</span>,
    <span class="hljs-string">'hot dog'</span>,
    <span class="hljs-string">'huevos rancheros'</span>,
    <span class="hljs-string">'hummus'</span>,
    <span class="hljs-string">'ice cream'</span>,
    <span class="hljs-string">'lasagna'</span>,
    <span class="hljs-string">'lobster bisque'</span>,
    <span class="hljs-string">'lobster roll sandwich'</span>,
    <span class="hljs-string">'macaroni and cheese'</span>,
    <span class="hljs-string">'macarons'</span>,
    <span class="hljs-string">'miso soup'</span>,
    <span class="hljs-string">'mussels'</span>,
    <span class="hljs-string">'nachos'</span>,
    <span class="hljs-string">'omelette'</span>,
    <span class="hljs-string">'onion rings'</span>,
    <span class="hljs-string">'oysters'</span>,
    <span class="hljs-string">'pad thai'</span>,
    <span class="hljs-string">'paella'</span>,
    <span class="hljs-string">'pancakes'</span>,
    <span class="hljs-string">'panna cotta'</span>,
    <span class="hljs-string">'peking duck'</span>,
    <span class="hljs-string">'pho'</span>,
    <span class="hljs-string">'pizza'</span>,
    <span class="hljs-string">'pork chop'</span>,
    <span class="hljs-string">'poutine'</span>,
    <span class="hljs-string">'prime rib'</span>,
    <span class="hljs-string">'pulled pork sandwich'</span>,
    <span class="hljs-string">'ramen'</span>,
    <span class="hljs-string">'ravioli'</span>,
    <span class="hljs-string">'red velvet cake'</span>,
    <span class="hljs-string">'risotto'</span>,
    <span class="hljs-string">'samosa'</span>,
    <span class="hljs-string">'sashimi'</span>,
    <span class="hljs-string">'scallops'</span>,
    <span class="hljs-string">'seaweed salad'</span>,
    <span class="hljs-string">'shrimp and grits'</span>,
    <span class="hljs-string">'spaghetti bolognese'</span>,
    <span class="hljs-string">'spaghetti carbonara'</span>,
    <span class="hljs-string">'spring rolls'</span>,
    <span class="hljs-string">'steak'</span>,
    <span class="hljs-string">'strawberry shortcake'</span>,
    <span class="hljs-string">'sushi'</span>,
    <span class="hljs-string">'tacos'</span>,
    <span class="hljs-string">'takoyaki'</span>,
    <span class="hljs-string">'tiramisu'</span>,
    <span class="hljs-string">'tuna tartare'</span>,
    <span class="hljs-string">'waffles'</span>
])
</code></pre>
<p>Now that we have the food classes, let's write the main API functionality.</p>
<pre><code>@app.post(<span class="hljs-string">"/net/image/prediction/"</span>)
<span class="hljs-keyword">async</span> def get_net_image_prediction(image_link: str = <span class="hljs-string">""</span>):
    <span class="hljs-keyword">if</span> image_link == <span class="hljs-string">""</span>:
        <span class="hljs-keyword">return</span> {<span class="hljs-string">"message"</span>: <span class="hljs-string">"No image link provided"</span>}

    img_path = get_file(
        origin = image_link
    )
    img = load_img(
        img_path, 
        target_size = (<span class="hljs-number">224</span>, <span class="hljs-number">224</span>)
    )

    img_array = img_to_array(img)
    img_array = expand_dims(img_array, <span class="hljs-number">0</span>)

    pred = model.predict(img_array)
    score = softmax(pred[<span class="hljs-number">0</span>])

    class_prediction = class_predictions[argmax(score)]
    model_score = round(max(score) * <span class="hljs-number">100</span>, <span class="hljs-number">2</span>)

    <span class="hljs-keyword">return</span> {
        <span class="hljs-string">"model-prediction"</span>: class_prediction,
        <span class="hljs-string">"model-prediction-confidence-score"</span>: model_score
    }
</code></pre><p>Here, we make a <strong>post</strong> request to the endpoint <code>/net/image/prediction/</code> and provide the <code>image_url</code> as a query parameter. That is, the full endpoint when posting an image URL link would be <code>/net/image/prediction/image_url=image-url</code>.</p>
<p>For simplicity's sake, we give the <code>image_link</code> a default value of <code>""</code> and when there's no link passed to the endpoint, we simply return a message saying that there's no image link provided. </p>
<p><code>get_file()</code> downloads the image through the provided URL link, while <code>load_img()</code> loads the image in PIL format, and turns it into the appropriate image size that the model wants. </p>
<p><code>img_to_array()</code> converts the loaded image to a NumPy array. <code>expand_dims()</code> expands the dimensions of the array by one at the zero'th index. </p>
<p>We then use <code>model.predict()</code> to get the model prediction on the loaded image, and get the model's confidence score on said prediction using <code>softmax()</code>. I used softmax here as that's the activation function used in creating the model.</p>
<p>We finally then get the food type by using <code>argmax()</code> on the model's confidence score. We'll use that as the index that we'll use in searching through the <code>class_predictions</code> array which contains the various food classes we have. </p>
<p>Lastly, we multiply the model's confidence score by 100 so that the range of the score would be from 1 to 100.</p>
<p>We then return the model's prediction, and the model's confidence score.</p>
<h2 id="heading-why-we-need-to-use-docker-to-deploy-this-app">Why We Need to Use Docker to Deploy this App</h2>
<p>You can actually deploy this app as is on Heroku, using the usual method of defining a <code>Procfile</code>. But when I tried this method, I kept on getting a <a target="_blank" href="https://stackoverflow.com/questions/71152285/valueerror-out-of-range-float-values-are-not-json-compliant-error-on-heroku-an"><code>ValueError: Out of range float values are not JSON compliant</code></a> error. I also get this error when running the app on <em>Windows Subsystem for Linux</em> (WSL). When I run on Windows, however, the error disappears.</p>
<p>You can actually avoid this error by adding this line of code, after the initial assignment of the <code>model_score</code> variable:</p>
<pre><code>model_score = dumps(model_score.tolist())
</code></pre><p>This lets the app run on both Heroku and WSL, but it will only return these values when making the POST request.</p>
<pre><code>{
    <span class="hljs-string">"model-prediction"</span>: <span class="hljs-string">"apple pie"</span>,
    <span class="hljs-string">"model-prediction-confidence-score"</span>: <span class="hljs-literal">NaN</span>,
}
</code></pre><p>So, it works on my machine (Windows), but not on Heroku (using Procfile), nor on WSL. This is the kind of problem that Docker solves! </p>
<h2 id="heading-how-to-dockerize-the-application">How to Dockerize the Application</h2>
<p>Let's start dockerizing the application. Create a <code>Dockerfile</code> in the project's root directory and put in the following content:</p>
<pre><code>FROM python:<span class="hljs-number">3.7</span><span class="hljs-number">.3</span>-stretch

# Maintainer info
LABEL maintainer=<span class="hljs-string">"your-email-address"</span>

# Make working directories
RUN  mkdir -p  /food-vision-api
WORKDIR  /food-vision-api

# Upgrade pip <span class="hljs-keyword">with</span> no cache
RUN pip install --no-cache-dir -U pip

# Copy application requirements file to the created working directory
COPY requirements.txt .

# Install application dependencies <span class="hljs-keyword">from</span> the requirements file
RUN pip install -r requirements.txt

# Copy every file <span class="hljs-keyword">in</span> the source folder to the created working directory
COPY  . .

# Run the python application
CMD [<span class="hljs-string">"python"</span>, <span class="hljs-string">"main.py"</span>]
</code></pre><p>This pulls the Python 3.7.3 image, and installs all the necessary packages defined in the <code>requirements.txt</code> file. Then it runs the application by using the command <code>python main.py</code> as defined in the last line of the file.</p>
<p>You can then build and run the application using the following CLI commands:</p>
<pre><code>$ docker image build -t &lt;app-name&gt; .
$ docker run -p <span class="hljs-number">5000</span>:<span class="hljs-number">5000</span> -d &lt;app-name&gt;
</code></pre><p>Then you can stop the app, and free up system resources by running the following:</p>
<pre><code>$ docker container stop &lt;container-id&gt;
$ docker system prune
</code></pre><p><code>container-id</code> is returned when running the <code>docker run</code> command above. </p>
<h2 id="heading-how-to-deploy-to-heroku">How to Deploy to Heroku</h2>
<p>With the app now dockerized, we can deploy it to Heroku. I'm assuming you already have the Heroku CLI installed, and have already logged the CLI into your Heroku account. </p>
<p>Let's first create the app in Heroku through the CLI:</p>
<pre><code>$ heroku create &lt;app-name&gt;
</code></pre><p>Then we can push and release the app through the Docker container we made earlier with the following commands:</p>
<pre><code>$ heroku container:push web --app &lt;app-name&gt;
$ heroku container:release web --app &lt;app-name&gt;
</code></pre><p>After this, you can go to your Heroku dashboard and open the app. You should be greeted with the JSON message we have in the <code>"/"</code> directory of the application.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/03/image-7.png" alt="Image" width="600" height="400" loading="lazy">
<em>JSON message greeting on <code>"/"</code> directory</em></p>
<p>When you navigate to the <code>/docs</code> you'll be greeted with the Swagger documentation of the application. Here you can play around with the POST request we created and see if the model predictions are correct. Note that you must upload image links with the <code>jpeg</code> or <code>png</code> in its URL.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/03/image-8.png" alt="Image" width="600" height="400" loading="lazy">
<em>Swagger documentation of the application on <code>/docs</code></em></p>
<p>Let's try this out by using a picture of a chocolate cake, its URL link is <a target="_blank" href="https://tallypress.com/wp-content/uploads/2017/11/7-irresistible-chocolate-cakes-you-should-try-in-klang-valley.jpg">this</a>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/03/image-9.png" alt="Image" width="600" height="400" loading="lazy">
<em>Image from tallypress.com</em></p>
<p>Paste the link to the text box in the <code>/docs</code> as so, then press <code>Execute</code>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/03/image-10.png" alt="Image" width="600" height="400" loading="lazy">
<em>Demonstration of the app</em></p>
<p>After pressing the <code>Execute</code> button, it will take a few seconds until we get the model prediction. That's because we're using <code>tensorflow-cpu</code> because we're limited with the RAM and the slug size of our application when using the free tier of Heroku. </p>
<p>After the execution is finished, you should be greeted with this response:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/03/image-11.png" alt="Image" width="600" height="400" loading="lazy">
<em>Response of the API after usage</em></p>
<p>As you can see, the model predicted it correctly, with a confidence score of 2.65%. This confidence score is alright as we're not dealing with model accuracy (which requires the truth value beforehand), and we're dealing with data the model hasn't seen before. </p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this article, you learned how to deploy a TensorFlow CNN model to Heroku by serving it as a RESTful API, and by using Docker. </p>
<p>If you find this article helpful, feel free to share it on social media. Let's connect on <a target="_blank" href="https://twitter.com/neil_ruaro">Twitter</a>! You can also support me by <a target="_blank" href="https://www.buymeacoffee.com/eRuaro">buying me a coffee</a>. </p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Deep Learning Tutorial – How to Train and Deploy a Deep Learning Model with fast.ai ]]>
                </title>
                <description>
                    <![CDATA[ Deep learning is bringing revolutionary changes to many disciplines. It is also becoming more accessible to domain experts and AI enthusiasts with the advent of libraries like TensorFlow, PyTorch, and now fast.ai. fast.ai's mission is to democratize ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/deep-learning-with-fastai/</link>
                <guid isPermaLink="false">66d45f393a8352b6c5a2aa73</guid>
                
                    <category>
                        <![CDATA[ Artificial Intelligence ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Deep Learning ]]>
                    </category>
                
                    <category>
                        <![CDATA[ fastai,  ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Harshit Tyagi ]]>
                </dc:creator>
                <pubDate>Tue, 06 Oct 2020 22:08:19 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/10/Untitled-design.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Deep learning is bringing revolutionary changes to many disciplines. It is also becoming more accessible to domain experts and AI enthusiasts with the advent of libraries like TensorFlow, PyTorch, and now <strong>fast.ai</strong>.</p>
<p>fast.ai's mission is to democratize deep learning. It is a research institute dedicated to helping everyone – from a beginner level coder to a proficient deep learning practitioner – achieve world-class results with state-of-the-art models and techniques from the latest research in the field.</p>
<p>This blog post will walk you through the process of developing <strong>a dog classifier</strong> using <strong>fast.ai</strong>. The goal is to learn how easy it is to get started with deep learning models and to be able to achieve near-perfect results with a limited amount of data using pre-trained models.</p>
<h3 id="heading-prerequisite">Prerequisite</h3>
<p>The only prerequisite to get started is that you <strong>know how to code in Python</strong> and that you are familiar with high school math.</p>
<h3 id="heading-what-youll-learn">What You’ll Learn</h3>
<ol>
<li><p>Importing the libraries and setting up the notebook</p>
</li>
<li><p>Collecting Imagery Data using Microsoft Azure</p>
</li>
<li><p>Converting downloaded data into DataLoader objects</p>
</li>
<li><p>Data Augmentation</p>
</li>
<li><p>Cleaning Data using Model Training</p>
</li>
<li><p>Exporting the Trained Model</p>
</li>
<li><p>Building an Application out of your Jupyter Notebook</p>
</li>
</ol>
<p>So let's get started.</p>
<h2 id="heading-how-to-import-the-libraries-and-set-up-the-notebook">How to Import the Libraries and Set Up the Notebook</h2>
<p>Before we get down to building our model, we need to import the required libraries and utility function from <a target="_blank" href="https://github.com/fastai/fastbook">the set of notebooks</a> called <a target="_blank" href="https://github.com/fastai/fastbook">fastbook</a>. It's been developed to cover the introduction to Deep Learning using fast.ai and PyTorch.</p>
<p>Let’s install the fastbook package to set up the notebook:</p>
<pre><code class="lang-javascript">!pip install -Uqq fastbook
<span class="hljs-keyword">import</span> fastbook
fastbook.setup_book()
</code></pre>
<p>Then, let’s import all the functions and classes from the fastbook package and fast.ai vision widgets API:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">from</span> fastbook <span class="hljs-keyword">import</span> *
<span class="hljs-keyword">from</span> fastai.vision.widgets <span class="hljs-keyword">import</span> *
</code></pre>
<h2 id="heading-how-to-collect-imagery-data-using-microsoft-azure">How to Collect Imagery Data using Microsoft Azure</h2>
<p>For most types of projects, you can find the data online from various <a target="_blank" href="https://towardsdatascience.com/data-repositories-for-almost-every-type-of-data-science-project-7aa2f98128b?source=---------6----------------------------">data repositories and websites</a>. To develop a Dog Classifier, we need to have images of dogs. There are many images of dogs available on the internet.</p>
<p>To download these images, we’ll use the <a target="_blank" href="https://azure.microsoft.com/en-us/services/cognitive-services/bing-image-search-api/">Bing Image Search API</a> provided by Microsoft Azure. So, sign up for a free account on Microsoft Azure and you’ll get $200 worth of credits.</p>
<p>Go to your portal and create a new Cognitive Service resource using <a target="_blank" href="https://docs.microsoft.com/en-us/azure/cognitive-services/cognitive-services-apis-create-account?tabs=multiservice%2Clinux">this quickstart.</a> Enable the Bing Image Search API. Then, from the <code>Keys and Endpoint</code> option in the left panel, copy the <strong>keys</strong> to your resource.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/10/1-2.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>With the retrieved keys, set these keys to the environment as follows:</p>
<pre><code class="lang-javascript">key = os.environ.get(<span class="hljs-string">'AZURE_SEARCH_KEY'</span>, <span class="hljs-string">'&lt;YOUR_KEY&gt;'</span>)
</code></pre>
<p>Now, fastbook comes with utility functions like <code>search_images_bing</code> that returns URLs corresponding to your search query. You can learn about such functions using the help function:</p>
<pre><code class="lang-javascript">help(fastbook)
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/10/8-1.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>You can check the <code>search_image_bing</code> function in this help guide. The function accepts a key to your resource that you’ve defined above and the search query, and we can access the URLs of the search results using the <code>attrgot</code> method:</p>
<pre><code class="lang-javascript">results = search_images_bing(key, <span class="hljs-string">'german shepherd dogs'</span>)
images = results.attrgot(<span class="hljs-string">'content_url'</span>)
len(images)
</code></pre>
<p>We have 150 URLs of images of German Shepherd dogs:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/10/9-1.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Now, we can download these images using the <code>download_url</code> function. But let’s first define the type of dogs that we want.</p>
<p>For this tutorial, I’m going to work with three types of dogs: German Shepherds, black dogs, and Labradors.</p>
<p>So, let’s define a list of dog types:</p>
<pre><code class="lang-javascript">dog_types = [<span class="hljs-string">'german shepherd'</span>, <span class="hljs-string">'black'</span>, <span class="hljs-string">'labrador'</span>]
path = Path(<span class="hljs-string">'dogs'</span>)
</code></pre>
<p>You’ll then need to define the path where your images will be downloaded along with the semantic names of the folder for each class of dog.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">if</span> not path.exists():
    path.mkdir()
    <span class="hljs-keyword">for</span> t <span class="hljs-keyword">in</span> dog_types:
        dest = (path/t)
        print(dest)
        dest.mkdir(exist_ok=True)
        results = search_images_bing(key, <span class="hljs-string">'{} dog'</span>.format(t))
        download_images(dest, urls=results.attrgot(<span class="hljs-string">'content_url'</span>))
</code></pre>
<p>This will create a “dogs” directory which further contains 3 directories for each type of dog image.</p>
<p>After that, we pass the search query (which is the dog_type) and the key to the search function, followed by the download function to download all the URLs from the search results in their respective destination (<code>dest</code>) directories.</p>
<p>We can check the images downloaded to a path using the <code>get_image_file</code> function:</p>
<pre><code class="lang-python">files = get_image_files(path)
files
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/10/10.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h3 id="heading-how-to-verify-images">How to Verify Images</h3>
<p>You can also check for the number of corrupt files/images in the files:</p>
<pre><code class="lang-javascript">corrupt = verify_images(files)
corrupt

##output: (#<span class="hljs-number">0</span>) []
</code></pre>
<p>You can remove all the corrupt files (if any) by mapping the unlink method to the list of corrupt files: corrupt.map(Path.unlink);</p>
<p>That’s it, we have 379 dog images ready with us to train and validate our model.</p>
<h2 id="heading-how-to-convert-downloaded-data-into-dataloader-objects">How to Convert Downloaded Data into DataLoader Objects</h2>
<p>Now, we need a mechanism to provide data to our model. fast.ai has this concept of DataLoaders that stores multiple DataLoader objects passed to it and makes them available as a <code>training</code> and <code>validation</code> set.</p>
<p>Now, to convert the downloaded data into a DataLoader object, we have to provide four things:</p>
<ul>
<li><p>What kinds of data we are working with</p>
</li>
<li><p>How to get the list of items</p>
</li>
<li><p>How to label these items</p>
</li>
<li><p>How to create the validation set</p>
</li>
</ul>
<p>Now, to create these DataLoaders objects along with the information mentioned above, fast.ai offers a flexible system called the <strong>data block API_._</strong> We can specify all the details of the DataLoader creation using the arguments and an array of transformation methods that the API offers:</p>
<pre><code class="lang-javascript">dogs = DataBlock(
                  blocks=(ImageBlock, CategoryBlock),
                  get_items=get_image_files,
                  splitter=RandomSplitter(valid_pct=<span class="hljs-number">0.2</span>, seed=<span class="hljs-number">41</span>),
                  get_y=parent_label,
                  item_tfms=Resize(<span class="hljs-number">128</span>)
                  )
</code></pre>
<p>Here, we have a bunch of arguments that we should understand:</p>
<ul>
<li><p><strong>blocks</strong> — this specifies the feature variables (images) and the target variable (a category for each image)</p>
</li>
<li><p><strong>get_items</strong> — retrieves the underlying items (which are images in our case) and we have a <code>**get_image_files**</code> function that returns a list of all of the images in that path.</p>
</li>
<li><p><strong>splitter</strong> — splits the data as per the provided method. We are using a random split with 20% of the data reserved for the validation set and specified the seed to get the same split on every run.</p>
</li>
<li><p><strong>get_y —</strong> the target variable is referred to as y. To create the labels, we are using the <code>**parent_label**</code> function which gets the name of the folder where the file resides as its label.</p>
</li>
<li><p><strong>item_tfms</strong> — we have images of different sizes and this causes a problem because we always send a batch of files to the model instead of a single file. Therefore we need to preprocess these images by resizing them to a standard and then group them in a tensor to pass through the model. We are using the <code>**Resize**</code> transformation here.</p>
</li>
</ul>
<p>Now, we have the DataBlock object which needs to be converted to a DataLoader by providing the path to the dataset:</p>
<pre><code class="lang-javascript">dls = dogs.dataloaders(path)
</code></pre>
<p>We can then check for the images in the dataloader object using the <code>show_batch</code> method:</p>
<pre><code class="lang-javascript">dls.valid.show_batch()
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/10/2-2.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h2 id="heading-data-augmentation">Data Augmentation</h2>
<p>We can add transformations to these images to create random variations of the input images, such that they appear different but still represent the same facts.</p>
<p>We can rotate, warp, flip, or change the brightness/contrast of the images to create these variations. We also have a standard set of augmentations encapsulated in the <code>aug_transforms</code> function that works pretty well for the majority of computer vision datasets.</p>
<p>We can now apply these transformations to an entire batch of images as all the images are of the same size (224 pixels, standard for image classification problems) using the following:</p>
<pre><code class="lang-javascript">##adding item transformations
dogs = dogs.new(
        item_tfms=RandomResizedCrop(<span class="hljs-number">224</span>, min_scale=<span class="hljs-number">0.5</span>),
        batch_tfms=aug_transforms(mult=<span class="hljs-number">2</span>)
        )
dls = dogs.dataloaders(path)
dls.train.show_batch(max_n=<span class="hljs-number">8</span>, nrows=<span class="hljs-number">2</span>, unique=True)
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/10/3-1.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h2 id="heading-model-training-and-data-cleaning">Model Training and Data Cleaning</h2>
<p>It’s time to train the model with this limited number of images. fast.ai offers many architectures to use which makes it very easy to use transfer learning.</p>
<p>We can create a convolutional neural network (CNN) model using the pre-trained models that work for most of the applications/datasets.</p>
<p>We are going to use ResNet architecture, as it is both fast and accurate for many datasets and problems. The 18 in the <code>**resnet18**</code> represents the number of layers in the neural network.</p>
<p>We also pass the metric to measure the quality of the model’s predictions using the validation set from the dataloader. We are using <strong>error_rate</strong> which tells us how frequently the model is making incorrect predictions:</p>
<pre><code class="lang-javascript">model = cnn_learner(dls, resnet18, metrics=error_rate)
model.fine_tune(<span class="hljs-number">4</span>)
</code></pre>
<p>The <code>fine_tune</code> method is analogous to the <code>fit()</code> method in other ML libraries. Now, to train the model, we need to specify the number of times (epochs) we want to train the model on each image.</p>
<p>Here, we are training for only 4 epochs:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/10/4-1.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>We can also visualize the predictions and compare them with the actual labels using the confusion matrix:</p>
<pre><code class="lang-javascript">interp = ClassificationInterpretation.from_learner(learn)
interp.plot_confusion_matrix()
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/10/5-1.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>As you can see, we only have five incorrect predictions. Let’s check for the top losses, that is the images with the highest loss in the dataset:interp.plot_top_losses (6, nrows=3):</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/10/6-1.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>You can see that the model got confused between black and labrador. Thus, we can specify these images to be in a particular category using the ImageClassifierCleaner class.</p>
<p>Pass the model to the class and it will open up a widget with an intuitive GUI for data cleaning. We can change the labels of training and validation set images and view the highest-loss images.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/10/7-1.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>After adding each image to their respective correct class, we have to move them to their right directory using:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">for</span> idx,cat <span class="hljs-keyword">in</span> cleaner.change():
    shutil.move(str(cleaner.fns[idx]), str(path/cat).split(<span class="hljs-string">'.'</span>)[<span class="hljs-number">0</span>] +<span class="hljs-string">"_fixed.jpg"</span>)
</code></pre>
<h2 id="heading-how-to-export-the-trained-model">How to Export the Trained Model</h2>
<p>After a couple of rounds of hyperparameter tuning, and once you’re happy with your model, you need to save it so that you can deploy it on a server to be used in production.</p>
<p>While saving a model, we have the model architecture and the trained parameters that are of value to us. fast.ai offers the <code>export()</code> method to save the model in a pickle file with the extension <code>.pkl</code>.</p>
<pre><code class="lang-javascript">model.export()
path = Path()
path.ls(file_exts=<span class="hljs-string">'.pkl'</span>)
</code></pre>
<p>We can then load the model and make inferences by passing an image to the loaded model:</p>
<pre><code class="lang-javascript">model_inf = load_learner(path/<span class="hljs-string">'export.pkl'</span>)
</code></pre>
<p>Use this loaded model to make inferences:</p>
<pre><code class="lang-javascript">model_inf.predict(<span class="hljs-string">'dogs/labrador/00000000.jpg'</span>)
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/10/11.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>We can check the labels from the models dataloader vocabulary:</p>
<pre><code class="lang-javascript">model_inf.dls.vocab
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/10/12.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h2 id="heading-how-to-build-an-application-out-of-your-jupyter-notebook">How to Build an Application out of your Jupyter Notebook</h2>
<p>The next step is to create an application that we can share with our friends, colleagues, recruiters, and others.</p>
<p>To create an application, we need to add interactive elements so that we can try and test the application’s features. We also need to make it available on the web as a webpage, which includes deploying it via some framework like Flask or simply using Voila.</p>
<p>You can use Voila to convert this Jupyter Notebook into a standalone app. I have not covered it here but you can go through my <a target="_blank" href="https://medium.com/r?url=https%3A%2F%2Ftowardsdatascience.com%2Fbuilding-covid-19-analysis-dashboard-using-python-and-voila-ee091f65dcbb">blog/video</a> which covers the whole process.</p>
<h3 id="heading-deploying-your-model">Deploying your Model</h3>
<p>I’ve covered deploying an ML model in my post <a target="_blank" href="https://towardsdatascience.com/deploying-a-trained-ml-model-using-flask-541520b3cbe9">here</a>. But if you want another easy and free way of deploying your Voila application, you can use <a target="_blank" href="https://mybinder.org/">Binder</a>.</p>
<p>Follow these steps to deploy the application on Binder:</p>
<ol>
<li><p>Add your notebook to a <a target="_blank" href="http://github.com/">GitHub repository</a>.</p>
</li>
<li><p>Insert the URL of that repo into Binder’s URL field.</p>
</li>
<li><p>Change the file drop-down to instead select the URL.</p>
</li>
<li><p>In the “URL to open” field, enter <code>/voila/render/&lt;_name&gt;_.ipynb</code></p>
</li>
<li><p>Click the clipboard button at the bottom right to copy the URL and paste it somewhere safe.</p>
</li>
<li><p>Click Launch.</p>
</li>
</ol>
<p>And there you go, your dog classifier is live!</p>
<p>If you prefer to watch me going through all of these steps, here’s the video version of this blog:</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/pNaCrhxmN1w" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<p> </p>
<h3 id="heading-data-science-with-harshithttpswwwyoutubecomcdatasciencewithharshitsubconfirmation1"><a target="_blank" href="https://www.youtube.com/c/DataSciencewithHarshit?sub_confirmation=1">Data Science with Harshit</a></h3>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/yapSsspJzAw" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<p> </p>
<p>With this channel, I am planning to roll out a couple of <a target="_blank" href="https://towardsdatascience.com/hitchhikers-guide-to-learning-data-science-2cc3d963b1a2?source=---------8------------------">series covering the entire data science space</a>. Here is why you should be subscribing to the <a target="_blank" href="https://www.youtube.com/channel/UCH-xwLTKQaABNs2QmGxK2bQ">channel</a>:</p>
<ul>
<li><p>These series would cover all the required/demanded quality tutorials on each of the topics and subtopics like <a target="_blank" href="https://towardsdatascience.com/python-fundamentals-for-data-science-6c7f9901e1c8?source=---------5------------------">Python fundamentals for Data Science</a>.</p>
</li>
<li><p>Explained <a target="_blank" href="https://towardsdatascience.com/practical-reasons-to-learn-mathematics-for-data-science-1f6caec161ea?source=---------9------------------">Mathematics and derivations</a> of why we do what we do in ML and Deep Learning.</p>
</li>
<li><p><a target="_blank" href="https://www.youtube.com/watch?v=a2pkZCleJwM&amp;t=2s">Podcasts with Data Scientists and Engineers</a> at Google, Microsoft, Amazon, etc, and CEOs of big data-driven companies.</p>
</li>
<li><p><a target="_blank" href="https://towardsdatascience.com/building-covid-19-analysis-dashboard-using-python-and-voila-ee091f65dcbb?source=---------2------------------">Projects and instructions</a> to implement the topics learned so far. Learn about new certifications, Bootcamp, and resources to crack those certifications like this <a target="_blank" href="https://youtu.be/yapSsspJzAw"><strong>TensorFlow Developer Certificate Exam by Google.</strong></a></p>
</li>
</ul>
<p>If this tutorial was helpful, you should check out my data science and machine learning courses on <a target="_blank" href="https://www.wiplane.com/">Wiplane Academy</a>. They are comprehensive yet compact and helps you build a solid foundation of work to showcase.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Train an Image Classifier and Teach Your Computer Japanese ]]>
                </title>
                <description>
                    <![CDATA[ By Ajay Uppili Arasanipalai Introduction Hi. Hello. こんにちは Those squiggly characters you just saw are from a language called Japanese. You’ve probably heard of it if you’ve ever watched Dragon Ball Z. _Source_ Here’s the problem though: you know thos... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-teach-your-computer-japanese/</link>
                <guid isPermaLink="false">66d45d5ed7a4e35e38434932</guid>
                
                    <category>
                        <![CDATA[ AI ]]>
                    </category>
                
                    <category>
                        <![CDATA[ algorithms ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Artificial Intelligence ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Computer Vision ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Deep Learning ]]>
                    </category>
                
                    <category>
                        <![CDATA[ fastai,  ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Machine Learning ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Sun, 21 Jul 2019 16:30:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2019/07/kmnist.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Ajay Uppili Arasanipalai</p>
<h2 id="heading-introduction">Introduction</h2>
<p>Hi. Hello. こんにちは</p>
<p>Those squiggly characters you just saw are from a language called Japanese. You’ve probably heard of it if you’ve ever watched Dragon Ball Z.</p>
<p><img src="https://assets.website-files.com/5ac6b7f2924c652fd013a891/5d2951d9e7d17d10d2b65c0b_100881-dragon-ball-z-dragon-ball-fight.gif" alt="Image" width="400" height="226" loading="lazy">
_<a href="http://fanaru.com/dragon-ball-z/image/100881-dragon-ball-z-dragon-ball-fight.gif" target="_blank">Source</a>_</p>
<p>Here’s the problem though: you know those ancient Japanese scrolls that make you look like you’re going to unleash an ultimate samurai ninja overlord super combo move.</p>
<p>Yeah, those. I can’t exactly read them, and it turns out that very few people can.</p>
<p>Luckily, a bunch of smart people understands how important it is that I master the Bijudama-Rasenshuriken, so they invented this thing called deep learning.</p>
<p>So pack your ramen and get ready. In this article, I’ll show you how to train a neural network that can accurately predict Japanese characters from  their images.</p>
<p>To  ensure that we get good results, I’m going to use of an incredible deep learning library called fastAI, which is a wrapper around PyTorch that  makes it easy to implement best practices from modern research. You can  read more about it on their <a target="_blank" href="https://docs.fast.ai">docs</a>.</p>
<p>With that said, let’s get started.</p>
<h2 id="heading-kmnist">KMNIST</h2>
<p>OK, so before we can create anime subtitles, we’re going to need a dataset. Today we’re going to focus on KMNIST.</p>
<p>This dataset takes of examples of characters from the Japanese Kuzushiji script, and organizes them into 10 labeled classes. The images measure 28x28 pixels, and there are 70,000 images in total, mirroring the  structure of MNIST.</p>
<p>But why KMNIST? Well firstly, it has “MNIST” in its name, and we all know how much people in machine learning love MNIST.</p>
<p><img src="https://assets.website-files.com/5ac6b7f2924c652fd013a891/5d2951dabfaf722c2f74abc4_kmnist.png" alt="Image" width="884" height="292" loading="lazy">
_<a href="http://codh.rois.ac.jp/img/kmnist.png" target="_blank">Source</a>_</p>
<p>So  in theory, you could just change a few lines of that Keras code that  you copy-pasted from Stack Overflow and BOOM! You now have computer code  that can <a target="_blank" href="https://www.wandb.com/articles/collaborative-deep-learning-for-reading-japanese">revive an ancient Japanese script</a>.</p>
<p>Of  course, in practice, it isn’t that simple. For starters, the cute  little model that you trained on MNIST probably won’t do that well.  Because, you know, figuring out whether a number is a 2 or a 5 is just a  tad easier than deciphering a forgotten cursive script that only a  handful of people on earth know how to read.</p>
<p><img src="https://assets.website-files.com/5ac6b7f2924c652fd013a891/5d2951d9e7d17dd802b65c0c_giphy.gif" alt="Animated GIF showing " width="500" height="470" loading="lazy"></p>
<p>Apart  from that, I guess I should point out that Kuzushiji, which is what the  “K” in KMNIST stands for, is not just 10 characters long.  Unfortunately, I’m <strong>NOT</strong> one of the handfuls of experts that can read the language, so I can’t describe in intricate detail how it works.</p>
<p>But  here’s what I do know: There are actually three variants of these  Kuzushiji character datasets — KMNIST, Kuzushiji-49, and  Kuzushiji-Kanji.</p>
<p>Kuzushiji-49 is variant with 49 classes instead of 10. Kuzushiji-Kanji is even more insane, with a whopping 3832 classes.</p>
<p>Yep, you read that right. It’s three times as many classes as ImageNet.</p>
<p>‍</p>
<h2 id="heading-how-to-not-mess-up-your-dataset">How to Not Mess Up Your Dataset</h2>
<p>To  keep things as MNIST-y as possible, it looks like the researchers who  put out the KMNIST dataset kept it in the original format (man, they  really took that whole MNIST thing to heart, didn’t they).</p>
<p>If you take a look at <a target="_blank" href="https://github.com/rois-codh/kmnist">the KMNIST GitHub repo</a>, you’ll see that the dataset is served in two formats: the original MNIST thing, and as a bunch of Numpy arrays.</p>
<p>Of course, I know you were probably too lazy to click that link. So here you go. You can thank me later.</p>
<p><img src="https://assets.website-files.com/5ac6b7f2924c652fd013a891/5d2951da80b61183001c8a76_s_F44ECE835EEC7420BCA13A4D3C5E89A345A0759A53AF1A997CB55909898D5236_1561571516749_Screenshot%2B2019-06-26%2Bat%2B11.20.09%2BPM.png" alt="GitHub screenshot showing the various download formats for the KMNIST dataset" width="982" height="649" loading="lazy">
_<a href="https://github.com/rois-codh/kmnist" target="_blank">Source</a>_</p>
<p>Personally,  I found the NumPy array format easier to work with when using fastai,  but the choice is yours. If you’re using PyTorch, KMNIST comes for free  as a part of <a target="_blank" href="https://pytorch.org/docs/stable/torchvision/datasets.html?highlight=kmnist#kmnist"><code>torchvision.datasets</code></a>.</p>
<p>The  next challenge is actually getting those 10,000-year-old brush strokes  onto your notebook (or IDE, who am I to judge). Luckily, the GitHub repo  mentions that there’s this handy script called <code>download_data.py</code> that’ll  do all the work for us. Yay!</p>
<p><img src="https://paper.dropboxstatic.com/static/img/ace/emoji/1f389.png?version=3.1.2" alt="party popper" width="64" height="64" loading="lazy"></p>
<p>From here, it’ll probably start getting awkward if I continue talking  about how to pre-process your data without actual code. So check out <a target="_blank" href="https://colab.research.google.com/gist/iyaja/fe102ae34312e48e637edd804a450207/kmnist.ipynb">the notebook</a> if you want to dive deeper.</p>
<p>Moving on…</p>
<h2 id="heading-should-i-use-a-hyper-ultra-inception-resnet-xxxl">Should I use a hyper ultra Inception ResNet XXXL?‍</h2>
<h3 id="heading-short-answer">Short Answer</h3>
<p>Probably not. A regular ResNet should be fine.</p>
<h3 id="heading-a-little-less-short-answer">A Little Less Short Answer</h3>
<p>Ok, look. By now, you’re probably thinking, “KMNIST big. KMNIST hard. Me need to use very new, very fancy model.”</p>
<p>Did I overdo the Bizzaro voice?</p>
<p>The point is, you <strong>DON’T</strong> need a shiny new model to do well on these image classification tasks.  At best, you’ll probably get a marginal accuracy improvement at the cost  of a whole lot of time and money.</p>
<p>Most of the time, you’ll just waste a whole lot of time and money.</p>
<p>So  heed my advice — just stick to good ol’ fashion ResNets. They work  really well, they're relatively fast and lightweight (compared to some  of the other memory hogs like Inception and DenseNet), and best of all,  people have been using them for a while, so it shouldn’t be too hard to  fine-tune.</p>
<p>If the  dataset you’re working with is simple like MNIST, use ResNet18. If it’s  medium-difficulty, like CIFAR10, use ResNet34. If it’s really hard,  like ImageNet, use ResNet50. If it’s harder than that, you can probably  afford to use something better than a ResNet.</p>
<p>Don’t believe me? Check out my leading entry for the Stanford DAWNBench competition from April 2019:</p>
<p><img src="https://assets.website-files.com/5ac6b7f2924c652fd013a891/5d2951dae06d1bb7f8a731ba_s_F44ECE835EEC7420BCA13A4D3C5E89A345A0759A53AF1A997CB55909898D5236_1561651063683_D4s0U9_UwAA3vk2.png" alt="Image" width="680" height="503" loading="lazy"></p>
<p>What do you see? ResNets everywhere! Now come on, there’s got to be a reason for that.‍</p>
<h2 id="heading-hyperparameters-galore">Hyperparameters Galore</h2>
<p>A few months ago, I wrote an article on <a target="_blank" href="https://blog.nanonets.com/hyperparameter-optimization/">how to pick the right hyperparameters</a>.  If you’re interested in a more general solution to this herculean task,  go check that out. Here, I’m going to walk you through my process of  picking good-enough hyperparameters to get good-enough results on  KMNIST.</p>
<p>To start off, let’s go over what hyperparameters we need to tune.</p>
<p>We’ve  already decided to use a ResNet34, so that’s that. We don’t need to  figure out the number of layers, filter size, number of filters, etc.  since that comes baked into our model.</p>
<p>See, I told you it would save time.</p>
<p>So  what’s remaining is the big three: learning rate, batch size, and the  number of epochs (plus stuff like dropout probability for which we can  just use the default values).</p>
<p>Let’s go over them one by one.</p>
<h3 id="heading-number-of-epochs">Number of Epochs</h3>
<p>Let’s  start with the number of epochs. As you’ll come to see when you play  around with the model in the notebook, our training is pretty efficient.  We can easily cross 90% accuracy within a few minutes.</p>
<p><img src="https://assets.website-files.com/5ac6b7f2924c652fd013a891/5d2955a222d8c93af99209f9_Screenshot%202019-07-13%20at%209.23.20%20AM.png" alt="Image" width="1336" height="297" loading="lazy"></p>
<p>So  given that our training is so fast in the first place, it seems  extremely unlikely that we would use too many epochs and overfit. I’ve  seen other KMNIST models train for over 50 epochs without any issues, so  staying in the 0-30 range should be absolutely fine.</p>
<p>That  means within the scope of the restrictions we’ve put on the model when  it comes to epochs, the more, the merrier. In my experiments, I found  that 10 epochs strike a good balance between model accuracy and training  time.</p>
<h3 id="heading-learning-rate">Learning Rate</h3>
<p>What  I’m about to say is going to piss a lot of people off. But I’ll say it  anyway — We don’t need to pay too much attention to the learning rate.</p>
<p>Yep, you heard me right. But give me a chance to explain.</p>
<p>Instead  of going “Hmm… that doesn’t seem to work, let’s try again with lr=3e-3  ,” we’re going to use a much more systematic and disciplined approach to  finding a good learning rate.</p>
<p>We’re going to use the learning rate finder, a revolutionary idea proposed by Leslie Smith in his <a target="_blank" href="https://arxiv.org/pdf/1506.01186.pdf">paper on cyclical learning rates</a>.</p>
<p>Here’s how it works:</p>
<ul>
<li>First,  we set up our model and prepare to train it for one epoch. As the model  is training, we’ll gradually increase the learning rate.</li>
<li>Along the way, we’ll keep track of the loss at every iteration.</li>
<li>Finally, we select the learning rate the corresponds to the lowest loss.</li>
</ul>
<p>When all is said and done, and you plot the loss against the learning rate, you should see something like this:</p>
<p><img src="https://assets.website-files.com/5ac6b7f2924c652fd013a891/5d2951dabfaf72811274abb2_s_F44ECE835EEC7420BCA13A4D3C5E89A345A0759A53AF1A997CB55909898D5236_1561652469267_Unknown.png" alt="Image" width="389" height="266" loading="lazy"></p>
<p>Now, before you get all giddy and pick 1e-01 as the learning rate, I’ll have you know that it’s <strong>NOT</strong> the best choice.</p>
<p>That’s  because fastai implements a smoothening technique called exponentially  weighted averages, which is the deep learning researcher version of an  Instagram filter. It prevents our plots from looking like the result of  giving your neighbors’ kid too much time with a blue crayon.</p>
<p><img src="https://assets.website-files.com/5ac6b7f2924c652fd013a891/5d2951dae06d1b5fb4a731bb_art2_loss_vs_lr.png" alt="Image" width="375" height="252" loading="lazy"></p>
<p>Since  we’re using a form of averaging to make the plot look smooth, the  “minimum” point that you’re looking at on the learning rate finder isn’t  actually a minimum. It’s an average.</p>
<p>Instead, to <em>actually</em> find the learning rate, a good rule of thumb is to pick the learning  rate that’s an order of magnitude lower than the minimum point on the  smoothened plot. That tends to work really well in practice.</p>
<p>I  understand that all this plotting and averaging might seem weird if all  you’ve been brute-forcing learning rate values all your life. So I’d  advise you to check out <a target="_blank" href="https://sgugger.github.io/how-do-you-find-a-good-learning-rate.html">Sylvain Gugger’s explanation of the learning rate finder</a> to learn more.</p>
<h3 id="heading-batch-size">Batch Size</h3>
<p>OK, you caught me red-handed here. My initial experiments used a batch size of 128 since that’s what the top submission used.</p>
<p>I  know, I know. Not very creative. But it’s what I did. Afterward, I  experimented with a few other batch sizes, and I couldn’t get better  results. So 128 it is!</p>
<p>In  general, batch sizes can be a weird thing to optimize, since it  partially depends on the computer you’re using. If you have a GPU with  more VRAM, you can train on larger batch sizes.</p>
<p>So  if I tell you to use a batch size of 2048, for example, instead of  getting that coveted top spot on Kaggle and eternal fame and glory for  life, you might just end up with a CUDA: out of memory error.</p>
<p>So  it’s hard to recommend a perfect batch size because, in practice, there  are clearly computational limits. The best way to pick it is to try out  values that work for you.</p>
<p>But how would you pick a random number from the vast sea of positive integers?</p>
<p>Well,  you actually don’t. Since GPU memory comes is organized in bits, it’s a  good idea to choose a batch size that’s a power of 2 so that your  mini-batches fit snugly in memory.</p>
<p>Here’s  what I would do: start off with a moderately large batch size like 512.  Then, if you find that your model starts acting weird and the loss is  not on a clear downward trend, half it. Next, repeat the training  process with a batch size of 256, and see if it behaves this time.</p>
<p>If it doesn’t, wash, rinse, and repeat.</p>
<h2 id="heading-a-few-pretty-pictures">A Few Pretty Pictures</h2>
<p>With  the optimizations going on here, it’s going to be pretty challenging to  keep track of this giant mess of models, metrics, and hyperparameters  that we’ve created.</p>
<p>To ensure that we all remain sane human beings while climbing the accuracy mountain, we’re going to use <a target="_blank" href="https://docs.wandb.com/docs/frameworks/fastai.html">the wandb + fastai integration</a>.</p>
<p>So what does wandb actually do?</p>
<p>It  keeps track of a whole lot of statistics about your model and how it’s  performing automatically. But what’s really cool is that it also  provides instant charts and visualizations to keep track of critical  metrics like accuracy and loss, all in real-time!</p>
<p>If  that wasn’t enough, it also stores all of those charts, visualizations,  and statistics in the cloud, so you can access them anytime anywhere.</p>
<p>Your days of starting at a black terminal screen and fiddling around with matplotlib are over.</p>
<p><a target="_blank" href="https://colab.research.google.com/gist/iyaja/fe102ae34312e48e637edd804a450207/kmnist.ipynb">The notebook tutorial</a> for this article has a straightforward introduction to how it works seamlessly with fastai. You can also check out <a target="_blank" href="https://app.wandb.ai/ajayuppili/kmnist/runs/41gbr2yx">the wandb workspace</a>, where you can take a look at all the stuff I mentioned without writing any code.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>これで終わりです</p>
<p>That means “this is the end.”</p>
<p>But  you didn't need me to tell you that, did you? Not after you went  through the trouble of getting a Japanese character dataset, using the  learning rate finder, training a ResNet using modern best practices, and  watching your model rise to glory using real-time monitoring in the  cloud.</p>
<p>Yep, in about 20 minutes, you actually did all of that! Give yourself a pat on the back.</p>
<p>And please, go watch some Dragonball.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How I used Deep Learning to classify medical images with Fast.ai ]]>
                </title>
                <description>
                    <![CDATA[ By James Dietle Convolutional Neural Networks (CNNs) have rapidly advanced the last two years helping with medical image classification. How can we, even as hobbyists, take these recent advances and apply them to new datasets? We are going to walk th... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-i-used-deep-learning-to-classify-medical-images-with-fast-ai-cc4cfd64173c/</link>
                <guid isPermaLink="false">66c34e27912fb29c4f156c0f</guid>
                
                    <category>
                        <![CDATA[ AI ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Deep Learning ]]>
                    </category>
                
                    <category>
                        <![CDATA[ fastai,  ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Machine Learning ]]>
                    </category>
                
                    <category>
                        <![CDATA[ tech  ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Wed, 27 Feb 2019 16:53:26 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/1*vyFlFjwlsfV7DX3kBDXJPQ.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By James Dietle</p>
<p>Convolutional Neural Networks (CNNs) have rapidly advanced the last two years helping with medical image classification. How can we, even as hobbyists, take these recent advances and apply them to new datasets? We are going to walk through the process, and it’s surprisingly more accessible than you think.</p>
<p>As our family moved to Omaha, my wife (who is in a fellowship for pediatric gastroenterology) came home and said she wanted to use image classification for her research.</p>
<p>Oh, I was soooo ready.</p>
<p>For over two years, I have been playing around with deep learning as a hobby. I even wrote several articles (<a target="_blank" href="https://medium.com/@JamesDietle/part-of-the-fun-of-learning-data-science-is-seeing-how-quickly-it-can-relate-to-your-usual-roles-ceb7b0ff5f13">here</a> and <a target="_blank" href="https://medium.com/@JamesDietle/9-months-in-the-hobby-of-deep-learning-d688cce4fa2e">here</a>). Now I had some direction on a problem. Unfortunately, I had no idea about anything in the gastrointestinal tract, and my wife hadn’t programmed since high school.</p>
<h3 id="heading-start-from-the-beginning"><strong>Start from the beginning</strong></h3>
<p>My entire journey into deep learning has been through the <a target="_blank" href="https://www.fast.ai/">Fast.ai</a> process. It started 2 years ago when I was trying to validate that all the “AI” and “Machine Learning” we were using in the security space wasn’t over-hyped or biased. It was, and we steered clear from those technologies. The most sobering fact was learning that being an expert in the field takes a little experimentation.</p>
<h4 id="heading-setup"><strong>Setup</strong></h4>
<p>I have used Fast.ai for all the steps, and the newest version is making this more straightforward than ever. The ways to create your learning environment are proliferating rapidly. There are now docker images, Amazon amis, and services (like <a target="_blank" href="https://www.crestle.com/">Crestle</a>) that make it easier than ever to set up.</p>
<p>Whether you are the greenest of coding beginners or experienced ninja, <a target="_blank" href="https://course.fast.ai/">start here</a> on the Fast.ai website.</p>
<p>I opted to build my machine learning rig during a previous iteration of the course. However, it is not necessary, and I would recommend using another service instead. Choose the easiest route for you and start experimenting.</p>
<h4 id="heading-changes-to-fastai-with-version-3"><strong>Changes to Fast.ai with version 3</strong></h4>
<p>I have taken the other iterations of Fast.ai, and after reviewing the newest course, I noticed how much more straightforward everything was in the notebook. Documentation and examples are everywhere.</p>
<p>Let’s dive into “<a target="_blank" href="https://github.com/fastai/course-v3/blob/master/nbs/dl1/lesson1-pets.ipynb">lesson1-pets</a>”, and if you have setup Fast.ai feel free to follow along in your personal jupyter instance.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/u7vNdhatx2eygqg8w4IUCXuZGZuRHIx2y4f5" alt="Image" width="800" height="182" loading="lazy">
<em>lesson1-pets from Fast.ai</em></p>
<p>I prepared for the first lesson (typically defining between 2 classes — cats and dogs — as I had many times before. However, I saw this time that we were doing something much more complex regarding 33 breeds of cats and dogs using fewer lines of code.</p>
<p><strong>The CNN was up and learning in 7 lines of code!!</strong></p>
<p>That wasn’t the only significant change. Another huge stride was in showing errors. For example, we could quickly see a set of the top losses (items we confidently predicted wrong) and corresponding pet pictures from our dataset below.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/KWKmlZf52x6jVJPZDmtUMITcbqCbHl54Tjwh" alt="Image" width="800" height="291" loading="lazy">
<em>Incorrect cat and dog breed predictions</em></p>
<p>This function was pretty much a spot check for bad data. Ensuring a lion, tiger, or bear didn’t sneak into the set. We could also see if there were glaring errors that were obvious to us.</p>
<p>The confusion matrix was even more beneficial to me. It allowed me to look across the whole set for patterns in misclassification between the 33 breeds.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/sfF1pvbZpjjbu3n6GjRMuRaUbQxHAMg-jeTm" alt="Image" width="800" height="635" loading="lazy"></p>
<p>Of the 33 breeds presented, we could see where our data diverged and ask ourselves if it made sense. A few breeds popped out in particular, and here are examples of the commonly confused images:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/59yz56xv0LGDuWt8T1iQuqWRP-lE74eJqUkK" alt="Image" width="606" height="374" loading="lazy">
<em>Staffordshire terrier and American terrier.</em></p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/8vnEnaLgEN6Dm9I6AeIzYzxD3-4MbV36UYMt" alt="Image" width="420" height="388" loading="lazy">
<em>Egyptian Mau and Bengal</em></p>
<p>Not being a pet owner or enthusiast, I wouldn’t have be able to figure out these subtle details out about a breed’s subtle features. The model is doing a much better job than I would’ve been able to do! While I am certainly getting answers, I am also curious to find that missing feature or piece of data to improve the model.</p>
<p>There is an important caveat. We are now at the point where the model is <em>teaching</em> us about the data. Sometimes we can get stuck in a mindset where the output is the end of the process. If we fall into that trap, we might miss a fantastic opportunity to create a positive feedback loop.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/2YFbSBKXrC8F4-AZn65WWIiJQ7rLnHkoAOBW" alt="Image" width="800" height="617" loading="lazy">
<em>30-second powerpoint drawing</em></p>
<p>Therefore, we are sitting a little wiser and little more confident in the 4th phase. Given this data, what decisions should I improve accuracy with?</p>
<ul>
<li>More training</li>
<li>More images</li>
<li>More powerful architecture</li>
</ul>
<p>Trick question! I am going to look at a different dataset. Let’s get up and personal with endoscope images of people’s insides.</p>
<h3 id="heading-get-the-dataset-see-a-whole-lot-of-sh-stuff"><strong>Get the dataset, see a whole lot of sh… stuff</strong></h3>
<p>For anyone else interested in gastroenterology I recommend looking into <a target="_blank" href="https://datasets.simula.no/kvasir/#data-collection">The Kvasir Dataset</a>. A good description from their site is:</p>
<blockquote>
<p>the dataset containing images from inside the gastrointestinal (GI) tract. The collection of images are classified into three important anatomical landmarks and three clinically significant findings. In addition, it contains two categories of images related to endoscopic polyp removal. Sorting and annotation of the dataset is performed by medical doctors (experienced endoscopists)</p>
</blockquote>
<p>There is also a <a target="_blank" href="https://www.researchgate.net/publication/316215961_KVASIR_A_Multi-Class_Image_Dataset_for_Computer_Aided_Gastrointestinal_Disease_Detection">research paper</a> by experts (Pogorelov et al.) describing how they tackled the problem, which includes their findings.</p>
<p>Perfect, this is an excellent dataset to move from pets to people. Although a less cuddly dataset (that also includes stool samples) it is something exciting and complete.</p>
<p>As we download the data, the first thing we notice is that there are 8 classes in this dataset for us to classify instead of the 33 from before. However, it shouldn’t change any of our other operations.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/uo1ea2vqjqGnAJwIXtSBKnHIjWhRJrXi0LXx" alt="Image" width="800" height="68" loading="lazy"></p>
<p><em>Side Note: Originally, I spent a few hours scripting out how to move folders into validation folders, and spent some good time setting everything up. The scripting effort turned out to be a waste of time because there is already a simple function to create a validation set.</em></p>
<p><em>The lesson is “if something is a pain, chances are someone from the Fast.ai community has already coded it for you.”</em></p>
<h3 id="heading-diving-into-the-notebook">Diving into the notebook</h3>
<p><em>You can pick up my Jupyter notebook from <a target="_blank" href="https://github.com/jamesdietle/fastaipart3/blob/master/Kvasir-Dataset2.ipynb">GitHub here</a>.</em></p>
<h4 id="heading-building-for-speed-and-experimentation"><strong>Building for speed and experimentation</strong></h4>
<p>As we start experimenting, it is crucial to get the framework correct. Try setting up the minimum needed to get it working that can scale up later. Make sure data is being taken in, processed, and provides outputs that make sense.</p>
<p>This means:</p>
<ul>
<li>Use smaller batches</li>
<li>Use lower numbers of epochs</li>
<li>Limit transforms</li>
</ul>
<p>If a run is taking longer than 2 minutes, figure out a way to go faster. Once everything is in place, we can get crazy.</p>
<h4 id="heading-data-handling">Data Handling</h4>
<p>Data prioritization, organization, grooming, and handling is the most important aspect of deep learning. Here is a crude picture showing how data handling occurs, or you can read the <a target="_blank" href="https://docs.fast.ai/basic_data.html">documentation</a>.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/Ni-fwUCcGWDAXcUlCqgVl8Epvi13uUqUHVwl" alt="Image" width="800" height="375" loading="lazy"></p>
<p>Therefore we need to do the same thing for the endoscope data, and it is one line of code.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/JtZ6HKXcNXHZbxTGaFNOaMEnI8zVSJeF4dgS" alt="Image" width="800" height="41" loading="lazy"></p>
<p>Explaining the variables:</p>
<ul>
<li>Path points to our data (#1)</li>
<li>The validation set at 20% to properly create dataloaders</li>
<li>default transforms</li>
<li>the image size set at 224</li>
</ul>
<p>That’s it! The data block is all set up and ready for the next phase.</p>
<h4 id="heading-resnet">Resnet</h4>
<p>We have data and we need to decide on an architecture. Nowadays Resnet is popularly used for image classification. It has a number after it which equates to the number of layers. Many <a target="_blank" href="https://medium.com/@14prakash/understanding-and-implementing-architectures-of-resnet-and-resnext-for-state-of-the-art-image-cf51669e1624">better articles</a> exist <a target="_blank" href="https://medium.com/@14prakash/image-classification-architectures-review-d8b95075998f">about Resnet</a>, therefore, to simplify for this article:</p>
<blockquote>
<p>More layers = more accurate (Hooray!)</p>
<p>More layers = more compute and time needed (Boo..)</p>
</blockquote>
<p>Therefore Resnet34 has 34 layers of image finding goodness.</p>
<h4 id="heading-ready-im-ready">Ready? I’m ready!</h4>
<p>With the structured data, architecture, and a default error metric we have everything we need for the learner to start fitting.</p>
<p>Let’s look at some code:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/Y-uV2EnLty823Yv1yMquSiR2aRgacmKyd1ck" alt="Image" width="800" height="324" loading="lazy"></p>
<p>We see that after the cycles and 7 minutes we get to 87% accuracy. Not bad. Not bad at all.</p>
<p>Not being a doctor, I have a very untrained eye looking at these. I have no clue what to be looking for, categorization errors, or if the data is any good. So I went straight to the confusion matrix to see where mistakes were being made.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/EVJNURCQyxNtY8JnWDo7gQ-nbpxjG5P04ow2" alt="Image" width="800" height="713" loading="lazy"></p>
<p>Of the 8 classes, 2 sets of 2 are often confused with each other. As a baseline, I could only see if they are dyed, polyps, or something else. So compared to my personal baseline of 30% accuracy, the machine is getting an amazing 87%.</p>
<p>After looking at the images from these 2 sets side by side, you can see why. (Since they are medical images, they might be NSFW and are present in the Jupyter notebook.)</p>
<ol>
<li>The dyed sections are being confused with each other. This type of error can be expected. They are both blue and look very similar to each other.</li>
<li>Esophagitis is hard to tell from a normal Z-line. Perhaps esophagitis presents redder than Z-line? I’m not certain.</li>
</ol>
<p>Regardless, everything seems great, and we need to step up our game.</p>
<h3 id="heading-more-layers-more-images-more-power">More layers, more images, more power!</h3>
<p>Now that we see our super fast model working, let’s switch over to the powerhouse.</p>
<ul>
<li>I increased the size of the dataset from v1 to v2. The larger set doubles the number of images available from 4000 to 8000. <em>(Note: All examples in this article show v2.)</em></li>
<li>Transform everything that makes sense. There are lots of things you can tweak. We are going to go into more of this shortly.</li>
<li>Since the images from the dataset are relatively large, I decided to try making the size bigger. Although this would be slower, I was curious if it would be better able to pick out little details. This hypothesis still requires some experimentation.</li>
<li>More and more epochs.</li>
<li>If you remember from before, Resnet50 would have more layers (be more accurate) but would require more compute time and therefore be slower. So we will change the model from Resnet34 to Resnet50.</li>
</ul>
<h4 id="heading-transforms-getting-the-most-of-an-image"><strong>Transforms: Getting the most of an image</strong></h4>
<p>Image transforms are a great way to improve accuracy. If we make random changes to an image (rotate, change color, flip, etc.) we can make it seem like we have more images to train from and we are less likely to overfit. Is it as good as getting more images? No, but it’s fast and cheap.</p>
<p>When choosing which transforms to use, we want something that makes sense. Here are some examples of normal transforms of the same image if we were looking at dog breeds. If any of these individually came into the dataset, we would think it makes sense. Putting in transforms we now we have 8 images instead for every 1.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/HnxacZmYHwcPPBgjOeLVLBh8YllnaULywJBn" alt="Image" width="800" height="383" loading="lazy"></p>
<p>What if in the transformation madness we go too far? We could get the images below that are a little too extreme. We wouldn’t want to use many of these because they are not clear and do not correctly orient in a direction we would expect data to come in. While a dog could be tilted, it would never be upside down.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/MNijsrlyoAn6dSbT2SiepF27riQolrHI7LA3" alt="Image" width="800" height="400" loading="lazy"></p>
<p>For the endoscope images, we are not as concerned about it being upside down or over tilted. An endoscope goes all over the place and can have a 360-degree rotation here, so I went wild with rotational transforms. Even a bit with the color as the lighting inside the body would be different. All of these seem to be in the realm of possibility.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/tpnXtApoMmk8rhYu71DdHORHiCP5oVwXHF9q" alt="Image" width="800" height="403" loading="lazy">
<em>Example of dyed polyps</em></p>
<p><em>(Note: the green box denotes how far the scope traveled. Therefore, this technique might be cutting off the value that could have provided.)</em></p>
<h4 id="heading-reconstructing-data-and-launching">Reconstructing data and launching</h4>
<p>Now we can see how to add transforms and how we would shift other variables for data:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/QUZEWFkUm8lcFXTCWXM58rplndCdQUW1A2M4" alt="Image" width="800" height="120" loading="lazy"></p>
<p>Then we change the learner:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/jzQl2sQv19lAeWrUdY4B6UpXYbmo40tjy0mr" alt="Image" width="800" height="111" loading="lazy">
<em>It really is that easy</em></p>
<p>Then we are ready to fire!</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/ApcLKcBsWNAF1Iz6Pw0cGx6sBVnc2tgB6NjK" alt="Image" width="300" height="225" loading="lazy"></p>
<p><em>Many epochs later…</em></p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/qHbnsIFF1V209q1rVzFmzMZvE7Vz0EjN-oA4" alt="Image" width="514" height="62" loading="lazy">
<em>Just worry about the number of the right here</em></p>
<p>93% accurate! Not that bad, let’s look a the confusion matrix again.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/LfwbVbdB131A6yIuizYC2KpS02lZ1KqMJZx1" alt="Image" width="800" height="707" loading="lazy"></p>
<p>It looks like the problem with dyed classification has gone away, but the esophagitis errors remain. In fact, the numbers of errors get worse in some of my iterations.</p>
<h3 id="heading-can-this-run-in-production">Can this run in production?</h3>
<p>Yes, there are instructions to quickly host this information as a web service. As long as the license isn’t up and you don’t mind waiting… you can try it on <a target="_blank" href="https://kvasir-demo.onrender.com/">Render right here</a>!</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/5YnqATL1HQXt7zcTcvCi2wEeXQxVLMrq43BH" alt="Image" width="800" height="738" loading="lazy"></p>
<h3 id="heading-conclusion-and-follow-up">Conclusion and Follow-up:</h3>
<p>As you can see, it is straightforward to transfer the new course from Fast.ai to a different dataset. Much more accessible than ever before.</p>
<p>When going through testing, make sure you start with a fast concept to make sure everything is on the right path, then turn up the power later. Create a positive feedback loop to make sure you are both oriented correctly and as a mechanism to force you to learn more about the dataset. You will have a much richer experience in doing so.</p>
<p>Some observations on this dataset.</p>
<ul>
<li>I am trying to solve this problem wrong. I am using a single classifier when these slides have multiple classifications. I discovered this later while reading the research paper. <em>Don’t wait until the end to read papers!</em></li>
<li>As a multi-classification problem, I should be including bounding boxes for essential features.</li>
<li>Classifications can benefit from a feature describing how far the endoscope is in the body. Significant landmarks in the body would help to classify the images. The small green box on the bottom left of the images is a map describing where the endoscope is and might be a useful feature to explore.</li>
<li>If you haven’t seen the new fast.ai course take a look, it took me more time to write this post than it did to code the program, it was that simple.</li>
</ul>
<p><strong>Resources</strong></p>
<ul>
<li><a target="_blank" href="https://github.com/jamesdietle/fastaipart3/blob/master/Kvasir-Dataset2.ipynb">Github Notebook</a></li>
<li><a target="_blank" href="https://datasets.simula.no/kvasir/#data-collection">Kvasir Dataset</a></li>
<li><a target="_blank" href="https://www.researchgate.net/publication/316215961_KVASIR_A_Multi-Class_Image_Dataset_for_Computer_Aided_Gastrointestinal_Disease_Detection">KVASIR: A Multi-Class Image Dataset for Computer Aided Gastrointestinal Disease Detection</a> (Pogorelov, Konstantin &amp; Randel, Kristin &amp; Griwodz, Carsten &amp; de Lange, Thomas &amp; Eskeland, Sigrun &amp; Johansen, Dag &amp; Spampinato, Conceo &amp; Dang Nguyen, Duc Tien &amp; Lux, Mathias &amp; Schmidt, Peter &amp; Riegler, Michael &amp; Halvorsen)</li>
<li><a target="_blank" href="https://docs.fast.ai/">FastAI</a></li>
<li><a target="_blank" href="https://pytorch.org/docs/master/">PyTorch</a></li>
<li><a target="_blank" href="https://youtu.be/GXuqT4uMKZk">Youtube video on this topic</a></li>
</ul>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
