<?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" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Inveterate Learner - Medium]]></title>
        <description><![CDATA[We are a couple of graduates from IIT Guwahati who are extremely fascinated by AI and love to learn something new from everything around us. - Medium]]></description>
        <link>https://medium.com/inveterate-learner?source=rss----ba6eaa0b1544---4</link>
        <image>
            <url>https://cdn-images-1.medium.com/proxy/1*TGH72Nnw24QL3iV9IOm4VA.png</url>
            <title>Inveterate Learner - Medium</title>
            <link>https://medium.com/inveterate-learner?source=rss----ba6eaa0b1544---4</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sun, 15 Nov 2026 04:08:22 GMT</lastBuildDate>
        <atom:link href="https://medium.com/feed/inveterate-learner" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com/" rel="hub"/>
        <item>
            <title><![CDATA[LLMs as single-step reasoners: mitigating hallucination in multi-step reasoning]]></title>
            <link>https://medium.com/inveterate-learner/llms-as-single-step-reasoners-mitigating-hallucination-in-multi-step-reasoning-bd109f8a5bfa?source=rss----ba6eaa0b1544---4</link>
            <guid isPermaLink="false">https://medium.com/p/bd109f8a5bfa</guid>
            <category><![CDATA[large-language-models]]></category>
            <category><![CDATA[machine-learning]]></category>
            <category><![CDATA[ai]]></category>
            <category><![CDATA[nlp]]></category>
            <category><![CDATA[deep-learning]]></category>
            <dc:creator><![CDATA[Aman Dalmia]]></dc:creator>
            <pubDate>Thu, 28 Mar 2024 06:55:36 GMT</pubDate>
            <atom:updated>2024-03-28T07:11:39.411Z</atom:updated>
            <content:encoded><![CDATA[<h4>LLMs struggle with multi-level reasoning in a single inference step, often resulting in hallucination. Breaking the problem down into smaller steps could be the key!</h4><p><em>Special thanks to </em><a href="https://in.linkedin.com/in/shreyasajal"><em>Shreya Sajal</em></a><em>, </em><a href="https://in.linkedin.com/in/thevishalagarwal"><em>Vishal Agarwal</em></a><em> and </em><a href="https://in.linkedin.com/in/aravinth-muthu-259663108"><em>Aravinth Muthu</em></a><em> for giving very helpful feedback on previous versions of this post!</em></p><p>A common challenge with using Large Language Models (LLMs) in production is hallucination, where a model produces responses that sounds real/accurate but is factually incorrect, leading to lack of reliability in LLM-powered apps. We have been using LLMs successfully in production to analyse and extract information from thousands of legal contracts at <a href="https://www.hyperstart.com/">HyperStart</a>, a contract-lifecycle management tool for Small and Medium scale Businesses (SMBs). In this post, I’ll share a simple technique that has improved the accuracy and reliability of our system on the most challenging tasks multi-fold.</p><p>Before we jump into the approach, let’s understand the problem a bit more. The two most common techniques for mitigating hallucination are Chain-Of-Thought (CoT) prompting [<a href="https://cameronrwolfe.substack.com/p/chain-of-thought-prompting-for-llms">1</a>, <a href="https://www.rungalileo.io/blog/mastering-rag-llm-prompting-techniques-for-reducing-hallucinations">2</a>] and Retrieval Augmented Generation (RAG) [<a href="https://cameronrwolfe.substack.com/p/a-practitioners-guide-to-retrieval">3</a>, <a href="https://www.rungalileo.io/blog/tags/rag">4</a>]. If you’re not already familiar with these, do check out the links and return back to the blog post later.</p><p>You might be able to tackle hallucination for your specific use case almost entirely using CoT + RAG itself (although you will likely need to <a href="https://medium.com/inveterate-learner/a-simple-not-easy-technique-for-debugging-llms-using-llms-d97a175e4bb5">iterate</a> a few times to land at the right custom prompt). However, if your problem statement involves a strong reasoning component with multiple reasoning steps, this might not be enough. The gap between where you want to be and where you land after applying CoT + RAG (and their variations) [<strong>the reasoning gap</strong>] is what this blog post aims to fill.</p><p><em>Note: I haven’t tested Claude Opus/Gemini 1.5 yet (the only other models in the class of GPT4 at the time of this post) and it is very likely that future versions of all these models will be much better at reasoning, in which case you might not need this technique. But one can speculate that when that future arrives, you might not need a lot of things. But that’s a separate post. Let’s focus on solving the problems of today while being optimistic about the future!</em></p><p>For ease of understanding, let’s assume you want the LLM to produce the desired output in a given JSON format. Arriving at the final JSON answer requires multiple steps of reasoning. Let’s consider the following example to automatically screen a candidate’s resume:</p><pre>System prompt:<br>You are a very good recruiting assistant. <br><br>You will be given the resume of a candidate for a Machine Learning role. <br><br>You need to assess whether the candidate must be shortlisted.<br><br>Use the following criteria for deciding if the candidate must be shortlisted:<br>- Number of internships in machine learning/deep learning<br>- GPA<br>- Number of publications and personal projects they have worked on related to<br>  machine learning<br><br>If the GPA is more than 9.5, then, they only need to have one internship to be<br>shortlisted. If the GPA is more than 9 but less than 9.5, along with one<br>internship, they need at least one publications or projects as well. If the<br>GPA is between 8 and 9, publications + project + internship must be &gt;= 3, with<br>at least one internship. Otherwise, the number combined must be atleast 4.<br><br>Give your final answer as a JSON with the key `is_shortlisted` which should be a boolean value.</pre><p>This is an example of a multi-step reasoning task as the LLM has to first extract various details like the GPA, identify which parts of the CV represent projects vs internships vs publications, classify the relevance of each of them and then, use the provided rubric to come up with the final answer.</p><p>Here, the candidate’s resume will be provided as context to the LLM for extracting the final answer. Since we’ve asked the model to simply output a JSON, without any chain-of-thought prompting, the model will likely instantly respond with:</p><pre>{ &quot;is_shortlisted&quot;: True }</pre><p><em>Note: this is a relatively simpler example and the actual challenge here is figuring out how to classify a given project/internship/publication as relevant. But let’s ignore that for now and focus on the model’s behaviour.</em></p><p>You might evaluate this prompt on your dataset and are likely to observe poor performance. Your first instinct should be to utilise “Chain-of-Thought Prompting” which asks the model to include reasoning steps before arriving at the final answer. You’re likely to notice a significant boost in performance.</p><p>However, you might notice there are still several mistakes. Upon inspecting the responses, you might notice that the model correctly inferred the GPA as well as the number of relevant projects (n_p), internships (n_i) and publications (n_pu) individually. However, it still failed to arrive at the correct output. For one such error sample, it might have incorrectly added n_pi, n_p, and n_i. For another one, it might have computed the sum correctly but failed to follow the rubric.</p><p>There are two types of reasoning steps you’ll encounter when breaking a problem into smaller steps. We’ll be looking at each of them with an example along with how to tackle them.</p><h4><strong>Deterministic reasoning</strong></h4><p>In this case, the next reasoning step is deterministic over the outputs of the previous reasoning steps. As shown in the example above, is_shortlisted must be decided using a rubric (mentioned in the system prompt), which is a deterministic step, given the gpa, n_pu, n_i, and n_p as inputs.</p><p>Instead of asking the LLM to output is_shortlisted, the core information that only the LLM can extract is really just gpa, n_pu, n_i, and n_p . We don’t need the LLM to refer to the rubric to give the final output. The LLM is just a tool and we should use the right tool to solve a given problem. Once the values have been extracted, the LLM is not the right tool to follow the rubric. The rubric can simply be applied outside the LLM call as shown in the image below.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*f9XIQV2gubOMuDAsq5nydA.png" /><figcaption>An example of how using LLMs as single step reasoners can help mitigate hallucinations for the deterministic reasoning case. For semantic reasoning, the deterministic rubric can be replaced by one or more LLM calls as described in the second example below.</figcaption></figure><p>An additional benefit of doing this is one level deeper explainability for the final response given by the system as we now know the input to the rubric, which helps with building user trust as well as debugging (in case the inputs have been extracted incorrectly).</p><h4>Semantic reasoning</h4><p>Here, the current reasoning step requires an LLM to operate on the outputs of the previous steps to arrive at the final answer. Suppose your task is to count the number of times the co-leads in a movie script are playing a positive role vs a negative role. You could ask the LLM to give the answer directly in one go. But it is possible that it might confuse the positive/negative role occurrences between the co-leads.</p><p>A better approach could be:</p><ol><li>Extract the names of the co-leads (1 LLM call)</li><li>For each name, count the number of times that person played a positive and negative role (<em>N</em> API calls for <em>N</em> co-leads).</li></ol><h4><strong>Summary</strong></h4><p>Given the examples above, the core idea can be summarised as:</p><ul><li>Break the problem statement down into smaller steps such that every reasoning step requires only one level of reasoning (as explained above).</li><li>At each step, use the LLM as an extractor of information that can be used by the next step to get closer to the final output.</li><li>Depending on whether the current step requires deterministic or requires semantic reasoning, either avoid using LLMs (e.g. handle conditionals separately through code instead of asking an LLM to follow a given rubric) or make further LLM calls respectively.</li></ul><p>It probably does not look very different from thinking step-by-step or using function calling in agentic flows. The key change proposed here is in the mindset of what each step means. Typically, we expect an LLM inference to perform all the reasoning steps in one go before arriving at the final answer, even steps where an LLM is not even needed (e.g. following a rubric). LLM Agent flows would usually consider the multiple steps we’ve proposed as just one block in the flow, with a single LLM call. A mindset shift is needed to see one block as being composed of potentially multiple blocks itself.</p><p>There are a couple of tradeoffs in this approach that you must be aware of. If the individual steps require semantic reasoning, you’ll need to make multiple LLM calls, which will increase your inference cost and time. If your problem statement resembles the second example above (extracting the number of negative and positive roles for all the co-leads), you can run the LLM inference for each co-lead in parallel in the second step, reducing the increase in the overall inference time.</p><h4>Conclusion</h4><p>This technique has radically improved the reliability of the systems I’ve built and given a massive boost to their overall accuracy. I hope this post was helpful and gave you a handy tool for improving the performance of your LLM apps too.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=bd109f8a5bfa" width="1" height="1" alt=""><hr><p><a href="https://medium.com/inveterate-learner/llms-as-single-step-reasoners-mitigating-hallucination-in-multi-step-reasoning-bd109f8a5bfa">LLMs as single-step reasoners: mitigating hallucination in multi-step reasoning</a> was originally published in <a href="https://medium.com/inveterate-learner">Inveterate Learner</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[A simple (not easy) technique for debugging LLMs using LLMs]]></title>
            <link>https://medium.com/inveterate-learner/a-simple-not-easy-technique-for-debugging-llms-using-llms-d97a175e4bb5?source=rss----ba6eaa0b1544---4</link>
            <guid isPermaLink="false">https://medium.com/p/d97a175e4bb5</guid>
            <category><![CDATA[large-language-models]]></category>
            <category><![CDATA[ai]]></category>
            <category><![CDATA[llm]]></category>
            <category><![CDATA[prompt-engineering]]></category>
            <category><![CDATA[llmops]]></category>
            <dc:creator><![CDATA[Aman Dalmia]]></dc:creator>
            <pubDate>Tue, 27 Feb 2024 16:12:56 GMT</pubDate>
            <atom:updated>2024-02-27T16:12:56.203Z</atom:updated>
            <content:encoded><![CDATA[<h4>Replication, problem identification, iteration, double checking and benchmarking</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/960/1*nBRxSjX1mkM_FRcTifPtug.png" /><figcaption>The overall flow for debugging LLMs. Each of the parts are described in detail below.</figcaption></figure><p>I’ve been working with LLMs on production for the last 10 months. Naturally, reliability and accuracy become crucial. So is debugging LLMs. I haven’t seen enough discussions around the processes people have adopted for debugging LLMs. But that is natural given that there hasn’t been enough time for best practices to emerge yet. I want to contribute my bit to the conversation by sharing the technique I’ve arrived at which has helped me dramatically improve the accuracy and reliability of the systems I build, quickly and efficiently:</p><ul><li><strong>Replication</strong>: Copy the system prompt and user prompt for which the LLM is failing to OpenAI’s Playground (after formatting, i.e. “\n” should become a new line), set all the parameters like temperature, max_tokens, top_p, etc. to the exact same value as that in your API call and hit “Submit”. If you’re lucky, you would be able to replicate the issue on the first go. Depending on your settings, however, you might have to repeat this a few times until you can reproduce the bug because the LLM’s output can vary on each API call (the chances of this reduces if you set temperature to 0 but it doesn’t guarantee deterministic outputs as described in more detail below).</li><li><strong>Problem identification</strong>: Once you’re able to replicate the issue, simply ask the LLM to “explain” the part of the output that is incorrect. It is very important not to ask “why did you output X” as the LLM will simply resort to apologising and giving the correct answer. The goal of this step is to figure out the part (s) of your prompt that is confusing the LLM, or any instructions that are missing in your prompt for the specific edge case where it is failing, probably because it is trying to provide an answer with missing information.</li><li><strong>Iteration</strong>: Once you’ve identified what’s incorrect or missing, you need to update your prompt to handle that edge case. The way you word your new instruction matters a lot. Writing correct grammatical sentences with consistent, appropriate spacing and punctuation marks has an unexpected impact on the consistency and reliability of the outputs. You might have to experiment with adding the instruction at the start of the prompt or at the end, or inside the description for a field if you’re extracting a JSON and have provided a JSON template for the LLM to output. I tend to keep a section named “Important Instructions” in my system prompt to which I keep adding new instructions as the need surfaces upon debugging. Now, you might be tempted to pile on more and more instructions but Mark Twain once said, “I didn’t have time to write a short letter, so I wrote a long one instead”. It takes more effort to identify the clunky bits in your prompt and make your prompt concise. If it is becoming confusing for you to go through the list of instructions, it is likely confusing for the LLM as well. Keep going back and try to find redundant pieces of instructions or instructions that are contradicting each other. You might have written an instruction as an overly complicated sentence. Sometimes, making a sentence simpler solves the problem. You are likely to see that the problem persists even after adding a new instruction that should have ideally handled the edge case. In such cases, you might want to rephrase your instruction or make it “shout” by adding phrases like: “if so and so happens, make sure to ALWAYS do so and so. It is very important that you pay a lot of attention to this and never make a mistake”. There is nothing magical about this exact phrase. It is just an example meant to convey a point. The main takeaway being that prompt engineering requires a lot of perseverance the harder your task is and the more nuanced your edge case becomes. You cannot give up. You have to keep iterating. But don’t blindly iterate. Pay attention to the pattern of its mistakes and find smarter experiments to try rather than simply adding/removing sentences/words randomly/thoughtlessly.</li><li><strong>Double checking</strong>: Alas, the moment has arrived. Your hours of hard work has paid off and the LLM is finally able to give the correct output. Unfortunately, it’s not yet the time to celebrate. Delete the assistant response and hit “Submit” again. You cannot believe yourself. It is back to generating the incorrect output. “How can that be?”, you might wonder. “The temperature is 0, shouldn’t the output be deterministic?”. Unfortunately, not. The parameters like temperature, top_p, etc. are just some of the sources of randomness in the inference step of an LLM. There are others that you cannot control. Because of this, even with the temperature being 0, the outputs of the LLM can vary. Sometimes, these variations are not harmful because they eventually land at the same answer, even if they are using a different combination of words in the output. But sometimes, they can break your heart and hurt your sleep. Typically, these variations that oscillate between the correct and the incorrect output are a result of ambiguity, confusion, contradiction or lack of instructions in your prompt. Thus, you’ll have to go back to the “Iteration” step to update your prompts until multiple LLM calls for the same input give the correct output consistently every time.</li><li><strong>Benchmarking</strong>: Are you kidding me? We aren’t done yet? Unfortunately not. But we are engineers who care about building a solid, reliable system using a technology that has immense potential but doesn’t have a good reputation for reliability. So, you found what was missing or incorrect in your prompt and after 100s of iterations, you’ve finally landed on something that consistently produces the correct output for the edge case where it was previously failing. That’s awesome. But how do you know that the new prompt doesn’t create new edge cases? You don’t. So, you’ll need to rerun the inference on your entire benchmark dataset (if you don’t have a benchmark dataset and you’re building an LLM application for production, you really need one, like, yesterday, trust me). If none of the other examples are affected, bravo. The debugging is complete. At least, for the moment. However, if the performance worsens on other samples now, you’ll have to go back to step 1 for those new erroneous samples.</li></ul><p>If the sounds like a lot of work, it is. But that is also what makes it fun (although it doesn’t look like anything remotely resembling fun when you’re knee deep in the debugging process). Not everyone will be able to persevere, find the correct underlying patterns that can apply correctly across all the samples, gracefully handling all the edge cases. But you did. And that’s what makes you awesome.</p><p>I hope you learnt something useful from this post. I’d love to hear your experiences (and frustrations) with prompt engineering (or LLMs, RAG, etc.) as well.</p><p>Disclaimer: this debugging tactic assumes that you’ve already tried (to no avail) some of the basic prompt engineering hacks like assigning a role to the LLM, enclosing your responses within delimiters, giving the model time to think using techniques like chain-of-thought reasoning. Many of these basic tactics have been documented in OpenAI’s prompt engineering guide along with other excellent prompt engineering guides available online.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=d97a175e4bb5" width="1" height="1" alt=""><hr><p><a href="https://medium.com/inveterate-learner/a-simple-not-easy-technique-for-debugging-llms-using-llms-d97a175e4bb5">A simple (not easy) technique for debugging LLMs using LLMs</a> was originally published in <a href="https://medium.com/inveterate-learner">Inveterate Learner</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[A community of doers: learnings from winning a solo silver medal within 2 weeks in my 2nd Kaggle…]]></title>
            <link>https://medium.com/inveterate-learner/a-community-of-doers-learnings-from-winning-a-solo-silver-medal-within-2-weeks-in-my-2nd-kaggle-35d920e5db?source=rss----ba6eaa0b1544---4</link>
            <guid isPermaLink="false">https://medium.com/p/35d920e5db</guid>
            <category><![CDATA[kaggle]]></category>
            <category><![CDATA[competition]]></category>
            <category><![CDATA[learning]]></category>
            <category><![CDATA[artificial-intelligence]]></category>
            <category><![CDATA[machine-learning]]></category>
            <dc:creator><![CDATA[Aman Dalmia]]></dc:creator>
            <pubDate>Fri, 21 Aug 2020 23:50:53 GMT</pubDate>
            <atom:updated>2020-08-31T13:08:04.231Z</atom:updated>
            <content:encoded><![CDATA[<h3>A community of doers: learnings from winning a solo silver medal within 2 weeks in my 2nd Kaggle competition</h3><h4>I provide the context for how I got started in the competition, my struggles, journey to the final solution and everything I learned</h4><p>I recently took part in the <a href="https://www.kaggle.com/c/siim-isic-melanoma-classification/leaderboard#score">SIIM-ISIC Melanoma Classification challenge</a> hosted on Kaggle during the last 2 weeks of the competition and was able to secure my first silver🏅on the platform. This was only my 2nd Kaggle competition, and the first one in 4 years.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*sPI0rGQgj7RpFzaUA1ivzQ.png" /></figure><p>The point of mentioning this is merely to indicate what is possible even within such a short time frame. It was a tremendous learning opportunity for me and I regretted not being a part of this earlier. The goal of this post is walk through my journey of beginning the competition in its final phase — my initial struggles, starting off step-by-step and arriving at my final submission — and to share everything that I learned in the process, specifically about the Kaggle community. This is how the blog post is structured:</p><ul><li><a href="#ba80"><strong><em>Participating in the competition</em></strong></a></li><li><a href="#b217"><strong><em>Arriving at the final solution</em></strong></a></li><li><a href="#2586"><strong><em>Some of the things I avoided</em></strong></a></li><li><a href="#122b"><strong><em>Learnings</em></strong></a></li><li><a href="#6b2b"><strong><em>References</em></strong></a></li></ul><p>I hope this blog post can convince you that irrespective of what you might think of yourself, you are always welcomed in the Kaggle community and the best way to start learning is by just diving right in and doing something.</p><h3><strong><em>Participating in the competition</em></strong></h3><p>The main reason that I hadn’t participated in a Kaggle competition seriously before was that I was not sure what I could learn from it that I wouldn’t from my everyday work as an AI researcher and hence, most of my time was spent completely at work. However, over time, I’ve realized that I have not been able to stay updated about the latest practical tips for improving model performance as a majority of my time at work is dedicated towards data, compounded with the data size being relatively small. So, I needed a playground for me to test out my wild ideas and learn about the techniques that worked in practice. This was a major reason for me to explore Kaggle and I found the <a href="https://www.kaggle.com/c/siim-isic-melanoma-classification/leaderboard#score">SIIM-ISIC Melanoma Classification challenge</a> as the perfect starting point as the binary image classification task is simple enough for me to get a feel for the platform and also, have a realistic chance of performing well as I’ve been working on computer vision for many years now.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/834/1*UHyqHeZJ98w1aUqZBbAL5w.png" /><figcaption>Source: <a href="https://www.kaggle.com/c/siim-isic-melanoma-classification/overview">competition website</a></figcaption></figure><h4><strong><em>Initial struggles </em></strong>😔</h4><p>Contrary to what I had expected, I felt extremely overwhelmed seeing the amount of discussions, knowledge sharing (in the form of data and code) that was taking place and the current best leaderboard scores. I wanted to keep track of everything and understand everything in one day so that I could be at the same place as everyone else. I ended up putting a lot of pressure on myself and this made me lose my initial motivation.</p><h4><strong><em>Slowly making progress </em></strong>🤞</h4><p>Thankfully, I realized quickly that it wasn’t possible for me to get a hold of everything and there will be things that I am missing out. I convinced myself to be comfortable with knowing that I won’t be knowing everything there is to know. I started off slowly by creating the right cross-validation data for validating model performance. Creating the right split was crucial for this competition and as I’ll mention later, the cross-validation score was very important in determining the final outcome. Then, I created a baseline model using <a href="https://arxiv.org/abs/1512.03385">ResNet-18</a> with a basic input processing pipeline. This helped me get an AUC of 0.84 on the public LeaderBoard (LB) and allowed me to complete the pipeline of submitting a result.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ECTPrxltV1gEZHZENmzpbw.png" /></figure><p>I usually breathe a sigh of relief once the end-to-end pipeline of anything that I’m working on is complete. This allows me the flexibility to tune individual components and be sure that there are no unknown unknowns down the road that would need my attention. So, I was happy after doing this and going forward, I kept adding new components to it one at a time and I’ll describe what finally landed me in the top 5% out of 3000+ competitors.</p><p>Before describing the final solution, I want to share three philosophies that helped me iterate faster:</p><ul><li>The first one is an advice from Jeremy Howard from fast.ai that practically, you often don’t need all of the data or even the entire input to arrive at a decent performance. This could mean using a fraction of the entire dataset and using images of smaller resolution (say, 224 x 224) instead of using the entire image, which could be 1024 x 1024 and take a lot of time to load and process.</li><li>Another philosophy is something that can be considered widely known to truly matter for improving model performance but I’ll still state it explicitly — feed the data correctly, more data helps, use the correct data augmentations, find the right optimization recipe and identify the right model class. Just focusing on these things should land you a pretty decent performance. It’s all about finding the right mix now. Once I found the right recipe on images with a smaller resolution, I used the same recipe with a larger image resolution. That is expected to improve performance.</li><li>Ensembling generally always helps. Model ensembling has a theoretical justification for model improvement with the current set of base models. <a href="http://mlwave.com/kaggle-ensembling-guide/">This</a> blog post is an excellent reference. Simple techniques like combining diverse models (models with low correlation in their predictions) and combining the same model trained on different input sizes can provide a significant lift.</li></ul><h3><strong><em>Arriving at the final solution </em></strong>🗻</h3><p>Once I had a solid base, I played around with different aspects of the entire pipeline which I listed towards the end of the last section— model, optimization, image sizes, using external data (data that is not a part of the competition), data augmentation and handling data imbalance.</p><p>My best model was an ensemble (taking the mean of the predictions of the individual models) of 4 models.</p><h4>Image sizes</h4><p>3 models were trained on 512x512 images and 1 model on 384x384.</p><h4>Augmentations</h4><p>2 models use the following augmentations (using <a href="https://kornia.readthedocs.io/">kornia</a>):</p><pre>- name: Rescale<br>  params:<br>      value: 255.<br>- name: RandomAffine<br>  params:<br>      degrees: 180<br>      translate:<br>        - 0.02<br>        - 0.02<br>- name: RandomHorizontalFlip<br>  params:<br>      p: 0.5<br>- name: ColorJitter<br>  params:<br>      saturation:<br>        - 0.7<br>        - 1.3<br>      contrast:<br>        - 0.8<br>        - 1.2<br>      brightness: 0.1<br>- name: Normalize<br>  params:<br>      mean: imagenet<br>      std: imagenet</pre><p>The meaning of different parameters can be found from kornia&#39;s <a href="https://github.com/kornia/kornia/blob/master/kornia/augmentation/augmentation.py">documentation</a>. The other 2 models additionally use <a href="https://arxiv.org/abs/1708.04552">Cutout</a>:</p><pre>- name: RandomErasing<br>  params:<br>      p: 0.5<br>      ratio:<br>        - 0.3<br>        - 3.3<br>      scale:<br>        - 0.02<br>        - 0.1</pre><h4>Data Sampling</h4><p>To iterate faster and handle data imbalance, instead of upsampling the minority class, I downsample the majority class per epoch. However, to avoid wasting data, I sample different instances from the majority class per epoch.</p><h4>Network</h4><p>The same network architecture is used for all the 4 models — EfficientNet-B5 features followed by a Linear layer. I tried a vast range of models but EfficientNet-B5 was the best single model.</p><h4>Optimization — SuperConvergence</h4><p>One of the decisions I made for iterating faster was to restrict the number of epochs to 20. To achieve this, I used the <a href="https://www.fast.ai/2018/07/02/adam-weight-decay/">OneCycle</a> learning rate scheduler introduced in <a href="https://arxiv.org/abs/1708.07120">this</a> paper. This scheduler requires one to specify the minimum and maximum learning rates. These two were found to be 5e-6 and 2e-4 respectively, using the <a href="https://forums.fast.ai/t/intuition-to-lr-range-test-cyclical-lr-and-the-one-cycle-policy/65013">LR-range-test</a>. Also, to address overfitting, I apply a weight decay of 0.1. <a href="https://arxiv.org/abs/1412.6980">Adam</a> usually obtains the best results in a very quick time. However, <a href="https://arxiv.org/abs/1711.05101">this</a> paper clarifies how weight decay is not applied correctly in Adam, and instead, proposes a modification to Adam — AdamW. That is the final optimizer that I have used.</p><h4>Test Time Augmentation (TTA)</h4><p>TTA was introduced in fast.ai to improve model performance during inference. Contrary to the general wisdom of turning data augmentation off during inference, TTA refers to keeping it on during inference as well. Since there is randomness associated with augmentations, trusting on running inference only once can lead to wrong conclusions and might even give a worse performance. Hence, in TTA, we run inference for N_TTA number of times. Finally, to obtain the prediction for each instance, we combine the predictions across the N_TTA inference runs. One simple way of combining is by taking the mean of the predictions. For this competition, I used N_TTA = 15. Note that this is computationally very expensive but it leads to clear performance improvement for this task.</p><h4><strong><em>Things I wanted to try but couldn’t</em></strong></h4><p>That’s it. These components helped me land in the top 5% of the competition in just 2 weeks. If they seem too simple to you, then you are right! :)</p><p>However, there were still many ideas that I wanted to try but I couldn’t, given the time shortage. I’m also listing them down in case there is something to learn from them:</p><ul><li><strong>Train on images of different sizes better</strong>: I would like to diligently keep track of the best experiments on images of lower resolution and re-run ALL of them for images with higher resolution followed by ensembling all of them. I didn’t stay consistent with this framework.</li><li><strong>Combine metadata with images: </strong>The competition also provides a lot of metadata for each image that could be used to improve performance. The winning team used the metadata by stacking it with the features extracted from the CNN before feeding it to the classifier.</li><li><strong>Spend time improving my ensembles: </strong>As I mention in the learnings section, ensembling was key and I, unfortunately, didn’t spend time learning about the best practices here and just stuck to averaging the predictions of my base models. More on this later.</li><li><strong>Trying more augmentations: </strong>There were a variety of augmentations discussed throughout the competition along with augmentations specific to the type of data in the augmentation (like adding hair randomly to images because a lot of images contained hairs).</li><li><strong>Custom head: </strong>My network consisted of a single linear layer after the features extracted from the convolutional network. However, it is often better to add more than one linear layer.</li></ul><h3>Some of the things I avoided</h3><p>There were many overly complicated things mentioned in the discussions like generating images from the data and using that as additional training data. These might be good ideas but I tend to like simplistic solutions and I wanted to achieve the best possible results using them. I still feel that I could get a higher score simply by using a better ensembling technique.</p><h3><strong><em>Learnings</em></strong></h3><h4><strong><em>1 - the power of ensembling</em></strong></h4><p>Ensembling is the technique of combining the predictions of several independent models/learners. I won’t go into technical details here as there are many excellent articles that already do that (<a href="http://mlwave.com/kaggle-ensembling-guide/">this</a> one for example). I noticed people reporting a cross-validation (CV) score much higher than what I was getting with a similar setup. It was only much later that I realized that the best CV score for a single model was still very close to what I was getting. The winners used advanced ensembling techniques like stacking, ranking (this one is specific to the metric being optimized here) and model blending to improve their final performance dramatically. One of the top submissions was actually just a weighted average of 20 public submissions. Thus, one should focus on getting the right ensembling recipe.</p><h4>2 - trust your CV</h4><p>One of the dramatic moments of the competition was when the private leaderboard results were opened. There was a massive shake-up in the entire leaderboard with many top submissions dropping significantly low and many teams jumping up more than 1000 spots (I myself climbed around 800 spots). This left many people reasonably disappointed as they had overfitted to the public leaderboard. However, a lot of the solution overviews posted after the competition ended strongly emphasized the need to focus on the CV score as the public leaderboard can often lie but they found a strong correlation between their CV scores and the private leaderboard ranking. So, the mantra became: “In CV, we trust”. Because I found this out very late, contrary to the general method of reporting cross-validation performance by taking the mean and standard deviation across all the folds, there is a better way that is typically used to report CV score in Kaggle competitions. <a href="https://www.kaggle.com/arthurtok/introduction-to-ensembling-stacking-in-python#Generating-our-Base-First-Level-Models">This</a> notebook illustrates that very nicely. Essentially, for each fold, you should save your Out-Of-Fold (OOF) predictions (predictions for the instances forming the validation set in that particular fold) for each fold. At the end of 5 folds, you will have a list of predictions for each sample in the train set and you should compute the metric on this list of predictions to get your final CV score.</p><h4>3 - code sharing through kernels</h4><p>Many people shared their submission notebooks publicly which truly helped clarify several doubts that often stay, even after people have tried their best (or not) to explain their methodology. It also helps to learn about minor implementation details that often get left out while talking about the big picture. Additionally, reading other people’s code is a great way of improving your own coding skills. I personally learned quite a bit as well. Finally, Kaggle Kernels offer both GPU and TPU for a limited quota. This is awesome and it removes the need to depend on on-prem infra or the requirement of being able to spend a lot of money on cloud VMs.</p><h4>4 - discussions and knowledge sharing 💡</h4><p>I was truly surprised to see how willing people were to engage with each other, often sharing their code and data to provide a very good starting point for other people. People also shared their approaches while the competition was still ongoing while also discussing what worked for them and what didn’t. Considering the fact that this is a competition with a monetary prize associated with it, I was truly taken aback by how collaborative the nature of discussions was and how kind everyone was to any newcomer asking silly questions as well.</p><h4>5 - community of doers 👨‍💻👩‍💻</h4><p>Finally, I just want to say that it was amazing to have found a community of doers — people who focus on actually getting the job done, with whom I could have deep, meaningful technical discussions (and jokes). I have struggled to find the right online community for myself and although I am yet to find my footing there, I definitely know that I am here to stay! :)</p><h3>References</h3><p>I’ll keep adding more to this list.</p><h4>General resources</h4><ul><li><a href="https://www.kaggle.com/c/siim-isic-melanoma-classification/discussion/175455">Collections of solutions from the competition</a></li><li><a href="https://blog.floydhub.com/ten-techniques-from-fast-ai/">Ten Techniques Learned From fast.ai</a></li><li><a href="https://arxiv.org/abs/1910.02190">Kornia: an Open Source Differentiable Computer Vision Library for PyTorch</a></li></ul><h4>Cross-validation</h4><ul><li><a href="https://www.kaggle.com/c/siim-isic-melanoma-classification/discussion/175614">How To CV and How To Ensemble OOF Files</a></li><li><a href="https://www.kaggle.com/arthurtok/introduction-to-ensembling-stacking-in-python#Generating-our-Base-First-Level-Models">Computing CV score correctly and example of stacking</a></li></ul><h4>Optimization</h4><ul><li><a href="https://forums.fast.ai/t/intuition-to-lr-range-test-cyclical-lr-and-the-one-cycle-policy/65013">Intuition to LR Range Test, Cyclical LR and the One-Cycle Policy</a></li><li><a href="https://arxiv.org/abs/1803.09820">A disciplined approach to neural network hyper-parameters: Part 1 — learning rate, batch size, momentum, and weight decay</a></li><li><a href="https://arxiv.org/abs/1708.07120">Super-Convergence: Very Fast Training of Neural Networks Using Large Learning Rates</a></li><li><a href="https://arxiv.org/abs/1711.05101">AdamW — Decoupled Weight Decay Regularization</a></li></ul><h4>Ensembling</h4><ul><li><a href="https://mlwave.com/kaggle-ensembling-guide/">Kaggle ensembling guide</a></li><li><a href="https://www.kaggle.com/c/siim-isic-melanoma-classification/discussion/165653">Several model averaging techniques</a></li><li><a href="https://www.kaggle.com/niteshx2/improve-blending-using-rankdata">Improve blending using Rankdata</a></li></ul><p>I hope this blog post was able to serve as a good starting point for anyone looking to jump into Kaggle. I have tried to cover all the topics that I felt was completely new to me and I had to dig through the discussions to understand them. In the near future, I plan to release my experimentation framework along with the code for this competition to foster reproducibility and help others build on top of my work — built with ❤️ using <a href="https://medium.com/u/ee766b3488b5">PyTorch</a>.</p><p><em>If there’s anything that you might want to share with me or give me any feedback on my writing/thoughts, I would love to hear it from you. Feel free to connect with me on </em><a href="https://twitter.com/dalmiaman"><em>Twitter</em></a><em>, </em><a href="https://www.linkedin.com/in/aman-dalmia"><em>LinkedIn</em></a><em> or follow me on </em><a href="http://github.com/dalmia"><em>Github</em></a><em>. To stay updated with my posts, do </em><a href="https://medium.com/@amandalmia18/"><em>follow</em></a><em> me on Medium.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=35d920e5db" width="1" height="1" alt=""><hr><p><a href="https://medium.com/inveterate-learner/a-community-of-doers-learnings-from-winning-a-solo-silver-medal-within-2-weeks-in-my-2nd-kaggle-35d920e5db">A community of doers: learnings from winning a solo silver medal within 2 weeks in my 2nd Kaggle…</a> was originally published in <a href="https://medium.com/inveterate-learner">Inveterate Learner</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Compression in the AI world: MobileNets, Pruning & Quantisation]]></title>
            <link>https://medium.com/inveterate-learner/compression-in-the-ai-world-mobilenets-pruning-quantisation-ca6bf1bce265?source=rss----ba6eaa0b1544---4</link>
            <guid isPermaLink="false">https://medium.com/p/ca6bf1bce265</guid>
            <category><![CDATA[machine-learning]]></category>
            <category><![CDATA[model-compression]]></category>
            <category><![CDATA[pytorch]]></category>
            <category><![CDATA[deployment]]></category>
            <category><![CDATA[artificial-intelligence]]></category>
            <dc:creator><![CDATA[Aman Dalmia]]></dc:creator>
            <pubDate>Sun, 14 Jul 2019 05:46:38 GMT</pubDate>
            <atom:updated>2019-07-14T06:27:47.298Z</atom:updated>
            <content:encoded><![CDATA[<h4>Learn how you can compress a 500 MB large deep learning model to just 5 MB with almost no drop in accuracy.</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*w6iVNpdTSJSfze7vLV2kdQ.png" /><figcaption>Source: <a href="https://www.blog.google/technology/ai/ai-takes-root-helping-farmers-identity-diseased-plants/">https://www.blog.google/technology/ai/ai-takes-root-helping-farmers-identity-diseased-plants/</a></figcaption></figure><p>Over the past couple of years, the state-of-the-art AI algorithms have started moving out from research labs to out in the real world. This has significant implications as the advancements that have been happening in the AI community, now has the potential to reach billions of people across the globe. However, once you decide to deploy an AI model, there are a ton of things that need to be decided, one of them being the nature of the deployment.</p><p>There are broadly two ways in which one can deploy an AI model:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*mDV1bQBPN3YjaBR6FP-qJw.png" /></figure><p>While it is easier to deploy your AI model on the server, it has several shortcomings. One of the major ones is the variability of network connection when the model is used on a large scale. Even though the internet seems ubiquitous today, there are still large parts of the world where internet connectivity is intermittent, if not absent. And if your target audience happens to reside in those geographies, you need to consider on-device inference seriously. Some of the other factors that make a case for on-device inference are privacy on the client side and server cost, to name a few.</p><p>Now that we understand the need for on-device inference, there are a few significant roadblocks to consider. Firstly, the average <strong><em>size</em></strong> of deep learning models is hundreds of MB; for example, VGGNet is &gt; 500 MB. One cannot deploy such a large model directly on the phone. Second is the <strong><em>inference time</em></strong>. Having a cloud-based model has the benefit that the inference can be done using a GPU, and hence, the inference time can be minimal. That is not the case when you have to run your model on a phone, which has much lower compute power. Finally, one also needs to consider <strong><em>energy efficiency</em></strong> — running your model shouldn’t drain out the battery of the phone completely.</p><p>There is an ongoing body of work in the AI research community (including both academia and industry) in the direction of <strong>Model Compression </strong>— which aims to tackle either all or some of the roadblocks discussed above. In this blog post, I’ll discuss some of the techniques which are commonly used to compress an AI model along with reducing the inference time, while trying to improve energy efficiency. As a guide along this journey, we’ll keep the following metrics in mind while discussing any new technique:</p><ol><li>Model accuracy drop/rise (rise? yes!)</li><li>Model size</li><li>Inference time</li><li>Energy efficiency</li></ol><p>Within model compression itself, there are two broad categories of techniques. One class of compression techniques focus on reducing the model size once the model has been trained. They are referred to as <strong>post-training</strong> techniques. <strong>Pruning</strong> and <strong>Quantisation </strong>are two techniques<strong> </strong>which<strong> </strong>belong to this class. The second category, on the other hand, trains a smaller model, to begin with, to match the accuracy of a larger model for the same task. MobileNets (<a href="https://arxiv.org/abs/1704.04861">v1</a> and <a href="https://arxiv.org/abs/1801.04381">v2</a>) are an example of this category of techniques.</p><h3>MobileNets</h3><p>We will first discuss the category of techniques which design a smaller and efficient model, to begin with, and train it from scratch. The most widely known work in this class of compression techniques is referred to as MobileNets, which is essentially a toolkit of layers and tricks that make a deep learning model more efficient in terms of runtime while reducing the number of parameters as well. <a href="https://arxiv.org/abs/1704.04861">MobileNetv1</a> discussed the idea of Depthwise Separable Convolution (DS convolution), which is a parameter-efficient way to achieve the output that standard 2D convolution does. It also proposes two hyperparameters — width and resolution multiplier — that can be used to tradeoff between latency and accuracy. I’ll take a stab at explaining the difference between a DS convolution and a regular convolution.</p><p>A regular convolution operation takes place as shown below:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/701/1*DI0Y3OKXnVz0m1pYVnlrgQ.png" /><figcaption>Filters for a standard convolution</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/360/1*9KgvcSgTekoI-6CfKUAf4Q.gif" /><figcaption>Notice how the operation maintains the feature map spatial dimension due to the 1x1 convolution.</figcaption></figure><p>Here, the size of the input feature map is I x I x M , the kernel (also referred to as filter throughout the post) size is K x K and the desired output feature map is of size O x O x N . The figure highlights the computation of one cell of one of the channels of the output feature map. To compute one channel of the output feature map requires K x K x M x I x I multiplications and additions (referred to as MultAdds from now). For an N-channel output feature map, the total number of MultAdds is, therefore, K x K x M x I x I x N .</p><p>A standard convolution combines both the filtering step (via the kernel) and the combining of input features (as each filter has a shape of K x K x M as shown in the figure above). DS convolution factorises these two operations in two separate steps — depthwise convolution and pointwise convolution — to reduce the total number of parameters as well as the number of MultAdds.</p><p>The depthwise convolution step performs only the filtering operation and doesn’t combine the input features. The size of the filters and the depthwise convolution is visually shown below:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/642/1*_LBgr4vDR0T02_tdhBbW5A.png" /><figcaption>Filters for the depthwise convolution</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/360/1*zKLd7NRjqNqxxr_usVDYUg.gif" /><figcaption>Notice how the output feature map size if M and not N (which is the case for the usual convolution).</figcaption></figure><p>The Depthwise convolution step is extremely efficient compared to regular convolution as the number of MultAdds involved is only K x K x M x I x I .</p><p>The pointwise convolution step uses a 1x1 convolution to combine the output of the depthwise convolution to generate the feature map of the desired number of output channels. The number of MultAdds in a pointwise convolution is M x N x O x O . Thus, the total number of MultAdds in a Depthwise Separable convolution is: K x K x M x I x I + M x N x I x I (I’ve replaced O x O by I x I in the calculation of the number of MultAdds for pointwise convolution just so that the comparison with a regular convolution is easy and asymptotically, it won’t matter).</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/690/1*qT3NF17mPjBEZPuE1dN-XQ.png" /><figcaption>Filters for the pointwise convolution</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/360/1*AxHjAjUvr30Y0JXFjnJPyw.gif" /><figcaption>Notice how the feature map spatial dimension is maintained due to the 1x1 convolution.</figcaption></figure><p>Thus, there is a reduction in the number of MultAdds by a factor of 1/K² (using K x K x M x I x I + M x N x I x I / K x K x M x I x I x N for the calculation and ignoring the 1/N term as N is usually large). Using a kernel size (K) of 3 gives a reduction by approximately 8–9 times.</p><p>The paper also introduced two hyperparameters for tweaking the network architecture to tradeoff between latency and accuracy: <br>i) <strong>Width multiplier (α)</strong>: The paper refers to the number of channels in each feature map as the width of that feature map. α can be used to make each of the feature maps, and hence, the network, either thinner or thicker. For a DS convolution with the number of input channels M and output channels N, using a width multiplier, α, makes them `αM` and `αN` respectively. Thus, the number of MultAdds becomes: K x K x αM x I x I + αM x αN x I x I . Use α &lt; 1 to reduce the width of the network.<br>ii) <strong>Resolution multiplier (ρ)</strong>: This is used to reduce the resolution of each of the feature maps in the network. Together with α, the number of MultAdds becomes K x K x αM x ρI x ρI + αM x αN x ρI x ρI . This is effectively implemented by reducing the input size.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*siqYqE4xBfyjtP6UeB7Nog.png" /><figcaption>Results of MobileNetv1. The red circle shows the comparison between using a regular convolution vs DS convolution in the MobileNetv1 architecture. As can be seen, there is a large drop in the number of parameters and MultAdds with just a 1% drop in accuracy. Similarly, the other tables indicate how using various hyperparameters affect the relevant metrics.</figcaption></figure><h3>Pruning</h3><p>Now, we shift over to the <strong>post-training </strong>class of techniques. The first among them is pruning. The broad idea is shown below. You start with the trained model and essentially “cut” or remove some connections such that they don’t have a major effect on the final accuracy. The resulting model is the pruned model which has fewer parameters.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*CMgwNR2aBDByBSSH" /><figcaption>Source: <a href="https://medium.com/tensorflow/tensorflow-model-optimization-toolkit-pruning-api-42cac9157a6a">https://medium.com/tensorflow/tensorflow-model-optimization-toolkit-pruning-api-42cac9157a6a</a></figcaption></figure><p>There are a few design choices involved here. One important decision is the criteria based on which certain filters are removed while others are retained. Another crucial factor is the level at which pruning is done. To understand this, consider the figure below.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/600/0*FvL5JpixWvfux2WU.jpg" /><figcaption>Source: <a href="http://cs231n.stanford.edu/slides/2017/cs231n_2017_lecture15.pdf">http://cs231n.stanford.edu/slides/2017/cs231n_2017_lecture15.pdf</a></figcaption></figure><p>The figure shows two levels of pruning — one at the level of individual connections between neurons and other at the level of nodes, where individual nodes are removed (and thus, any connection to/from that node).</p><p>This design choice is especially relevant for Convolutional Neural Networks, where the connections are non-trivial and instead of removing individual weights within each of the filters, most techniques perform a filter-level pruning, i.e. they either reject or retain an entire filter (which has a shape of K x K x M , where the terms refer to their meanings as used in the section above). This is understood better using the image below:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*VUFGwgFlG1m7OajX3v-b5Q.png" /><figcaption>After pruning, the filter represented by the dashed line indicates that that filter has been removed. Source: <a href="http://machinethink.net/blog/compressing-deep-neural-nets/">http://machinethink.net/blog/compressing-deep-neural-nets/</a></figcaption></figure><p>Most pruning algorithms actually work in an iterative manner. This means that they prune a few weights, retrain the pruned model to recover from the drop in accuracy as a result of the pruning operation, prune again, and so on. This is done until a threshold on the accuracy drop is reached beyond which the model cannot be pruned further.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*vCL5k6-r2hGs9_B_593VGg.png" /><figcaption>Source: <a href="http://cs231n.stanford.edu/slides/2017/cs231n_2017_lecture15.pdf">http://cs231n.stanford.edu/slides/2017/cs231n_2017_lecture15.pdf</a></figcaption></figure><p>As shown above, it is possible to achieve almost no drop in accuracy by pruning almost 95% of the parameters. More details can be found in the original paper <a href="https://arxiv.org/abs/1510.00149">here</a>.</p><h3>Quantisation</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/833/1*2clgI6r56PPLT3PV_0-Ssg.png" /></figure><p>All the weights don’t need to be stored in full-precision, and maybe, even, shouldn’t be stored in full precision. As a crude example, 1.98, 2.11, 2.03 can all be represented simply by 2. The reason why this <em>could</em> be even better than the original model is that it <em>could</em> provide some level of regularization. However, naive approximation might not be the best idea. <a href="http://machinethink.net/blog/compressing-deep-neural-nets/">This</a> paper introduced the idea of trained quantisation, where you can not only perform quantisation in a better way but even train your quantised model further. Also, as shown in the image above, energy efficiency becomes almost thrice when using 16-bit float vs 32-bit float.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/983/1*k2iVa1ilRFRIuwVdCGu6_Q.png" /></figure><p>The broad idea of trained quantization is to cluster the weight values using K-means clustering where the number of clusters is decided based on the number of bits desired, create a codebook for each weight value, use the codebook to perform a forward pass and get the gradients and update the centroid values of each cluster using the gradient updates. This last step is explained in a bit more detail later.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/859/1*VC1wz-68ZeQeHzor_3mhew.png" /></figure><p>So, we start with clustering the trained weights and replacing their values with the value of the centroid of the cluster they belong to.</p><p>Then, a forward pass is made using the centroid-replaced weight values, and the gradients are calculated accordingly (since each cell goes through a different forward pass, the cells belonging to the same cluster may end up having different gradient values). Since we know which cell indices belong to the same cluster, we group the gradient values based on the cluster the cell indices belong to, and sum over the gradients to receive the gradient value for a cluster. Finally, we perform the usual gradient descent update step on the older centroid values using the gradient value obtained above.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*cPjdJFPB-sRmCejemWVE4w.png" /><figcaption>Source: <a href="http://cs231n.stanford.edu/slides/2017/cs231n_2017_lecture15.pdf">http://cs231n.stanford.edu/slides/2017/cs231n_2017_lecture15.pdf</a></figcaption></figure><p>Now, one needs to store only the cluster indices and centroid values. Suppose that 16 clusters are chosen, the weight matrix can be represented using only 4-bits, which is an 8X reduction in model size (asymptotically). Combining this with Huffman coding to represent the bits efficiently, the final model size can be reduced dramatically with only a small drop in accuracy. The combination of Pruning + Quantization + Huffman coding was proposed in the Deep Compression <a href="https://arxiv.org/abs/1510.00149">paper</a> which has been referenced throughout this post.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*IcIpBUwbWxqlgQpbIswMsw.png" /><figcaption>Deep Compression results</figcaption></figure><h4>Resources:</h4><ul><li>CS 231N Guest Lecture: Efficient Methods and Hardware for Deep Learning (<a href="http://cs231n.stanford.edu/slides/2017/cs231n_2017_lecture15.pdf">slides</a>) (<a href="https://www.youtube.com/watch?v=eZdOkDtYMoo">video</a>)</li><li>Awesome model compression (<a href="https://github.com/memoiry/Awesome-model-compression-and-acceleration">Github</a>)</li><li>Official PyTorch <a href="https://pytorch.org/docs/stable/torchvision/models.html">implementation</a> for MobileNetv2</li><li>PyTorch <a href="https://github.com/ShuangXieIrene/ssds.pytorch/tree/master/lib/modeling/nets">implementation</a> of MobileNetv1 compatible for Object Detection</li><li>PyTorch implementation of Pruning (<a href="https://github.com/jacobgil/pytorch-pruning">Github</a>)</li><li>PyTorch implementation of Deep Compression (<a href="https://github.com/mightydeveloper/Deep-Compression-PyTorch">Github</a>)</li></ul><p>This post was a very gentle introduction to the world of model compression. There is a ton of work out there that has not been covered, and this is an active area of research in the AI community — with a major push from industry. I intend to write another blog post covering a few more techniques, especially Intrinsic Dimension (from Uber Research) and MobileNetv2 in their gory details. I hope this was a fun read for you and served as a starting point for you to now understand the concepts discussed above in more details as well as become comfortable with the terminologies generally used in this field.</p><blockquote>When I was in college, I wanted to be involved in things that would change the world. Now I am.<br>- Elon Musk</blockquote><p><em>If there’s anything that you might want to share with me or give me any feedback on my writing/thoughts, I would love to hear it from you. Feel free to connect with me on </em><a href="https://www.linkedin.com/in/aman-dalmia"><em>LinkedIn</em></a><em>, or follow me on </em><a href="http://github.com/dalmia"><em>Github</em></a><em>. To stay updated with my posts, do </em><a href="https://medium.com/@amandalmia18/"><em>follow</em></a><em> me on Medium. You can follow our publication on Medium </em><a href="https://medium.com/inveterate-learner"><em>here</em></a><em>.</em></p><h3>Don’t forget to give us your 👏 and follow us!</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/780/0*UCimvthX21z9ko5Y" /></figure><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=ca6bf1bce265" width="1" height="1" alt=""><hr><p><a href="https://medium.com/inveterate-learner/compression-in-the-ai-world-mobilenets-pruning-quantisation-ca6bf1bce265">Compression in the AI world: MobileNets, Pruning &amp; Quantisation</a> was originally published in <a href="https://medium.com/inveterate-learner">Inveterate Learner</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Real-time object detection part 1: Understanding SSD]]></title>
            <link>https://medium.com/inveterate-learner/real-time-object-detection-part-1-understanding-ssd-65797a5e675b?source=rss----ba6eaa0b1544---4</link>
            <guid isPermaLink="false">https://medium.com/p/65797a5e675b</guid>
            <category><![CDATA[artificial-intelligence]]></category>
            <category><![CDATA[computer-vision]]></category>
            <category><![CDATA[deep-learning]]></category>
            <category><![CDATA[object-detection]]></category>
            <category><![CDATA[machine-learning]]></category>
            <dc:creator><![CDATA[Aman Dalmia]]></dc:creator>
            <pubDate>Wed, 01 May 2019 07:17:41 GMT</pubDate>
            <atom:updated>2019-07-06T18:05:16.110Z</atom:updated>
            <content:encoded><![CDATA[<h3>Real-time object detection: Understanding SSD</h3><h4>This post explains the working of the Single-Shot MultiBox Detector along with a code walkthrough</h4><p>Object detection refers to the task of identifying various objects within an image and drawing a bounding box around each of them. A few examples are shown below to illustrate this better:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*pIIctp6MbiKAQ_xmLAAvew.png" /><figcaption>Source: <a href="https://arxiv.org/pdf/1512.02325.pdf">https://arxiv.org/pdf/1512.02325.pdf</a></figcaption></figure><p>A lot of research has happened in this domain and the most commonly heard object detection algorithm is <a href="https://pjreddie.com/darknet/yolo/">You Only Look Once</a> (YOLO), which was the first effort towards obtaining a real-time detector and ever since it was introduced, it has undergone several updates. A major problem with the first version of YOLO was that its accuracy was very low compared to the state-of-the-art detectors of that time, all of whom operated in two stages: the first stage generated a list of proposals or guesses for where the objects could be within the image and the second stage classified each of the proposed boxes. For more details on how two-stage detectors work, follow <a href="https://medium.com/@smallfishbigsea/faster-r-cnn-explained-864d4fb7e3f8"><em>this</em></a> blog post. YOLO belongs to the category of one-stage detectors which remove the proposal generation step and predict the class scores along with the bounding box coordinates directly from the image in an end-to-end framework. Single-Shot Multibox Detector (<a href="https://arxiv.org/pdf/1512.02325.pdf">SSD</a>) was the first one-stage detector to achieve an accuracy reasonably close to the two-stage detectors while still retaining the ability to work in real-time. There have been a lot of efforts towards making one-stage detectors surpass the accuracy of two-stage detectors by tackling several issues with SSD and adding an additional stage of refinement in the one-stage pipeline, but most of them use SSD as the starting point. In his post, I’ll explain each and every component of SSD in detail. Throughout the post, I’ll refer to <a href="https://github.com/amdegroot/ssd.pytorch"><em>this</em></a> excellent implementation of SSD in PyTorch to map the concepts with the corresponding code samples.</p><h4>1. Understanding Default Boxes</h4><p>The key idea underlying SSD is the concept of default boxes (or anchors). Don’t worry if you have a lot of questions by the end of this section. This section is just meant to give you a high-level picture and a flavour for the things to come.</p><p>Default boxes represent carefully selected bounding boxes based on their sizes, aspect ratios and positions across the image. SSD contains 8732 default boxes. The goal of the model is to decide which of the default boxes to use for a given image and then predict offsets from the chosen default boxes to obtain the final prediction. If this sounded like a lot of jargon, stay with me. The following example and the subsequent sections should clear this further. But you need to keep coming back to this point and make sure you are very clear about it. The image below contains objects of two different scales and aspect ratios. We know that as we keep adding convolutional layers, the resolution of the feature map keeps reducing and hence, the receptive field of each cell of the feature map keeps increasing. Thus, earlier layers, having a smaller receptive field are better suited to detect smaller objects whereas later layers, having larger receptive field, can detect larger objects better.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*lx6esyhycGsz2X4J1Dn0jg.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*igydPZnl4h0LQZsK45WCmQ.png" /><figcaption>Left: Feature map of resolution 8x8 contains default boxes that match the bounding box corresponding to the cat. Right: Feature map of size 4x4, having larger receptive field, is a better match for the larger bounding box corresponding to the dog.</figcaption></figure><p>In the image above, the green (positive) boxes are the default boxes that match at least one ground truth (cat, in case of the left one, and dog, in the right one) whereas the black (negative) default boxes are those that didn’t get matched to any ground truth. Matching here means assigning a label to a default box, positive or negative. I’ll talk about this in more detail later, but the essence here is that certain default boxes are matched to certain bounding boxes in the ground truth while the rest are considered negative. From a high-level, the network is trained to perform two tasks:</p><p>i) Classify which amongst its 8732 default boxes are positive;</p><p>ii) Predict offsets from the positive default box coordinates to obtain the final predicted bounding boxes.</p><h4>2. Architecture</h4><p>The architecture of SSD consists of 3 main components:</p><p>i) Base network</p><p>ii) Extra feature layers</p><p>iii) Prediction layers</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*me-94cTQxMw18shcUwtHzA.png" /><figcaption>Source: <a href="https://arxiv.org/pdf/1512.02325.pdf">https://arxiv.org/pdf/1512.02325.pdf</a></figcaption></figure><p>The base network is essentially the initial layers of any standard image classification network, pre-trained on the ImageNet dataset. The authors use VGG-16. The fully connected layers at the end are implemented as convolutional layers. The final output of the base network is a feature map of size 19 x 19 x 1024.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/72b924db2658b910f0e28c7b2acd901f/href">https://medium.com/media/72b924db2658b910f0e28c7b2acd901f/href</a></iframe><p>On top of the base network, 4 additional convolutional layers are added such that the size of the feature maps keep reducing until a final feature map of size 1 x 1 x 256 is obtained.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/44479382ab5ca79050e3ccf0d51a79b1/href">https://medium.com/media/44479382ab5ca79050e3ccf0d51a79b1/href</a></iframe><p>The prediction layers are a crucial component of SSD. Instead of just using one feature map for predicting the classification scores and bounding box coordinates, several feature maps, representing multiple scales are used. This is where the idea of default boxes and feature map resolutions, discussed above, is used. Specifically, the layers conv4_3, conv7, conv8_2, conv9_2, conv10_2 and conv11_2(shown in the figure) are used for the bounding box predictions.</p><figure><img alt="" src="https://cdn-images-1.medium.com/proxy/1*sZUWR2XgCAJ6AXM5NXYjNg.png" /><figcaption>Source: <a href="https://medium.com/@jonathan_hui/ssd-object-detection-single-shot-multibox-detector-for-real-time-processing-9bd8deac0e06">https://medium.com/@jonathan_hui/ssd-object-detection-single-shot-multibox-detector-for-real-time-processing-9bd8deac0e06</a></figcaption></figure><p>As shown in the image earlier, there are default boxes associated with each cell of a feature map and the number of such boxes — either 4 or 6 — is decided beforehand. Considering the number of classes (including the background class as class 0) to be <em>C</em>, each prediction is represented by (<em>C</em> + 4) numbers: <em>C</em> classification scores and 4 offsets: ∆<em>c</em>x, ∆<em>c</em>y, <em>w</em> and <em>h, </em>representing the offsets from the center of the default box and its dimensions. Thus, for a feature map with <em>k</em> default boxes per cell, the prediction layer is a 3 x 3 convolutional layer with <em>k</em> * (<em>C</em> + 4) channels.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/a738196427bf979dbed80ac6ee4bbd5d/href">https://medium.com/media/a738196427bf979dbed80ac6ee4bbd5d/href</a></iframe><h4>3. Forward pass</h4><p>In this section, I’ll describe how the complete forward pass looks like. Before we move to the code, one important detail to specify is that it has been <a href="https://arxiv.org/pdf/1506.04579.pdf"><em>shown</em></a> that the feature map corresponding to conv4_3 layer of VGG has a very different scale compared to the later layers.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*YeX1YP7qgApKpUPk" /></figure><p>So, the features from that specific layer are normalized and set to an initial scale value of 20. The actual scale is then learned during back-propagation via the weight parameter. The code for the L2Norm layer is shown below:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/498e0c0415cc36ba830144094c887e94/href">https://medium.com/media/498e0c0415cc36ba830144094c887e94/href</a></iframe><p>Finally, the forward pass through the network is shown below. sources contains the various feature maps that contribute to the final prediction.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/fdf563e0fb9719e17b55dab85f0014c0/href">https://medium.com/media/fdf563e0fb9719e17b55dab85f0014c0/href</a></iframe><h4>4. Choosing default boxes</h4><p>As SSD relies heavily on default boxes, it is very sensitive to the choice of the default boxes, specifically their scale and aspect ratios. In the paper, the authors design the default boxes such that each feature map corresponds to a specific scale of default boxes along with a list of aspect ratios for each scale. The minimum and maximum scales, s_min and s_max, are set to 0.2 and 0.9. For the <em>k</em>th feature map (among <em>m</em> feature maps), the scale is chosen as:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*5ohPvSC6LrsPHCziPmvqzw.png" /></figure><p>For a feature map corresponding to a specific scale and having 6 default boxes associated with it, the heights and widths of the default boxes are obtained as shown below:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*TInMBNs0apuABwj5Q1NENw.png" /></figure><p>For each feature map, an additional default box of scale s* and aspect ratio 1 is added. Feature maps having only 4 default boxes do not use aspect ratios 3 and 1/3. The center of each default box is set as the center of the cell to which it belongs. The default boxes are defined in code as shown below:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/7d4a8ec4526692907c0f7cdf2a1c4402/href">https://medium.com/media/7d4a8ec4526692907c0f7cdf2a1c4402/href</a></iframe><h4>5. Training</h4><p>The loss function used is the MultiBox loss, which consists of two terms: the confidence loss and the localization loss. The network outputs (<em>C</em> + 4) predictions for each of the 8732 boxes: <em>C</em> class scores and 4 localization offsets.</p><p><strong>Anchor Matching</strong>: To train the network, all the default boxes are matched to the ground truth boxes. First, each ground truth box is matched to the default box having the maximum jaccard overlap. This is done to make sure that each ground truth box has at least one corresponding default box. Then, each default box is matched to any ground truth box having a jaccard overlap &gt; 0.5. This essentially turns the problem into a <em>multi-label</em> problem for each box. The implementation below matches each default box to only the <em>best</em> matching ground truth, but it can be easily modified to incorporate the multi-label criteria.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/dbaa92d8f236b0d68ebdb44ac7bfea99/href">https://medium.com/media/dbaa92d8f236b0d68ebdb44ac7bfea99/href</a></iframe><p><strong>Loss function</strong>: The default boxes that didn’t get matched to any ground truth box are considered negative and contribute only to the confidence loss, whereas all the positively matched boxes add to the confidence loss as well as the localization loss. The confidence loss is essentially the cross-entropy loss while the localization loss is the Smooth L1 loss between the actual offsets of the default boxes to the ground truth boxes and the predicted offsets.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*vtPmCI-lWKwNeEyaprjzSg.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*FZhXFyo0zk3HyesVlRpCSA.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ik_qHXRcuqJF5S6OvlScYg.png" /></figure><p>The final loss is given by a combination of both the losses where α is the relative weighing of the localization loss w.r.t the confidence loss (set to 1 by cross validation) and N is the number of positively matched boxes.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/914/1*2Lg5sjavpIEmq8QmEopNHw.png" /></figure><p><strong>Hard Negative Mining</strong>: Most of the boxes, out of the 8732 default boxes, are negative. Using all the negative boxes directly would lead to a severe class imbalance during training and hence, once the matching is done, only those negative boxes having the highest confidence losses are retained such that the ratio between the positive and negative boxes is at least 1:3.</p><p><strong>Data augmentation</strong>: Not using data augmentation leads to a major drop in performance. The important data augmentation strategies used are:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*gNoyQTozlAyaAPwIvOg36w.png" /><figcaption>Horizontal Flip</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*4901vf-wCZwAq_XfApnONA.png" /><figcaption>Randomly cropping and resizing</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*403qkjJ5alzdRzBrbiVREw.png" /><figcaption>Random expansion</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*uNjBPQj02DhQAPc8dFOkJA.png" /><figcaption>Photometric Distort</figcaption></figure><h4>6. Inference</h4><p>During inference, we now have 8732 boxes for each class (because we output C confidence scores for each box). Most of these boxes are negative and among the positive ones, there would be a lot of overlapping boxes, as shown below:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*O9q_J_x1AS4yc1dBLLuo6g.png" /><figcaption>.Various stages of inference</figcaption></figure><p>Upon receiving an image as input, first, default boxes are generated for all classes together (top right). Then, a confidence threshold of 0.01 is applied per class to obtain positive boxes (bottom right). Finally, Non-Maximal Suppression (NMS) is applied to get rid of overlapping boxes per class and return at most 200 boxes, using an Jaccard Index as the measure of overlap and an overlap threshold of 0.45. The need of NMS and how it’s done can be understood from <a href="https://www.coursera.org/lecture/convolutional-neural-networks/non-max-suppression-dvrjH"><em>this</em></a> video. NMS essentially does the following (per class): sort the boxes based on the confidence scores, pick the box with the largest confidence score, remove all the other predicted boxes with Jaccard overlap &gt; the NMS threshold (0.45 here), repeat the process until all boxes are covered.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/1bf6580ccec4a6e0303da144b2089d80/href">https://medium.com/media/1bf6580ccec4a6e0303da144b2089d80/href</a></iframe><h4>7. Discussion</h4><p>Some general points to keep in mind regarding SSD are:</p><ul><li>Data augmentation is very critical to better performance, especially for small objects.</li><li>The network is very sensitive to default boxes and it is important to choose the default boxes based on the dataset that it is being used on. A good strategy is to use K-means clustering to identify the right default box sizes.</li><li>Using stronger image classification networks as the base network - like Resnet, Inception, Xception - is likely to improve performance.</li><li>SSD does not work well with small objects. One potential reason for this, discussed in <a href="https://arxiv.org/abs/1707.05031"><em>this</em></a> paper, is that the earlier layers which have smaller receptive field and are responsible for small object detection, are too shallow. There is also a structural contradiction where the earlier layers are supposed to learn low-level features to be passed on to the higher layers whereas also learn high-level abstraction for correctly identifying boxes. <a href="https://arxiv.org/abs/1707.05031"><em>This</em></a> paper adds more context to the predictions and shows significantly higher performance on small objects. Using higher resolution images is also likely to improve performance on small objects.</li><li>80% of the forward pass time is spent in the base network. Significant improvement in inference time can be obtained by using MobileNet instead of VGG.</li><li>Using multi-scale feature maps for prediction is imperative to SSD’s performance. Adding more default boxes can improve accuracy at the cost of lower speed.</li></ul><h4>8. Resources</h4><ul><li>Original SSD <a href="https://arxiv.org/pdf/1512.02325.pdf"><em>paper</em></a></li><li>PyTorch <a href="https://github.com/amdegroot/ssd.pytorch"><em>codebase</em></a> used throughout the post</li><li>Original Caffe <a href="https://github.com/weiliu89/caffe/tree/ssd"><em>code</em></a></li><li>Other blog posts explaining SSD: <a href="https://medium.com/@jonathan_hui/ssd-object-detection-single-shot-multibox-detector-for-real-time-processing-9bd8deac0e06"><em>1</em></a>, <a href="https://medium.com/@smallfishbigsea/understand-ssd-and-implement-your-own-caa3232cd6ad"><em>2</em></a>, <a href="https://towardsdatascience.com/understanding-ssd-multibox-real-time-object-detection-in-deep-learning-495ef744fab"><em>3</em></a></li></ul><p>To summarize, SSD is the first one-stage detector to achieve an accuracy comparable to two-stage detectors while maintaining real-time efficiency. It uses the idea of default boxes and multi-scale predictions to directly regress on the bounding box coordinates, without the need of a proposal generation step. There are a few shortcomings of SSD as well, like it doesn’t work well with small objects, and a lot of ideas have been proposed to tackle its various issues. We’ll discuss these ideas in the next post.</p><p>I, personally, found this to be a very fascinating read and as I went into the implementation details, I only got more interested. This is a perfect example of the importance of small details and I definitely learned a lot while working on it. For someone looking to get their hands dirty with object detection, SSD is one of the best places to start. Also, if you found the post useful, make sure to give it a clap and share with other people who might benefit from it.</p><blockquote>If you want to stay notified about my future posts, do follow me on Medium. If there’s anything that you might want to share with me or give any sort of feedback on my writing/thoughts, I would love to hear it as well. Feel free to connect with me on <a href="https://www.linkedin.com/in/aman-dalmia">LinkedIn</a>,<em> </em>or follow me on <a href="http://github.com/dalmia">Github</a>.</blockquote><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=65797a5e675b" width="1" height="1" alt=""><hr><p><a href="https://medium.com/inveterate-learner/real-time-object-detection-part-1-understanding-ssd-65797a5e675b">Real-time object detection part 1: Understanding SSD</a> was originally published in <a href="https://medium.com/inveterate-learner">Inveterate Learner</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[But wait, how to ACTUALLY do the cool stuff? — Chapter 11]]></title>
            <link>https://medium.com/inveterate-learner/deep-learning-book-chapter-11-c6ad1d3c3c08?source=rss----ba6eaa0b1544---4</link>
            <guid isPermaLink="false">https://medium.com/p/c6ad1d3c3c08</guid>
            <category><![CDATA[deep-learning]]></category>
            <category><![CDATA[machine-learning]]></category>
            <category><![CDATA[deep-learning-book]]></category>
            <category><![CDATA[debugging]]></category>
            <category><![CDATA[convolutional-network]]></category>
            <dc:creator><![CDATA[Aman Dalmia]]></dc:creator>
            <pubDate>Sat, 25 Aug 2018 03:39:21 GMT</pubDate>
            <atom:updated>2018-08-25T03:39:21.171Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*jlLjikVeV1qRv7PWuQq3EA.jpeg" /><figcaption>Photo by <a href="https://unsplash.com/photos/5Xwaj9gaR0g?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Martin Shreder</a> on <a href="https://unsplash.com/search/photos/work?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure><p><em>This is a series of blog posts on the </em><a href="http://deeplearningbook.org/"><em>Deep Learning book</em></a><em> where </em><a href="https://medium.com/inveterate-learner"><em>we</em></a><em> are attempting to provide a summary of each chapter highlighting the concepts that we found to be the most important so that other people can use it as a starting point for reading the chapters, while adding further explanations on few areas that we found difficult to grasp. Please refer </em><a href="http://www.deeplearningbook.org/contents/notation.html"><em>this</em></a><em> for more clarity on notation</em>.</p><p>We are excited to say that this is going to be the last chapter that we cover before entering the <strong>Deep Learning Research </strong>section<strong> </strong>of the book which is, for the most part, unfamiliar terrains for us. A lot of what we’d been talking about till now covered the theoretical aspects of Deep Learning. However, there’s a <a href="https://nips.cc/Conferences/2017/Schedule?showEvent=8776"><em>large gap</em></a> between theory and what works in practice. This chapter is specifically dedicated to practitioners and people who are looking to apply Deep Learning for building <a href="http://www.yaronhadad.com/deep-learning-most-amazing-applications/"><em>cool applications</em></a> and <a href="https://medium.com/@vratulmittal/top-15-deep-learning-applications-that-will-rule-the-world-in-2018-and-beyond-7c6130c43b01"><em>solving real-world problems</em></a>.</p><blockquote>A good machine learning practitioner needs to know how to choose an algorithm for a particular application and how to monitor and respond to feedback obtained from experiments in order to improve a machine learning system.</blockquote><p>The various choices that one might need to make include which type of data to gather, where would they find that data, should they gather more data, change model complexities, change (add/remove) regularization, improve optimization, debug the software implementation, etc. The recommended practical design process is as follows:</p><ul><li>Decide on a a single number metric to evaluate your model. This represents the final goal and you need to set a specific target that you want to achieve. Coming from <a href="https://medium.com/u/592ce2a67248">Andrew Ng</a>’s <a href="http://www.mlyearning.org/"><em>Machine Learning Yearning</em></a><em> </em>and also from personal experience, most teams forget to decide upon this only to realize the mistake very late in the process that setting this up would have gave them a clear guide on what they wanted to improve.</li><li>Get an end-to-end pipeline working as soon as possible, including the evaluation of the required metrics. This will, more often than not, require that you use a very simple model that can accept the inputs correctly and produce the outputs in the right format that can be further used for training / evaluation / analysis. The major benefit here is that now you can solely focus on improving the model and on doing any specific change, you can instantly get the final results and check whether that change improved the model or not.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ZkTmCMDFtVgreRHV3RtCwQ.png" /><figcaption>Set up the entire pipeline very early and then, keep improving the MODEL component without focusing about the entire system too much.</figcaption></figure><ul><li>Instrument the system well to determine bottlenecks in performance which requires diagnosing which components perform worse than expected and understanding the reason behind poor performance — overfitting, underfitting, modelling, problems in data, software implementation errors, etc.</li><li>Based on the diagnosis above, keep improving the algorithm iteratively either by adding more data, increasing the capacity of the model, tuning hyperparameters or improving the quality of data by better annotation, etc.</li></ul><p>The chapter is divided into the following sections:</p><ul><li><a href="#bfce"><strong><em>Performance Metrics</em></strong></a></li><li><a href="#7721"><strong><em>Default Baseline Models</em></strong></a></li><li><a href="#a7f0"><strong><em>Determining Whether to Gather More Data</em></strong></a></li><li><a href="#2568"><strong><em>Selecting Hyperparameters</em></strong></a></li><li><a href="#30ec"><strong><em>Debugging Strategies</em></strong></a></li></ul><h4><strong>1. Performance Metrics</strong></h4><p>As mentioned above, it’s extremely important to decide on which error metric to use as that will ultimately guide you on how to make progress. It should be sufficiently representative of the end goal that you are trying to achieve. Let me give you an example. Suppose you are working on a <a href="http://blog.qure.ai/notes/semantic-segmentation-deep-learning-review"><em>Semantic Segmentation</em></a> problem where we want to assign a class to each pixel of the input image. The image below demonstrates how the output should look like given an input image:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/737/1*hXNJyRsPvUrDnyNKLcM89w.png" /><figcaption>Here, all the pixels constituting the man has been marked as one class, those representing the bicycle as another class and the remaining ones as the background class. Source: <a href="https://www.jeremyjordan.me/semantic-segmentation/">https://www.jeremyjordan.me/semantic-segmentation/</a></figcaption></figure><p>To simplify, let’s consider a binary segmentation task where class 1 represents “man” and class 0 represents the background class. Thus, the expected output now becomes:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/737/1*wCbYcx5dCFdet8fYCgMndw.png" /><figcaption>Notice that the pixels belonging to the bicycle class are also labelled as 0 as we are considering only a binary semantic segmentation task. Thus, the bicycle class now comes under the background class.</figcaption></figure><p>Now, what would be a reasonable metric to choose here that would be representative of the final goal here? — Think before looking down.</p><p>A default metric to start off with is <a href="https://en.wikipedia.org/wiki/Accuracy_and_precision"><em>accuracy</em></a><em>,</em> which indicates the percentage of pixels where our model predicted the right class. Although the example above has a fairly equal number of class 1 and class 0 pixels, this need not be the case. There can be images where there is a single person in the image or there can be a lot of images with no people. In such cases where there is a high <a href="http://www.chioka.in/class-imbalance-problem/"><em>class imbalance</em></a>, a very simple way to achieve a high accuracy could be to always predict the class 0. However, it’s clearly not a good classifier although it might get 90% accuracy. You’d ideally like a metric that is not dependent on the distribution of the classes in the dataset. For this reason, the most commonly used metric for semantic segmentation is <strong>Intersection over Union (IoU)</strong>, which is defined as follows:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/600/1*2LPQLE87SJBRCSXhpow9sA.png" /><figcaption>IoU is given by the ratio of the overlap (intersection) and the union of the predicted output and the ground truth. Source: <a href="https://www.pyimagesearch.com/2016/11/07/intersection-over-union-iou-for-object-detection/">https://www.pyimagesearch.com/2016/11/07/intersection-over-union-iou-for-object-detection/</a></figcaption></figure><p>The image below shows why IoU is a good metric:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/600/1*JoyOqNm42i90sM2Y7VWBYA.png" /><figcaption>In the first case, although the red box is almost entirely within the green one, but their union is high and that makes the IoU low. However, in the other two cases, the intersection nears the union more and more. Source: <a href="https://www.pyimagesearch.com/2016/11/07/intersection-over-union-iou-for-object-detection/">https://www.pyimagesearch.com/2016/11/07/intersection-over-union-iou-for-object-detection/</a></figcaption></figure><p>One more thing that I’d like to point out before moving on from this example is that it is equally useful in images where there is no object, i.e. the entire image represents the background class. This is achieved by adding a small <strong>ϵ </strong>to both the numerator and denominator during the calculation of IoU. Now, if the ground truth contained only background class and our model predicted that as well, the intersection as well as the union is 0. Thus, the IoU becomes (0 + ϵ) / (0 + ϵ) = ϵ / ϵ = 1. This indicates the importance of choosing the right metric.</p><p>Then there can be problems where one type of mistake is more costly than another. In the case of spam detection, classifying a spam mail as non-spam is much less costlier than classifying a non-spam message as spam. In such cases, instead of measuring the error rate, we might be interested in observing some form of total cost which is representative of our problem.</p><p>Similar to the semantic segmentation problem described above, there are many cases where there is a large class imbalance. For example, in a particular sample of population, one out of a 1000 people might have cancer. Thus, 9999 people don’t have cancer. If I simply use a classifier that classifier everyone as not having cancer, I can achieve an accuracy of 99.99%. But would you be willing to use this classifier for testing yourself?<br>Definitely not. In such a case, accuracy is a bad metric. We instead use <strong>precision</strong> and <strong>recall</strong> to evaluate our classifier. I generally use this figure to remember what both of them mean:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/350/0*8rEaEah_GvtT6JR2.png" /><figcaption>Source: <a href="https://en.wikipedia.org/wiki/Precision_and_recall">https://en.wikipedia.org/wiki/Precision_and_recall</a></figcaption></figure><p>Precision represents the fraction of detections that were actually true, whereas Recall stands for the the fraction of true events that were successfully detected.</p><figure><img alt="Image result for precision recall equation" src="https://cdn-images-1.medium.com/proxy/1*7J08ekAwupLBegeUI8muHA.png" /><figcaption>Source: <a href="https://towardsdatascience.com/accuracy-precision-recall-or-f1-331fb37c5cb9">https://towardsdatascience.com/accuracy-precision-recall-or-f1-331fb37c5cb9</a></figcaption></figure><p>Now, consider that if a detector says that all the cases are not cancer will achieve the perfect precision, but 0 recall. Many a times, it’s actually desirable to have a single metric to judge on, rather than have a trade-off between two of them. F1-score, which is the Harmonic Mean of Precision &amp; Recall is a widely accepted metric:</p><figure><img alt="Image result for f1 score equation" src="https://cdn-images-1.medium.com/proxy/1*UJxVqLnbSj42eRhasKeLOA.png" /><figcaption>Source: <a href="https://towardsdatascience.com/beyond-accuracy-precision-and-recall-3da06bea9f6c">https://towardsdatascience.com/beyond-accuracy-precision-and-recall-3da06bea9f6c</a></figcaption></figure><p>However, F1-score gives equal weightage to both precision and recall. There can be cases where you want to weigh one over the other and hence, we have the more general, F-beta score:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*wECgRb1Vn3PPIGXgKqZXSQ.jpeg" /><figcaption>β &lt; 1 weighs precision more and β &gt; 1 weighs recall more. Source: <a href="https://www.youtube.com/watch?v=Clo-t9eeEwg">https://www.youtube.com/watch?v=Clo-t9eeEwg</a></figcaption></figure><p>Also, in some cases the machine learning algorithm can refuse to make any decision at all in cases where it’s not very confident about it’s decision. This can be important in situations where a misclassification can be harmful and it’d be much better for a human to have a look. Then again, a ML system is useful only when it significantly reduces the number of instances that a human operator must process. A natural performance metric here is <strong>coverage</strong>, which stands for the fraction of images that where the machine learning system is able to produce a response.</p><p>In most applications, it might not be possible to achieve absolute zero error even after having infinite data either due to the features not being sufficiently representative or the system being intrinsically stochastic. The minimum amount of error possible for a system is called the Bayes’ error for the system.</p><p>A major bottleneck to performance is often the fact that training data is limited. Now, once away from standard datasets like <a href="http://yann.lecun.com/exdb/mnist/"><em>MNIST</em></a> into more real-world problems, you’ll realize that getting accurate data is much more harder than it initially seems and in most often, doesn’t come for free as well. So, you really need to analyze how much is additional data going to improve your performance metric. I’ll try to explain this with an example. As mentioned in <a href="https://news.stanford.edu/thedish/2017/03/14/andrew-ng-why-ai-is-the-new-electricity/"><em>Andrew</em></a><em>’s </em>book, <a href="http://www.mlyearning.org/"><em>Machine Learning Yearning</em></a><em>, </em>a standard method of error analysis to actually observe (say) 100 examples where your model is failing and then checking which classes actually account for the maximum % of error:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/885/1*WuE8b_5djC97zvRoQgeTNQ.png" /><figcaption>Source: <a href="http://www.mlyearning.org/">http://www.mlyearning.org</a></figcaption></figure><p>From the figure above, it can be clearly seen that collecting more <strong>Dog </strong>images might improve the error rate by 8% at max. However, collecting more <strong>Blurry</strong> images might potentially improve the error rate by 61%, which is very significant. Thus, it makes sense to spend time on collecting more blurry images and doing this exercise would save you the embarrassment of spending months on collecting better Dog images only to see the error rate improve by 8%. For more such tips, refer to the book linked above.</p><p>The bottom line being that you need to decide what is realistic desired error rate for your intended application beforehand and use that to guide your design decisions in the future.</p><h4>2. Default Baseline Models</h4><p>As mentioned at the start, it is very important to establish a working end-to-end system as soon as possible. Depending on the complexity of the problem, we might even choose to begin with a very simplistic model like logistic regression. However, if the problem that you intend to solve falls under the <a href="https://en.wikipedia.org/wiki/AI-complete"><em>“AI-complete”</em></a> category like Image Classification, Speech Recognition, etc., starting off with a deep learning model would almost always be better.</p><p>You first begin with choosing the general category of model to use based on the structure of your data. If your data consists of fixed-size vectors and you intend to perform a supervised learning task, use a multi-layer perceptron. If your data has a fixed topological structure, using a <a href="https://medium.com/inveterate-learner/deep-learning-book-chapter-9-convolutional-networks-45e43bfc718d"><em>Convolutional Neural Network</em></a> might be the best way forward. Similarly, if your data has a sequential pattern, <a href="https://en.wikipedia.org/wiki/Recurrent_neural_network"><em>Recurrent Neural Networks</em></a> would be the ideal starting point. However, the <a href="https://www.technologyreview.com/s/513696/deep-learning/"><em>speed</em></a> at which Deep Learning as a field is progressing, default algorithms are likely to change. For example, 3–4 years ago <a href="https://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks.pdf"><em>AlexNet</em></a> would have been the ideal starting point for image-based tasks. However, now <a href="https://arxiv.org/abs/1512.03385"><em>ResNets</em></a> are the widely accepted default choice.</p><figure><img alt="Image result for alexnet vs resnet" src="https://cdn-images-1.medium.com/proxy/1*HyaPKtxU07iVzZ4RjJJlUQ.png" /><figcaption>ImageNet top-5 error progress over the years. AlexNet had 8 layers where the more powerful ResNet has more than 150 layers. Source: <a href="https://medium.com/@RaghavPrabhu/cnn-architectures-lenet-alexnet-vgg-googlenet-and-resnet-7c81c017b848">https://medium.com/@RaghavPrabhu/cnn-architectures-lenet-alexnet-vgg-googlenet-and-resnet-7c81c017b848</a></figcaption></figure><p>For training the model, a reasonable starting point is to use the Adam optimizer. Apart from this, SGD with momentum and a learning rate decay is widely used too where the learning rate is decayed exponentially until a point and then, reduced linearly by a factor of 2–10 each time validation error plateaus. <a href="https://medium.com/inveterate-learner/deep-learning-book-chapter-8-optimization-for-training-deep-models-part-ii-438fb4f6d135#5bbf"><em>Batch-Normalization</em></a> would, in general, always improve performance by providing stability and allowing the use of larger learning rate thereby helping to reach convergence faster.</p><p>As you increase your model complexity, you’ll eventually become prone to overfitting since your training data is limited. Thus, it’s always advised to add some <a href="https://medium.com/inveterate-learner/deep-learning-book-chapter-7-regularization-for-deep-learning-937ff261875c"><em>regularization</em></a> to your model as well. Common choices include L2-penalty to the loss function, Dropout between layers, Early stopping and Batch-Normalization. Using Batch-Normalization <a href="http://forums.fast.ai/t/batch-normalisation-vs-dropout/5172"><em>allows the omission</em></a> of Dropout. If you missed our post on regularization, feel free to go through it where all of these have been <a href="https://medium.com/inveterate-learner/deep-learning-book-chapter-7-regularization-for-deep-learning-937ff261875c"><em>explained in detail</em></a>.</p><p>If your task is reasonably similar to any other task where prior work has been done, it is advised to just copy the model (along with the weights) from the latter and use that as an initialization point for your task. This way of training is called <strong>transfer learning</strong>. For example, in the famous <a href="https://www.kaggle.com/c/dogs-vs-cats"><em>Dogs Vs Cats Image Classification challenge on Kaggle</em></a>, a model pretrained on ImageNet which contained similar images, was used as the starting point to achieve the best performance, rather than training the model from scratch.</p><figure><img alt="Related image" src="https://cdn-images-1.medium.com/proxy/1*6ACbDsBMeDZcLg9W8CFT_Q.png" /><figcaption>Here, the large dataset of object images refers to ImageNet. Source: <a href="https://towardsdatascience.com/transfer-learning-using-differential-learning-rates-638455797f00">https://towardsdatascience.com/transfer-learning-using-differential-learning-rates-638455797f00</a></figcaption></figure><p>Finally, some domains like Natural Language Processing (NLP) benefit tremendously from using unsupervised learning methods during initialization. In the current trend of Deep Learning applied to NLP, it’s common to represent each word as an embedding (vector) and there exist unsupervised learning methods like <a href="https://en.wikipedia.org/wiki/Word2vec"><em>word2vec</em></a> and <a href="https://nlp.stanford.edu/projects/glove/"><em>GLoVe</em></a> for learning these word embeddings.</p><h4>3. Determining Whether to Gather More Data</h4><blockquote>Numbers have an important story to tell. They rely on you to give them a clear and convincing voice.</blockquote><blockquote>— Stephen Few</blockquote><p>A rookie mistake that a lot of people make is that they keep trying different algorithms to improve the performance of their models, whereas simply improving the data they have or gathering more data can be the best source of improvement. We touched upon the topic of how to decide when to get more data, but since data is the most integral part of getting an AI solution working, we’ll explore this in a bit more detail now.</p><p>So, how do you decide when to get more data? Firstly, if the performance of your model on your training set is poor, it is not making full use of the information present in your data and in this case, you need to increase the complexity of your model by adding more layers or increasing the number of hidden units in each layer. Also, hyperparameter tuning is an important step to perform. You’d be surprised how large an effect choosing the right hyperparameters can have in getting your model working. For example, learning rate is THE <a href="https://medium.com/inveterate-learner/deep-learning-book-chapter-8-optimization-for-training-deep-models-part-i-20ae75984cb2#7da2"><em>most important</em></a> hyperparameter that you need to tune. Setting the right value of the learning rate for your problem can save you loads of hours of wasted effort. However, if your model is reasonably complex and optimization carefully tuned but still the performance is not up to the desired level, the problem might be the <em>quality</em> of data instead, in which you have to go back to square one and start collecting cleaner data.</p><p>If the training error is low but the validation error is much higher, then you can safely assume that your best would be to say:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/600/0*W2nWKNYuOSdZVU8X.jpg" /><figcaption>Source: <a href="https://makeameme.org/meme/yeahim-gonna-need-c45pbd">https://makeameme.org/meme/yeahim-gonna-need-c45pbd</a></figcaption></figure><p>The specific situation mentioned above, where training error is low but test error is high, is called overfitting and is one of the most commonly occurring problems in training deep models, in which case regularization might help. To reinforce the importance of data in the modern deep networks, for those who might not be aware, the reason that Deep Learning started gaining attention was the ImageNet competition where a deep learning model outperformed the previous best model by a significantly large margin in 2012. ImageNet consists of millions of annotated images and the creation of similar large labelled datasets is the reason that extremely complex problems like object detection have become solved problems today.</p><p>Finally, it’s generally observed that adding a small fraction of the total number of examples won’t have a noticeable effect on the performance. Thus, we need to monitor how much the performance of a model improves as the dataset size increases and it should be monitored at a logarithmic scale.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/724/1*xJp8U3vKnRhBTLXl05OBbg.png" /><figcaption>One possible plot of error Vs data size. It might be possible that your use-case comes out different. Source: <a href="http://www.mlyearning.org/">http://www.mlyearning.org</a></figcaption></figure><p>As can been seen from the plot above, the <strong>training error</strong> will generally <strong>increase</strong> as you increase the dataset size. This is because the model will find it harder to fit to all the datapoints exactly now. Also, by increasing the dataset size, your validation (dev) error will decrease as the model would learn to be more generalized now.</p><h4>4. Selecting Hyperparameters</h4><p>Most deep learning algorithms have a lot of hyperparameters that need to be chosen correctly. Different hyperparameters control different aspects of the model. Some affect the memory cost like the number of layers to use while others affect the performance like the keep probability for Dropout, learning rate, momentum, etc. Broadly, there are two approaches to choosing these hyperparameters. The first one is to choose them manually which involves understanding what the hyperparameters do and how they affect training and generalization. The other approach is to choose the hyperparameters automatically, which reduces the complexity a lot but comes at the cost of compute power. We’ll discuss these two approaches in more details now:</p><p><strong>i) Manual Hyperparameter Tuning:</strong></p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fgiphy.com%2Fembed%2FlVJvPplEQUFpe%2Ftwitter%2Fiframe&amp;url=https%3A%2F%2Fmedia.giphy.com%2Fmedia%2FlVJvPplEQUFpe%2Fgiphy.gif&amp;image=https%3A%2F%2Fmedia.giphy.com%2Fmedia%2FlVJvPplEQUFpe%2Fgiphy-downsized-large.gif&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=giphy" width="435" height="435" frameborder="0" scrolling="no"><a href="https://medium.com/media/c2284f39c21001797e11425b014599a0/href">https://medium.com/media/c2284f39c21001797e11425b014599a0/href</a></iframe><p>As briefly mentioned above, manual hyperparameter tuning requires a lot of domain knowledge and fundamental understanding of training error, generalization error, learning theory, etc. The primary aim of manual hyperparameter tuning is to achieve effective capacity to match the complexity of the task by trading off memory and runtime. Factors influencing the effective capacity are representational capacity of the model, ability of the learning algorithm to minimize the cost function used to train the model and the degree to which the cost function and the training procedure regularize the model.</p><p>The generalization error typically follows a U-shaped curve as shown below:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/438/0*jCng5a7VNGA9AG0l" /><figcaption>Source: <a href="https://djsaunde.wordpress.com/2017/07/17/the-bias-variance-tradeoff/">https://djsaunde.wordpress.com/2017/07/17/the-bias-variance-tradeoff/</a></figcaption></figure><p>On the extreme left, we are in the underfitting regime where the capacity of the model is low and both training and generalization errors are high. On the extreme right, we enter the overfitting regime where the training error is low but the gap between the training error and test error is high. The optimal spot is somewhere in the middle where we trade-off a slightly higher training error for the lowest possible generalization error.</p><p>Many hyperparameters affect overfitting (or underfitting) and in different ways. For e.g. increasing certain hyperparameters like, the number of hidden units, increases the chances of overfitting, whereas increasing others like weight decay reduces. Some of them are discrete like the number of hidden units, whereas others might be binary like whether to use Batch Normalization or not. Some hyperparameters have bounds that implicitly restrict them, like the weight decay coefficient which can <em>only reduce</em> capacity. Thus, if the model is underfitting, you can’t get it to overfit by adding weight decay.</p><p>As mentioned before, if you can tune only one hyperparameter, tune the <em>learning rate</em>. The effective capacity of the model is the highest at the right learning rate, neither too high nor too low. We discuss in more details about the effect of learning rate on the training process in one of our <a href="https://medium.com/inveterate-learner/deep-learning-book-chapter-8-optimization-for-training-deep-models-part-i-20ae75984cb2#7da2"><em>earlier posts</em></a>, but to summarize: setting the learning rate too low slows training and might even cause the algorithm to get stuck in local minima; setting it too high might make the training unstable due to wild oscillations.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*An4tZEyQAYgPAZl396JzWg.png" /></figure><p>If the training error is high, general approach is to add more layers or more hidden units to increase the capacity. If the training error is low but the test error is high, you need to reduce the gap between the train and test errors without increasing the training error too much. Usually, a sufficiently large model which is well-regularized (for e.g. by using Dropout, Batch Normalization, weight decay, etc.) works the best.</p><p>The two broad approaches to achieve the final goal of a low generalization are: adding <a href="https://medium.com/@amandalmia18/deep-learning-book-chapter-7-regularization-for-deep-learning-937ff261875c"><em>regularization</em></a> to the model and increasing the dataset size. The table below shows how each hyperparameter affects capacity:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/592/1*6f6SpcFZlNibrQbAKFJd4Q.png" /><figcaption>Taken from the Deep Learning Book (<a href="https://deeplearningbook.org/">https://deeplearningbook.org</a>)</figcaption></figure><p><strong>ii) Automatic Hyperparameter Optimization Algorithms</strong>: Hyperparameter tuning can be viewed as an optimization process itself which optimizes an objective function, such as the validates, sometimes under constraints like training time, memory limits, etc. Thus, we can design <em>Hyperparameter Optimization (HO) </em>algorithms<em> </em>that wrap a learning algorithm and choose its hyperparameters. Unfortunately, these HO algorithms have their own set of hyperparameters, but these are generally easier to choose as would be discussed now:<br><em>Grid Search</em>: For grid search, first pick a range of values that you feel is suitable for each hyperparameter. Then, you train the model for each possible combination of the values of the hyperparameters. To simplify, if you have 2 hyperparameters and pick a range of N values for each of them, you’ll need to train the model for all the possible N² combinations. You generally set the maximum and minimum of the range based on your understanding (and/or experience) and then choose the values in between, generally, on a logarithmic scale. For e.g. possible values for learning rate: {0.1, 0.01, 0.001}, number of hidden units: {50, 100, 200, 400}, etc.</p><p>Also, Grid search works best when performed repeatedly. E.g. if the range that you set was {0.1, 0, 1} and the best performing one was 1, you probably set the range wrong and you should check again for a higher range like {1, 2, 3}. In case the best performing value comes out as 0, then you should do a more refined search between {-0.1, 0, 0.1}.</p><p>The main problem with Grid Search is the computational cost. If there are <em>m</em> hyperparameters to be tuned, and each of them can take <em>N</em> values, the number of training and evaluation trials grows as O(N^m).</p><p><em>Random Search</em>: A better and faster approach is something known as random search. In this case, you define some distribution over the choice of values, e.g.binomial for binary, multinomial for discrete, uniform on a log-scale for say, learning rate:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/423/1*-9jmZfxEnU1djvC1pd0ckw.png" /></figure><p>Then, for each run, randomly sample the value of each hyperparameter based on its distribution. This can prove to be exponentially more efficient than grid search. The figure below explains this:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/702/1*uCCMhHmlK3EGRIqXjDBkPg.png" /></figure><p>To make it clearer, the main reason that random search reduces validation error faster than grid search is that it doesn’t perform any wasted computation. Since grid search goes over all possible combinations, it’ll evaluate cases where the value of only one hyperparameter changes, with the values of the rest being the same. Now, if this hyperparameter doesn’t affect the performance too much, then grid search has performed a wasted evaluation. However, in the case of random search, for different values of a hyperparameter, the values of the rest of the hyperparameters would most likely also be different. Thus, random search doesn’t do any wasted evaluation.</p><p><em>Model-based Hyperparameter Optimization</em>: As mentioned briefly above, hyperparameter tuning can be viewed as an optimization process. In simplified settings, it might be possible to take the gradient of some differentiable error measure on the validation set with respect to the hyperparameters and simply use Gradient Descent. However, in most practical settings, this gradient is not unavailable. To compensate for this, you can build a model of the validation error and perform optimization on this model. A general approach is to build a Bayesian regression model to estimate the expected value of the validation error along with the uncertainty around this estimate. Bayesian Hyperparameter Optimization (BHO) is still nascent and not sufficiently reliable. One major drawback compared to random search would be that BHO requires each experiment to go till completion to be able to extract any information out of it, whereas in many cases it might be clearly visible at the initial stages itself that that particular set of hyperparameters doesn’t work.</p><h4>5. Debugging Strategies</h4><p>Machine learning systems are invariably one of the most difficult ones to debug as it’s hard to figure out if the error was in training the model or in the software implementation. Another major bottleneck is that we ourselves are not sure what the intended behaviour of the algorithm is, since, the original goal of training machine learning algorithms is that they can discover useful behaviour from the data that we, as humans, might be unaware of. For example, if we are working on a new classification task (that no one has worked on before), it’s not sure that getting a 5% error is good or bad as we have nothing to compare it against.</p><p>There are various debugging strategies which are commonly used. I’m listing the ones that I commonly tend to use. Feel free to refer the book for a few more:<br>1) <em>Visualize the model in action: </em>This is one of the best ways to verify if the training is going correctly and also, understanding which areas might need improvement. Once the training starts, visualize the output of your model after a few epochs. If you’re working on a semantic segmentation problem, look at the segmentation output. If you’re training a generative model of speech, listen to a few sample of speech that it produces. Also, it’s common to have bugs in the evaluation metric as they might need corner-case handling which you might not have taken care of. Evaluation bugs are the hardest ones to catch and they fool you into believing that your model is performing/not performing well.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/636/1*30_9j4bNQAgj6WULagLZyA.png" /><figcaption>Source: <a href="https://www.semanticscholar.org/paper/End-to-End-Training-of-Hybrid-CNN-CRF-Models-for-Janusch-Kropatsch/4da5f0c1d07725a06c6b4a2646e31ea3a5f14435">https://www.semanticscholar.org/paper/End-to-End-Training-of-Hybrid-CNN-CRF-Models-for-Janusch-Kropatsch/4da5f0c1d07725a06c6b4a2646e31ea3a5f14435</a></figcaption></figure><p>2) <em>Visualize the worst mistakes:</em> Going back to the semantic segmentation problem above, suppose we run the model on our test set. Based on the IoU scores, we can sort the samples to identify where our model performed the worst. Visualizing those examples where the model fails terribly, is a great way to identify errors in data processing/annotation. In the case where you infer that the problem had been with the annotation of data, the best way to improve performance would be to actually correct the annotations, even manually if required, as the payoff of having the correct data is very high.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/359/0*1E4A9q_OAEWRrOdy.jpg" /><figcaption>Google misclassified the photo of humans as that of gorillas. It came under some scrutiny for having this bias in its algorithms. Source: <a href="https://blogs.wsj.com/digits/2015/07/01/google-mistakenly-tags-black-people-as-gorillas-showing-limits-of-algorithms/">https://blogs.wsj.com/digits/2015/07/01/google-mistakenly-tags-black-people-as-gorillas-showing-limits-of-algorithms/</a></figcaption></figure><p>3) <em>Fit a tiny dataset:</em> Before starting to train on your entire training set, always fit your model to a small subset of the entire dataset. Even very simple models will overfit to a handful of examples. Taking the extreme case of a single example, it’s very easy to correctly fit to it by setting the weights to zero and the biases appropriately. From my practical experience too, if you’re making a modification or trying something different, first make sure that it can overfit on a small enough dataset. If it can’t, then there’s a high probability that there’s been a software bug in setting up the training process.</p><p>4) <em>Monitor histograms of activations and gradients: </em>It can be useful to monitor the pre-activation values of hidden units in case there is a problem in training. What to monitor depends on the type of activation function used. For example, in the case of ReLU (commonly used between layers), we can check how often is the unit off (which would happen if the pre-activation value is less than 0). In the case of sigmoidal units, it can be useful to check how often does it stay in the saturated regions, i.e. either too positive or too negative. Also, if the gradients grow or vanish too quickly, it can be a problem during training. It has advised in the book that the magnitude of the gradient should be approximately 1% of the magnitude of the parameter, neither too high (50%) nor too low (0.001%). Thus, comparing the two magnitudes can be a good approach for debugging too.</p><p>Finally, it can be shown (covered in later chapters) that some optimization algorithms provide certain guarantees, like the objective function not increasing after each epoch, all the gradients being zero at convergence, etc. and as a safekeeping step, we can ensure that these guarantees are met.</p><p>This concludes our summary and explanation for <a href="http://www.deeplearningbook.org/contents/guidelines.html"><em>Chapter 11</em></a>. The motivation behind this post was to give you an intuition about the various knobs of a deep learning model and give you practical tips on getting your model to perform well. I believe that if you judiciously follow what was taught here, training your model wouldn’t be the bottleneck for you anymore. DATA will always be ;)<br>To stay updated with our posts, <a href="https://medium.com/inveterate-learner"><em>follow</em></a> our publication, <strong>Inveterate Learner</strong>. If you’re looking for the summary of previous chapters or are more comfortable reading from a Jupyter Notebook, feel free to have a look over our repository <a href="https://github.com/dalmia/Deep-Learning-Book-Chapter-Summaries"><em>here</em></a>.</p><blockquote>If you get up in the morning and think the future is going to be better, it is a bright day. Otherwise, it’s not.</blockquote><blockquote>- Elon Musk</blockquote><blockquote>If there’s anything that you might want to share with me or give any sort of feedback on my writing/thoughts, I would love to hear it from you. Feel free to connect with me on <a href="https://www.linkedin.com/in/aman-dalmia">LinkedIn</a>, <a href="https://www.facebook.com/aman.dalmia.8">Facebook</a> or follow me on <a href="http://github.com/dalmia">Github</a>.</blockquote><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=c6ad1d3c3c08" width="1" height="1" alt=""><hr><p><a href="https://medium.com/inveterate-learner/deep-learning-book-chapter-11-c6ad1d3c3c08">But wait, how to ACTUALLY do the cool stuff? — Chapter 11</a> was originally published in <a href="https://medium.com/inveterate-learner">Inveterate Learner</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Deep Learning Book: Chapter 8 — Optimization For Training Deep Models Part II]]></title>
            <link>https://medium.com/inveterate-learner/deep-learning-book-chapter-8-optimization-for-training-deep-models-part-ii-438fb4f6d135?source=rss----ba6eaa0b1544---4</link>
            <guid isPermaLink="false">https://medium.com/p/438fb4f6d135</guid>
            <category><![CDATA[artificial-intelligence]]></category>
            <category><![CDATA[deep-learning]]></category>
            <category><![CDATA[deep-learning-book]]></category>
            <category><![CDATA[optimization]]></category>
            <category><![CDATA[machine-learning]]></category>
            <dc:creator><![CDATA[Aman Dalmia]]></dc:creator>
            <pubDate>Mon, 13 Aug 2018 05:52:59 GMT</pubDate>
            <atom:updated>2018-08-13T06:08:11.063Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/375/1*tE8dh8Zv0kc4e0xet41xYA.jpeg" /></figure><p><em>This is going to be a series of blog posts on the </em><a href="http://deeplearningbook.org/"><em>Deep Learning book</em></a><em> where </em><a href="https://medium.com/inveterate-learner"><em>we</em></a><em> are attempting to provide a summary of each chapter highlighting the concepts that we found to be the most important so that other people can use it as a starting point for reading the chapters, while adding further explanations on few areas that we found difficult to grasp. Please refer </em><a href="http://www.deeplearningbook.org/contents/notation.html"><em>this</em></a><em> for more clarity on notation</em>.</p><p>This is a continuation of our <a href="https://medium.com/inveterate-learner/deep-learning-book-chapter-8-optimization-for-training-deep-models-part-i-20ae75984cb2"><em>previous post</em></a><em> </em>on the first three sections of Chapter 8. The main concepts that we discussed were <strong><em>How learning differs from pure optimization</em></strong>, <strong><em>Challenges in Neural Network Optimization </em></strong>and the <strong><em>Basic algorithms</em></strong> used in optimization. The remaining sections of the chapter deal with:</p><ul><li><a href="#f416"><strong><em>Parameter Initialization Strategies</em></strong></a></li><li><a href="#a36c"><strong><em>Algorithms with Adaptive Learning Rates</em></strong></a></li><li><a href="#5ff7"><strong><em>Approximate Second-Order Methods</em></strong></a></li><li><a href="#b113"><strong><em>Optimization Strategies and Meta-Algorithms</em></strong></a></li></ul><h4>1. Parameter Initialization Strategies</h4><p>Training algorithms for deep learning models are iterative in nature and require the specification of an initial point. This is extremely crucial as it often decides whether or not the algorithm converges and if it does, then does the algorithm converge to a point with high cost or low cost.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/450/1*VrvyP6Zv0G_u1m-CcAvlKA.png" /><figcaption>Source: <a href="https://towardsdatascience.com/random-initialization-for-neural-networks-a-thing-of-the-past-bfcdd806bf9e">https://towardsdatascience.com/random-initialization-for-neural-networks-a-thing-of-the-past-bfcdd806bf9e</a></figcaption></figure><p>We have limited understanding of neural network optimization but the one property that we know with complete certainty is that the initialization should <strong>break symmetry</strong>. This means that if two hidden units are connected to the same input units, then these should have different initialization or else the gradient would update both the units in the same way and we don’t learn anything new by using an additional unit. The idea of having each unit learn something different motivates random initialization of weights which is also computationally cheaper.</p><p>Biases are often chosen heuristically (zero mostly) and only the weights are randomly initialized, almost always from a Gaussian or uniform distribution. The scale of the distribution is of utmost concern. Large weights might have better symmetry-breaking effect but might lead to chaos (extreme sensitivity to small perturbations in the input) and exploding values during forward &amp; back propagation. As an example of how large weights might lead to chaos, consider that there’s a slight noise adding <strong><em>ϵ </em></strong>to the input. Now, we if did just a simple linear transformation like W * x, the <strong><em>ϵ </em></strong>noise would add a factor of W * ϵ<strong><em> </em></strong>to the output. In case the weights are high, this ends up making a significant contribution to the output. SGD and its <a href="#a36c"><em>variants</em></a> tend to halt in areas near the initial values, thereby expressing a prior that the path to the final parameters from the initial values is discoverable by steepest descent algorithms. A more mathematical explanation for the symmetry breaking can be found in the <a href="https://github.com/dalmia/Deep-Learning-Book-Chapter-Summaries/blob/master/Appendix.ipynb"><em>Appendix</em></a>.</p><p>Various suggestions have been made for appropriate initialization of the parameters. The most commonly used ones include sampling the weights of each fully-connected layer having m inputs and n outputs uniformly from the following distributions:</p><ul><li><em>U</em>(-1 / √m, 1 / √m)</li><li><em>U</em>(- √6 / (m+n), √6 / (m+n))</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/224/1*xFJ7Ddwp6mfFCnRFcdYMGw.png" /><figcaption><em>U</em>(<em>a</em>, <em>b</em>) represents the uniform distribution where the probability of each value between a and b, a and b inclusive, is 1/(b-a). The probability of every other value is 0.</figcaption></figure><p>These initializations have already been incorporated into the most commonly used Deep Learning frameworks nowadays so that you can just specify which initializer to use and the framework takes care of sampling appropriately. For e.g. <a href="https://keras.io/"><em>Keras</em></a>, which is a very famous deep learning framework, has a module called <a href="https://keras.io/initializers/"><em>initializers</em></a>, where the second distribution (among the 2 mentioned above) is implemented as glorot_uniform .</p><p>One drawback of using 1 / √m as the standard deviation is that the weights end up being small when a layer has too many input/output units. Motivated by the idea to have the total amount of input to each unit independent of the number of input units <em>m, </em><strong>Sparse initialization</strong> sets each unit to have exactly <em>k</em> non-zero weights. However, it takes a long time for GD to correct <em>incorrect large values</em> and hence, this initialization might cause problems.</p><p>If the weights are too small, the range of activations across the mini-batch will shrink as the activations propagate forward through the network.By repeatedly identifying the ﬁrst layer with unacceptably small activations and increasing its weights, it is possible to eventually obtain a network with reasonable initial activations throughout.</p><p>The biases are relatively easier to choose. Setting the biases to zero is compatible with most weight initialization schemes except for a few cases for e.g. when used for an output unit, to prevent saturation at initialization or when using unit as a gate for making a decision. Refer to the <a href="https://www.deeplearningbook.org/contents/optimization.html#pf1f"><em>chapter</em></a> for details.</p><h4>2. Algorithms with Adaptive Learning Rates</h4><ul><li><strong>AdaGrad</strong>: As mentioned in <a href="https://medium.com/inveterate-learner/deep-learning-book-chapter-8-optimization-for-training-deep-models-part-i-20ae75984cb2#d8ca"><em>Part I </em></a><em>, </em>it is important to incrementally decrease the learning rate for faster convergence. Instead of manually reducing the learning rate after each (or several) epochs, a better approach is to adapt the learning rate as the training progresses. This can be done by scaling the learning rates of <em>each model parameter </em>individually inversely proportional to the square root of the sum of historical squared values of the gradient. In the parameter update equation below, <strong>r</strong> is initialized with 0 and the multiplication in the update step happens element-wise as mentioned. Since the gradient value would be different for each parameter, the learning rate is scaled differently for each parameter too. Thus, those parameters having a large gradient have a large decrease in the learning rate as the learning rate might be too high leading to oscillations or it might be approaching the minima but having large learning rate might cause it to jump over the minima as explained in the figure below, because of which the learning rate should be decreased for better convergence, while those with small gradients have a small decrease in the learning rate as they might have already approached their respective minima and should not be pushed away from that. Even if they have not, reducing the learning rate too much would reduce the gradient even further leading to slower learning.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*_ESwA_N0b9XtH3GwCb7a7g.png" /><figcaption>AdaGrad parameter update equation.</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/602/1*nkJfEJpxUoqJNKUtIpYMOg.png" /><figcaption>This figure illustrates the need to reduce the learning rate if gradient is large in case of a single parameter. 1) One step of gradient descent representing a large gradient value. 2) Result of reducing the learning rate — moves towards the minima 3) Scenario if the learning rate was not reduced — it would have jumped over the minima.</figcaption></figure><p>However, accumulation of squared gradients from the very beginning can lead to excessive and premature decrease in the learning rate. Consider that we had a model with only 2 parameters (for simplicity) and both the initial gradients are 1000. After some iterations, the gradient of one of the</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/602/1*0b_myYm5IYxPUyGGPvI89w.png" /><figcaption>Figure explaining the problem with AdaGrad. Accumulated gradients can cause the learning rate to be reduced far too much in the later stages leading to slower learning.</figcaption></figure><p>parameters has reduced to 100 but that of the other parameter is still around 750. However, because of the <em>accumulation at each update</em>, the accumulated gradient would still have almost the same value. For e.g. let the accumulated gradients at each step for the <em>Parameter 1</em> be 1000 + 900 + 700 + 400 + 100 = 3100, 1/3100=0.0003 and that for <em>Parameter 2</em> be: 1000 + 900 + 850 + 800 + 750 = 4300, 1/4300 = 0.0002. This would lead to a similar decrease in the learning rates for both the parameters, even though the parameter having the lower gradient might have its learning rate reduced too much leading to slower learning.</p><ul><li><strong>RMSProp</strong>: RMSProp addresses the problem caused by accumulated gradients in AdaGrad. It modifies the gradient accumulation step to an exponentially weighted moving average in order to discard history from the extreme past. The RMSProp update is given by:</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*dTIlnEJgxhA_1Wou57Faeg.png" /><figcaption><strong>ρ </strong>is the weighing used for exponential averaging. As more updates are made, the contribution of past gradient values are reduced since <strong>ρ </strong>&lt; 1 and <strong>ρ &gt; ρ² &gt;ρ³ </strong>…</figcaption></figure><p>This allows the algorithm to converge rapidly after finding a convex bowl, as if it were an instance of AdaGrad initialized within that bowl. Let me explain why this is so. Consider the figure below. The region represented by <strong>1 </strong>indicates usual RMSProp parameter updates as given by the update equation, which is nothing but exponentially averaged AdaGrad updates. Once the optimization process lands on A, it essentially lands at the top of a convex bowl. At this point, intuitively, all the updates before A can be seen to be forgotten due to the exponential averaging and it can be seen as if (exponentially averaged) AdaGrad updates start from point A onwards.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/560/1*uKpozDTz7rhFWP7zcczs1Q.png" /><figcaption>Intuition behind RMSProp. 1) Usual parameter updates 2) Once it reaches the convex bowl, exponentially weighted averaging would cause the effect of earlier gradients to reduce and to simplify, we can assume their contribution to be zero. This can be seen as if AdaGrad had been used with the training initiated inside the convex bowl</figcaption></figure><ul><li><strong>Adam</strong>: Adapted from “<em>adaptive moments</em>”, it focuses on combining RMSProp and Momentum. Firstly, it views Momentum as an estimate of the first-order moment and RMSProp as that of the second moment. The weight update for Adam is given by:</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*khVmqO7_OHycJRpFHJ-6UQ.png" /></figure><p>Secondly, since <strong><em>s</em></strong> and<strong><em> r</em></strong> are initialized as zeros, the authors observed a bias during the initial steps of training thereby adding a correction term for both the moments to account for their initialization near the origin. As an example of what the effect of this bias correction is, we’ll look at the values of <strong><em>s</em></strong> and <strong><em>r</em></strong> for a single parameter (in which case everything is now represented as a scalar). Let’s first understand what would happen if there was no bias correction. Since <em>s (</em>notice that this is not in bold as we are looking at the value for a single parameter and the <em>s</em> here is a scalar<em>) </em>is initialized as zero, after the first iteration, the value of <em>s</em> would be (1 — <em>ρ</em>1) * <em>g</em> and that of <em>r</em> would be (1 — <em>ρ</em>2) * <em>g</em>². The <a href="https://arxiv.org/pdf/1412.6980.pdf"><em>preferred values</em></a> for <em>ρ</em>1 and <em>ρ</em>2 are 0.9 and 0.99 respectively. Thus, the initial values of <em>s</em> and<em> r </em>are pretty small and this gets compounded as the training progress. However, if we now use bias correction, after the first iteration, the value of <em>s</em> is just <em>g</em> and that of <em>r </em>is just <em>g</em>². This gets rid of the bias that occurs in the initial phase of training. A major advantage of Adam is that it’s <a href="https://stats.stackexchange.com/questions/232719/what-is-the-reason-that-the-adam-optimizer-is-considered-robust-to-the-value-of"><em>fairly robust</em></a> to the choice of these hyperparameters, i.e. <em>ρ</em>1 and <em>ρ</em>2.</p><p>The figure below shows the comparison between the various optimization methods discussed above. It can be clearly seen that algorithms with adaptive learning rates provide faster convergence:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/620/1*XVFmo9NxLnwDr3SxzKy-rA.gif" /><figcaption>NAG here refers to Nesterov Accelerated Gradient which is the same as Nesterov Momentum. Source: <a href="http://ruder.io/optimizing-gradient-descent/index.html#adam">http://ruder.io/optimizing-gradient-descent/index.html#adam</a></figcaption></figure><h4>3. Approximate Second-Order Methods</h4><p>The optimization algorithms that we’ve looked at till now involved computing only the first derivative. But there are many methods which involve higher order derivatives as well. The main problem with these algorithms are that they are not practically feasible in their vanilla form and so, certain methods are used to approximate the values of the derivatives. We explain three such methods, all of which use empirical risk as the objective function:</p><ul><li><strong>Newton’s Method</strong>: This is the most common higher-order derivative method used. It makes use of the curvature of the loss function via its second-order derivative to arrive at the optimal point. Using the second-order Taylor Series expansion to approximate J(θ) around a point θo and ignoring derivatives of order greater than 2 (this has already been discussed in previous chapters), we get:</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/937/1*teuyTQzGgNq6cj21xcLnEQ.png" /></figure><p>We know that we get a critical point for any function <em>f</em>(<em>x</em>) by solving for f&#39;(x) = 0. We get the following critical point of the above equation (refer to the <a href="https://github.com/dalmia/Deep-Learning-Book-Chapter-Summaries/blob/master/Appendix.ipynb"><em>Appendix</em></a> for proof):</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/603/1*-NIvAC_fMJHSu_GMAaoG6g.png" /></figure><p>For quadratic surfaces (i.e. where cost function is quadratic), this directly gives the optimal result in one step whereas gradient descent would still need to iterate. However, for surfaces that are not quadratic, <a href="https://math.stackexchange.com/questions/1985889/why-how-does-the-determinant-of-the-hessian-matrix-combined-with-the-2nd-deriva"><em>as long as the Hessian remains positive definite</em></a>, we can obtain the optimal point through a 2-step iterative process — 1) Get the inverse of the Hessian and 2) update the parameters.</p><p><a href="https://medium.com/inveterate-learner/deep-learning-book-chapter-8-optimization-for-training-deep-models-part-i-20ae75984cb2#c3a9"><em>Saddle points</em></a> are problematic for Newton’s method. If all the eigenvalues are not positive, Newton’s method might cause the updates to move in the wrong direction. A way to avoid this is to add regularization:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/504/1*e_P8lG0enVsEqd6e91UpKg.png" /></figure><p>However, if there is a strong negative curvature i.e. the eigenvalues are largely negative, <em>α</em> needs to be sufficiently high to offset the negative eigenvalues in which case the Hessian becomes dominated by the diagonal matrix. This leads to an update which becomes the standard gradient divided by <em>α:</em></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/470/1*hFaAfBd1m1O_-d-D9OtyRQ.png" /></figure><p>Another problem restricting the use of Newton’s method is the computational cost. It takes <em>O</em>(<em>k</em>³) time to calculate the inverse of the Hessian where <em>k</em> is the number of parameters. It’s not uncommon for Deep Neural Networks to have about a million parameters and since the parameters are updated every iteration, this inverse needs to be calculated at every iteration, which is not computationally feasible.</p><ul><li><strong>Conjugate Gradients</strong>: One weakness of the method of steepest descent (i.e. GD) is that <a href="http://www.deeplearningbook.org/contents/numerical.html#pf7"><em>line searches</em></a> happen along the direction of the gradient. Suppose the previous search direction is <em>d</em>(t-1). Once the search terminates (which it does when the gradient along the current gradient direction vanishes) at the minimum, the next search direction, d(t) is given by the gradient at that point, which is orthogonal to d(t-1) (because if it’s not orthogonal, it’ll have some component along d(t-1) which cannot be true as at the minimum, the gradient along d(t-1) has vanished). <br>Upon getting the minimum along the current search direction, the minimum along the previous search direction is not preserved, undoing, in a sense, the progress made in previous search direction.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/483/1*CNCvsfwQ8GBVPDbnML1vng.png" /></figure><p>In the method of conjugate gradients, we seek a search direction that is conjugate to the previous line search direction:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/279/1*H-jNAiXmNRKa3NAJ5RS3dA.png" /><figcaption>Now, the previous search direction contributes towards finding the next search direction.</figcaption></figure><p>with <em>d</em>(t) and <em>d</em>(t-1) being <strong>conjugates</strong> if d(t)&#39; H d(t-1) = 0. βt decides how much of <em>d</em>(t-1) is added back to the current search direction. There are two popular choices for βt — Fletcher-Reeves and Polak-Ribière. These discussions assumed the cost function to be quadratic where the conjugate directions ensure that the gradient along the previous direction does not increase in magnitude. To extend the concept to work for training neural networks, there is one additional change. Since it’s no longer quadratic, there’s no guarantee anymore than the conjugate direction would preserve the minimum in the previous search directions. Thus, the algorithm includes occasional resets where the method of conjugate gradients is restarted with line search along the unaltered gradient.</p><ul><li><strong>BFGS: </strong>This algorithm tries to bring the advantages of Newton’s method without the additional computational burden by approximating the inverse of H by <em>M</em>(t), which is iteratively refined using low-rank updates. Finally, line search is conducted along the direction <em>M(t)g(t)</em>. However, BFGS requires storing the matrix <em>M(t)</em> which takes <em>O</em>(<em>n</em>²) memory making it infeasible. An approach called Limited Memory BFGS (L-BFGS) has been proposed to tackle this infeasibility by computing the matrix <em>M</em>(t) using the same method as BFGS but assuming that <em>M(t</em>−1) is the identity matrix.</li></ul><h4>4. Optimization Strategies and Meta-Algorithms</h4><ul><li><strong>Batch Normalization:</strong> Batch normalization (BN) is one of the most exciting innovations in Deep learning that has significantly stabilized the learning process and allowed faster convergence rates. The intuition behind batch normalization is as follows: Most of the Deep Learning networks are compositions of many layers (or functions) and the gradient with respect to one layer is taken considering the other layers to be constant. However, in practise all the layers are updated simultaneously and this can lead to unexpected results. For example, let y* = x W¹ W² … W¹⁰. Here, y* is a linear function of x but not a linear function of the weights. Suppose the gradient is given by <strong><em>g </em></strong>and we now intend to reduce y* by 0.1. Using first-order Taylor Series approximation, taking a step of <strong>ϵg </strong>would reduce y* by<strong> ϵg’ g. </strong>Thus, <strong>ϵ </strong>should be<strong> 0.1/(g’ g) </strong>just<strong> </strong>using the first-order information. However, higher order effects also creep in as the updated y* is given by:</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/428/1*YSJoF3TDLrA7UTasPOgjKQ.png" /></figure><p>An example of a second-order term would be <strong>ϵ² g</strong>1<strong> g</strong>2<strong> </strong>∏ <strong>w</strong>i. ∏ <strong>w</strong>i can be negligibly small or exponentially high depending on whether the individual weights are less than or greater than 1. Since the updates to one layer is so strongly dependent on the other layers, choosing an appropriate learning rate is tough. Batch normalization takes care of this problem by using an efficient reparameterization of almost any deep network. Given a matrix of activations, <strong>H</strong>, the normalization is given by: <strong>H’ = (H-μ) / σ</strong>, where the subtraction and division is <a href="https://docs.scipy.org/doc/numpy-1.13.0/user/basics.broadcasting.html"><em>broadcasted</em></a>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/343/1*KSsf0zMeSPVPjp1C82iIOA.png" /><figcaption>𝛿 is added to ensure that σ is not equal to 0.</figcaption></figure><p>Going back to the earlier example of y*, let the activations of layer <em>l </em>be given by <strong>h</strong>(<em>l</em>-1). Then <strong>h</strong>(<em>l</em>-1) = x <strong>W</strong>1 <strong>W</strong>2 … <strong>W</strong> (<em>l</em>-1). Now, if x is drawn from a unit Gaussian, then <strong>h</strong>(<em>l</em>-1) also comes from a Gaussian, however, not of zero mean and unit variance, as it is a linear transformation of x. BN makes it zero mean and unit variance. Therefore, y* = <strong>W</strong><em>l</em> <strong>h</strong>(<em>l</em>-1) and thus, the learning now becomes much simpler as the parameters at the lower layers mostly do not have any effect. This simplicity was definitely achieved by rendering the lower layers useless. However, in a realistic deep network with non-linearities, the lower layers remain useful. Finally, the complete reparameterization of BN is given by replacing <strong>H</strong> with <strong>γH’ + β</strong>. This is done to retain its expressive power and the fact that the mean is solely determined by <strong>XW</strong>. Also, among the choice of normalizating <strong>X</strong> or <strong>XW + B</strong>, the authors recommend the latter, specifically<strong> XW</strong>, since<strong> B </strong>becomes redundant because of<strong> β</strong>. Practically, this means that when we are using the Batch Normalization layer, the biases should be turned off. In a deep learning framework like <a href="http://keras.io/"><em>Keras</em></a>, this can be done by setting the parameter <em>use_bias=False </em>in the Convolutional layer<em>.</em></p><ul><li><strong>Coordinate Descent: </strong>Generally, a single weight update is made by taking the gradient with respect to every parameter. However, in cases where some of the parameters might be independent (discussed below) of the remaining, it might be more efficient to take the gradient with respect to those independent sets of parameters separately for making updates. Let me clarify that with an example. Suppose we have the following cost function:</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/750/1*crgxMCmeL7n0MWCR6tSf3Q.png" /></figure><p>This cost function describes the learning problem called sparse coding. Here, <strong><em>H</em></strong> refers to the sparse representation of <strong><em>X</em></strong> and <strong><em>W </em></strong>is the set of weights used to linearly decode <strong><em>H</em></strong> to retrieve <strong><em>X</em></strong>. An explanation of why this cost function enforces the learning of a sparse representation of <strong><em>X</em></strong> follows. The first term of the cost function penalizes values far from 0 (positive or negative because of the modulus, |<strong>H</strong>|, operator. This enforces most of the values to be 0, thereby <em>sparse</em>. The second term is pretty self-explanatory in that it compensates the difference between <strong><em>X</em> </strong>and <strong><em>H</em></strong> being linearly transformed by <strong><em>W</em></strong>, thereby enforcing them to take the same value. In this way, <strong><em>H </em></strong>is now learned as a sparse “representation” of<strong><em> X</em></strong>. The cost function generally consists of additionally a <a href="https://medium.com/inveterate-learner/deep-learning-book-chapter-7-regularization-for-deep-learning-937ff261875c"><em>regularization</em></a> term like <a href="https://medium.com/inveterate-learner/deep-learning-book-chapter-7-regularization-for-deep-learning-937ff261875c#e021"><em>weight decay</em></a><em>,</em> which has been avoided for simplicity. Here, we can divide the entire list of parameters into two sets, <strong><em>W</em></strong> and<strong><em> H</em></strong>. Minimizing the cost function with respect to any of these sets of parameters is a convex problem. <strong>Coordinate Descent (CD)</strong> refers to minimizing the cost function with respect to only 1 parameter at a time. It has been shown that repeatedly cycling through all the parameters, we are guaranteed to arrive at a local minima. If instead of 1 parameter, we take a set of parameters as we did before with <strong><em>W</em></strong> and <strong><em>H</em></strong>, it is called <strong>block coordinate descent </strong>(the interested reader should explore <a href="http://www.mit.edu/~rakhlin/6.883/lectures/lecture07.pdf"><em>Alternating Minimization</em></a>). CD makes sense if either the parameters are clearly separable into independent groups or if optimizing with respect to certain set of parameters is more efficient than with respect to others.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/248/1*FeihHwBCV0vGcCmbLxexgw.png" /><figcaption>The points A, B, C and D indicates the locations in the parameter space where coordinate descent landed after each gradient step. Source: <a href="https://www.researchgate.net/figure/Coordinate-Descent-CD-CD-algorithm-searches-along-one-coordinate-direction-in-each_fig2_262805949">https://www.researchgate.net/figure/Coordinate-Descent-CD-CD-algorithm-searches-along-one-coordinate-direction-in-each_fig2_262805949</a></figcaption></figure><p>Coordinate descent may <a href="https://www.deeplearningbook.org/contents/optimization.html#pf30"><em>fail terribly</em></a> when one variable influences the optimal value of another variable.</p><ul><li><strong>Polyak Averaging: </strong>Polyak averaging consists of averaging several points in the parameter space that the optimization algorithm traverses through. So, if the algorithm encounters the points <em>θ</em>(1), <em>θ</em>(2), … during optimization, the output of Polyak averaging is:</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/246/1*aua2WRoCMBAh1GvZTy4QFQ.png" /></figure><p>The figure below explains the intuition behind Polyak averaging:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/602/1*jI_RD6zNzXwTwIwe4AebOw.png" /><figcaption>The optimization algorithm might oscillate back and forth across a valley without ever reaching the minima. However, the average of those points should be closer to the bottom of the valley.</figcaption></figure><p>Most optimization problems in deep learning are non-convex where the path taken by the optimization algorithm is quite complicated and it might happen that a point visited in the distant past might be quite far from the current point in the parameter space. Thus, including such a point in the distant past might not be useful, which is why an exponentially decaying running average is taken. This scheme where the recent iterates are weighted more than the past ones is called <strong>Polyak-Ruppert Averaging</strong>:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/435/1*hWFvSOFbLBpWaXil4Vg59g.png" /></figure><ul><li><strong>Supervised Pre-training: </strong>Sometimes it’s hard to directly train to solve for a specific task. Instead it might be better to train for solving a simpler task and use that as an initialization point for training to solve the more challenging task. As an intuition for why this seems logical, consider that you didn’t have any background in integration and were asked to learn how to compute the following integral:</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/727/1*BduPga7CL9nGaCb-GY69vw.jpeg" /></figure><p>If you’re anyone close to a normal person, your first reaction would be:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/490/1*Tx-IbR4XwVb1FeKREFb_LQ.jpeg" /><figcaption>Source: <a href="https://imgflip.com/i/gdnbg">https://imgflip.com/i/gdnbg</a></figcaption></figure><p>However, wouldn’t it be better if you were asked to understand the more basic integrations first:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/374/1*kvE8hFWKsS0d5Yyh4XtHhg.gif" /></figure><p>I hope you understand what I meant with this example — learning a simpler task would put you in a better position to understand the more complex task. This particular strategy of training to solve a simpler task before facing the herculean one is called <strong>pretraining</strong>. A particular type of pretraining, called <strong>greedy supervised pretraining, </strong>firstly breaks a given supervised learning problem into simpler supervised learning ones and solving for the optimal version of each component in isolation. To build on the above intuition, the hypothesis as to why this works is that it gives better guidance to the intermediate layers of the network and helps in both, generalization and optimization. More often that not, the greedy pretraining is followed by a fine-tuning stage where all the parts are jointly optimized to search for the optimal solution to the full problem. As an example, the figure below shows how each hidden layer is trained one at a time, where the input to the hidden layer being learned is the output of the previously trained hidden layer.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/230/1*KG4XSeSIxUW4q-TeWbMjRA.png" /><figcaption>Greedy supervised pretraining (a) The first hidden layer is being trained only using the original inputs and outputs. (b) For training the second hidden layer, the hidden-output connection from the first hidden layer is removed and the output of the first hidden layer is used as the input.</figcaption></figure><p>Also, <a href="https://arxiv.org/abs/1412.6550"><strong>FitNets</strong></a><strong> </strong>shows an alternative way to guide the training process. Deep networks are hard to train mainly because as deeper the model gets, more non-linearities are introduced. The authors propose the use of a shallower and wider <strong>teacher</strong> network that is trained first. Then, a second network which is thinner and deeper, called the <strong>student</strong> network is trained to predict not only the final outputs but also the intermediate layers of the teacher network. For those who might not be clear with what deep, shallow, wide and thin might mean, refer the following diagram:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/872/1*KUYrZ7g-arLWxRbUWlBLsQ.png" /><figcaption>Explanation of the terms “shallow”, “deep”, “thin” and “wide” in the context of neural networks.</figcaption></figure><p>The idea is that predicting the intermediate layers of the teacher network provides some hints as to how the layers of the student network should be used and aids the optimization procedure. It was shown that without the hints to the hidden layers, the students networks performs poorly in both the training and test data.</p><ul><li><strong>Designing Models to Aid Optimization: </strong>Most of the work in deep learning has been towards making the models easier to optimize rather than designing a more powerful optimization algorithm. This is evident from the fact that <a href="https://medium.com/inveterate-learner/deep-learning-book-chapter-8-optimization-for-training-deep-models-part-i-20ae75984cb2#f1c7"><em>Stochastic Gradient Descent</em></a><em>,</em> which is primarily used for training deep models today, has been in use <a href="https://en.wikipedia.org/wiki/Stochastic_gradient_descent#Applications"><em>since the 1960s</em></a>. Many of the current design choices lend towards using linear transformations between layers and using activation functions like ReLU [max(0, x)] which are linear for the most part and enjoy large gradients as compared to sigmoidal units which saturate easily. Also, linear functions increase in a particular direction. Thus, if there’s an error, there’s a clear direction towards which the output should move to minimize the error.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/376/1*JCy4o3c6vs9jgAF35V0LOQ.png" /><figcaption>Source: <a href="https://arxiv.org/pdf/1512.03385.pdf">https://arxiv.org/pdf/1512.03385.pdf</a></figcaption></figure><p><a href="https://arxiv.org/pdf/1512.03385.pdf"><em>Residual connections</em></a><em> </em>reduce the length of the shortest path from the output to the lower layers, thereby allowing a larger gradient to flow through and hence, tackling the <a href="https://medium.com/inveterate-learner/deep-learning-book-chapter-8-optimization-for-training-deep-models-part-i-20ae75984cb2#6fd2"><em>vanishing gradient problem</em></a><em>. </em>Similarly, <a href="https://arxiv.org/pdf/1409.4842.pdf"><em>GoogleNet</em></a> attached multiple copies of the output to intermediate layers so that a larger gradient flows to those layers. Once training is complete, the auxiliary heads are removed<em>.</em></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*IktkDnerHBPlLCtEdwxlUQ.png" /><figcaption>Inception architecture with the outputs at the intermediate layers being marked.</figcaption></figure><ul><li><strong>Continuation Methods and Curriculum Learning: </strong>Based on the explanation given in the book (and also given that it’s fairly short), I’d recommend the interested reader to refer the <a href="http://www.deeplearningbook.org/contents/optimization.html#pf35"><em>book</em></a> directly. The reason being that I realized that the content there was exactly to the point with no further scope of summarizing and hence, found it redundant to explain it again here. To give a very brief idea, <strong>Continuation Methods </strong>are a family of strategies where instead of a single cost function, a series of cost functions are optimized to aid optimization by making sure that the algorithm spends most of the time in well-behaved regions in the parameter space. The series of cost functions are designed such that the cost functions become progressively harder to solve, i.e. the first cost function is easiest to solve and the final cost function (which is actually the cost function we wanted to minimize) is the toughest, and the solution to each easier cost function serves as a good initialization point for the next, harder-to-optimize cost function. <strong>Curriculum Learning</strong> can be interpreted as a type of continuation method where the learning process is planned such that the simpler concepts are learned first and then the harder ones which depend on those simpler concepts. This concept had been shown to accelerate progress in animal training. One simple way to use it in the context of machine learning is to initially show the algorithm more of the easier images and less of the harder images. As the learning progresses, the proportion of easier images is reduced and that of the harder images is increased so that the model can ultimately learn the harder task.</li></ul><p>This concludes the 2nd part of our summary for <a href="http://www.deeplearningbook.org/contents/optimization.html"><em>Chapter 8</em>.</a> This has been one of the most math intensive chapters that I have ever read and if you’ve made it this far, I have two things for ya: <em>Thank You</em> for taking the time out and <em>Congratulations</em>, as hopefully you have a much better clarity on what goes under the hood. Since Medium doesn’t support math symbols yet, a few of the mathematical notations were not proper and if you’re looking for a version with better notation, feel free to have a look over our repository <a href="https://github.com/dalmia/Deep-Learning-Book-Chapter-Summaries"><em>here</em></a><em> </em>which contains Jupyter Notebooks entailing the same content but with the symbols converted to LaTex<em>. </em>Our next post will be about <a href="http://www.deeplearningbook.org/contents/guidelines.html"><em>Chapter 11: Practical Methodology</em> </a>which focuses upon practical tips for making your Deep Learning model work. To stay updated with our posts, <a href="https://medium.com/inveterate-learner"><em>follow</em></a> our publication, <strong>Inveterate Learner</strong>. Finally, I thank my co-author, <a href="https://medium.com/u/6b3fcf7407c8">Ameya Godbole</a>, for thoroughly reviewing the post and suggesting many important changes. A special thanks to <a href="https://medium.com/u/314be6963dfe">Raghav Somani</a> for providing an in-depth review from a theoretical perspective that played an important role in the final shaping of this post.</p><blockquote>Patience is a virtue and I’m learning patience. It’s a tough lesson.</blockquote><blockquote>- Elon Musk</blockquote><blockquote>If there’s anything that you might want to share with me or give any sort of feedback on my writing/thoughts, I would love to hear it from you. Feel free to connect with me on <a href="https://www.linkedin.com/in/aman-dalmia">LinkedIn</a>, <a href="https://www.facebook.com/aman.dalmia.8">Facebook</a> or follow me on <a href="http://github.com/dalmia">Github</a>.</blockquote><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=438fb4f6d135" width="1" height="1" alt=""><hr><p><a href="https://medium.com/inveterate-learner/deep-learning-book-chapter-8-optimization-for-training-deep-models-part-ii-438fb4f6d135">Deep Learning Book: Chapter 8 — Optimization For Training Deep Models Part II</a> was originally published in <a href="https://medium.com/inveterate-learner">Inveterate Learner</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Deep Learning Book: Chapter 9— Convolutional Networks]]></title>
            <link>https://medium.com/inveterate-learner/deep-learning-book-chapter-9-convolutional-networks-45e43bfc718d?source=rss----ba6eaa0b1544---4</link>
            <guid isPermaLink="false">https://medium.com/p/45e43bfc718d</guid>
            <category><![CDATA[data-science]]></category>
            <category><![CDATA[machine-learning]]></category>
            <category><![CDATA[neural-networks]]></category>
            <category><![CDATA[convolutional-network]]></category>
            <category><![CDATA[deep-learning]]></category>
            <dc:creator><![CDATA[Ameya Godbole]]></dc:creator>
            <pubDate>Fri, 29 Jun 2018 11:41:24 GMT</pubDate>
            <atom:updated>2018-06-29T12:15:32.912Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/375/1*tE8dh8Zv0kc4e0xet41xYA.jpeg" /></figure><p><em>This is going to be a series of blog posts on the </em><a href="http://deeplearningbook.org/"><em>Deep Learning book</em></a><em> where </em><a href="https://medium.com/inveterate-learner"><em>we</em></a><em> are attempting to provide a summary of each chapter highlighting the concepts that we found to be the most important so that other people can use it as a starting point for reading the chapters, while adding further explanations on few areas that we found difficult to grasp. Please refer </em><a href="http://www.deeplearningbook.org/contents/notation.html"><em>this</em></a><em> for more clarity on notation</em>.</p><p>When discussing deep learning, two models have become the leading buzzwords — <em>Convolutional Neural Networks</em>, which are the topic of this post, and <em>Recurrent Neural Networks</em>, which will be discussed soon.</p><p>Convolutional networks are an example of the successful application of insights obtained by studying the brain. We will avoid reiteration, and direct the reader to a summary of the history of deep learning and how convolutional networks tie in, which can be found<em> </em><a href="http://www.deeplearningbook.org/contents/convnets.html#pf28"><em>at the end of this chapter</em></a>.</p><ul><li><a href="#bba5"><strong><em>The Convolution Operation</em></strong></a></li><li><a href="#8783"><strong><em>Motivation</em></strong></a></li><li><a href="#2a0e"><strong><em>Pooling</em></strong></a></li><li><a href="#0fc8"><strong><em>Convolution and Pooling as an Infinitely Strong Prior</em></strong></a></li><li><a href="#0301"><strong><em>Variants of the Basic Convolution Function</em></strong></a></li><li><a href="#5949"><strong><em>Structured Outputs</em></strong></a></li><li><a href="#a4f3"><strong><em>Data Types</em></strong></a></li><li><a href="#cc34"><strong><em>Efficient Convolution Algorithms</em></strong></a></li><li><a href="#7777"><strong><em>Random and Unsupervised Features</em></strong></a></li><li><a href="#f905"><strong><em>The Neuroscientific Basis for Convolutional Networks</em></strong></a></li></ul><h3>1. The Convolution Operation</h3><p>The convolution operates on the <strong>input</strong> with a <strong>kernel</strong> (weights) to produce an <strong>output map</strong> given by:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/193/0*4tNQephVyw6F05po.png" /><figcaption>Continuous domain convolution</figcaption></figure><p>Let us break down the formula. The steps involved are:</p><ol><li>Express each function in terms of a dummy variable τ</li><li>Reflect the function <em>g</em> i.e. <em>g(τ) →</em> <em>g(-τ)</em></li><li>Add a time offset i.e. <em>g(τ) </em>→ <em>g(t-τ). </em>Adding the offset shifts the input to the right by <em>t </em>units (by convention, a negative offset shits it to the left)</li><li>Multiply <em>f</em> and <em>g </em>point-wise and accumulate the results to get output at instant <em>t</em>. Basically, we are calculating the area of overlap between <em>f</em> and shifted <em>g</em></li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/713/1*4vS5AHKfjVzvTsIMBvGplQ.jpeg" /><figcaption>source: <a href="https://en.wikipedia.org/wiki/Convolution">https://en.wikipedia.org/wiki/Convolution</a></figcaption></figure><p>For our application, we are interested in the discrete domain formulation:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/203/0*ZVyL7CZSx8VxCa_-.png" /><figcaption>1-D discrete convolution</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/292/0*JYqqZagzPOW1z-mZ.png" /><figcaption>2-D discrete convolution</figcaption></figure><p>When the kernel is not flipped in its domain, we obtain the <strong>cross-correlation</strong> operation. The basic difference between the two operations is that convolution is commutative in nature, i.e. <em>f</em> and <em>g</em> can be interchanged without changing the output. Cross-correlation is not commutative. This difference is highlighted in the image below:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/512/0*6P8pXuW28a-qOpcr.png" /><figcaption>source: <a href="https://en.wikipedia.org/wiki/Convolution">https://en.wikipedia.org/wiki/Convolution</a></figcaption></figure><p>Although these equations imply that the <a href="https://en.wikipedia.org/wiki/Domain_of_a_function"><em>domains</em></a> for both <em>f </em>and<em> g </em>are infinite, in practice, these two variables are non-zero only in a finite region. As a result, the output is non-zero only in a finite region (where the non-zero regions of <em>f</em> and <em>g</em> overlap).</p><p>The intuition for convolution in 1-D can be extended to <em>n</em>-dimensions by nesting the convolution operations.<em> </em><a href="https://arxiv.org/pdf/1603.07285.pdf"><em>Vincent Dumoulin and Francesco Visin</em></a> provide an in depth analysis of how input and output shapes and computations are tied. Below is their visualization of a 2-D convolution operation:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/244/0*jL2-1xfsWaxIMdGW" /><figcaption>2D convolution (<a href="https://arxiv.org/abs/1603.07285">source</a>)</figcaption></figure><p>The 1D convolution operation can be represented as a matrix vector product. The kernel marix is obtained by composing weights into a <strong>Toeplitz matrix</strong>. A Toeplitz matrix has the property that values along all diagonals are constant.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/328/1*CcJxPjWTQdi49tYFDFRKXg.png" /><figcaption>The general structure of a Toeplitz matrix</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/290/1*uuEhpTFkgrcgBfOy7rWYsQ.png" /><figcaption>Using the Toeplitz matrix of the kernel for matrix-vector implementation of convolution</figcaption></figure><p>To extend this principle to 2D input, we first need to unroll the 2D input into a 1D vector. Once this is done, the kernel needs to be modified as before but this time resulting in a <strong>block-circulant matrix</strong>. What’s that?</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/396/1*JkIm8Q-XuPKzY_fJkcaZSw.png" /><figcaption>A general circulant matrix</figcaption></figure><p>A <strong>circulant matrix</strong> is a special case of a Toeplitz matrix where each row is a circular shift of the previous row. To see that it is a special case of the Toeplitz matrix is trivial.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/165/0*j0uFbJSm8_hpQ0ve.png" /><figcaption>A block circulant matrix (each Hi is a matrix)</figcaption></figure><p>A matrix which is circulant with respect to its sub-matrices is called a <strong>block circulant matrix</strong>. If each of the submatrices is itself circulant, the matrix is called <strong>doubly block-circulant matrix</strong>.</p><p>Now, given a 2D kernel, we can create the block-circulant matrix that will act allow matrix-vector implementation of convolution as below:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ECbJ2zn6ZngNaEwM5ihYSA.png" /><figcaption>Convince yourself that the resultant of convolving a 3x3 kernel on a 4x4 input (16x1 unrolled vector) results in a 2x2 output (4x1 vector) [refer to gif above] and hence the required kernel matrix must be of shape 4x16</figcaption></figure><h3>2. Motivation</h3><h4>Sparse Interactions</h4><p>Each output unit is connected to (affected by) only a subset of the input units.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/468/1*jkhJotQX3uz-Ja7QDOKQBg.png" /><figcaption>Sparse connectivity (upper) vs full connectivity (lower). The grey shaded nodes in the input show the receptive field of the node in the first layer (<a href="http://www.deeplearningbook.org/contents/convnets.html#pf7">source</a>)</figcaption></figure><p>If there are <strong><em>m</em></strong> input units and <strong><em>n</em></strong><em> </em>output units, a fully connected layer would require <strong><em>mn</em></strong> parameters (one per connection) and correspondingly the number of operations would scale as <strong><em>O(mn)</em></strong>. On the other hand, if each output unit is sparsely connected to <strong><em>k</em></strong> input units, the layer requires <strong><em>kn</em></strong> parameters and <strong><em>O(kn)</em></strong> computations. In general, for a convolutional layer, the number of output units are a function of kernel size, stride and padding (discussed later). This actually makes <strong><em>n</em></strong> a function of <strong><em>m</em></strong>. Keeping this in mind <strong><em>O(mn) ~ O(m²)</em></strong> while <strong><em>O(kn) ~ O(km)</em></strong>. By keeping <strong><em>k</em></strong> several orders of magnitude smaller than <strong><em>m</em></strong>, we see that the computational saving from sparse connections are huge.</p><p>As a practical example, consider a 3x3kernel operating on a black and white image of dimensions 224x224(this is a very standard setting of kernel size and image size, and can be seen in the first layer of the <a href="https://arxiv.org/abs/1409.1556"><em>VGGNet</em></a>). For same padding and stride as 1 (discussed in detail later), output size will also be 224x224. If this first layer were to be a fully connected layer, number of parameters would be <strong>~2.5 billion</strong> (=224² x 224²)<em>.</em> On the other hand, using a sparse layer with each output connected to 9(=3x3) inputs, the number of parameters is <strong>~451 thousand</strong> (=224² x 9). In fact, a convolutional layer also incorporates parameter sharing (see below) and this number will decrease further.</p><h4>Parameter Sharing</h4><p>In the previous section, we saw that the output units are only connected to a small number of input units. In a convolutional layer, each kernel weight is used at every input position (except maybe at boundaries where different padding rules apply as discussed <a href="#2a0e"><em>below</em></a>), i.e. parameters used to compute different output units are <strong>tied together</strong>. By tied together, we mean that at all times their values are same. This means that even during training, they are updated by the same amount and by collecting the gradients from all output units.</p><p>Parameter sharing allows models to capture local connectivity while simultaneously computing the same features at different spatial locations. We will see the use of this property soon.</p><p>Here we make a short detour to section 5 for discussing locally connected layers and tiled convolution.</p><ul><li><strong>Locally connected layer/unshared convolution</strong>: The connectivity graph of convolution operation and locally connected layer is the same. The only difference is that parameter sharing is not performed, i.e. each output unit performs a linear operation on its neighbourhood but the parameters are not shared across output units. This allows models to capture local connectivity while allowing different features to be computed at different spatial locations. This however requires much more parameters than the convolution operation.</li><li><strong>Tiled convolution</strong> is a sort of middle step between locally connected layer and traditional convolution. It uses a set of kernels that are cycled through. This reduces the number of parameters in the model while allowing for some freedom provided by unshared convolution.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/366/1*bL-Qe3d81Ne6TL-Y5AKKmg.png" /><figcaption>Comparison of connectivity and parameters of locally-connected (top), tiled (middle) and standard convolution (bottom) (<a href="http://www.deeplearningbook.org/contents/convnets.html#pf18">source</a>)</figcaption></figure><p>The parameter complexity and computation complexity can be obtained as below. Note that:</p><ul><li><strong><em>m</em></strong> = number of input units</li><li><strong><em>n</em></strong> = number of output units</li><li><strong><em>k</em></strong> = kernel size</li><li><strong><em>l</em></strong> = number of kernels in the set (for tiled convolution)</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/484/1*I_vXQolPQxQkrJnsECYZgg.png" /></figure><p>You can see now that the quantity of <strong>~451 thousand</strong> parameters corresponds to the locally connected convolution operation. If we use a set of 200 kernels, the number of parameters for tiled convolution is <strong>1.8 thousand</strong>. For a traditional convolution operation, this number is <strong>9</strong> parameters.</p><h4>Equivariance</h4><blockquote>A function <strong><em>f</em></strong> is said to be equivariant to a function <strong><em>g</em></strong> if</blockquote><blockquote><strong>f<em>(</em>g<em>(x)) = </em>g<em>(</em>f<em>(x))</em></strong></blockquote><blockquote>i.e. if input changes, the output changes in the same way.</blockquote><p>Parameter sharing in a convolutional network provides <strong>equivariance to translation</strong>. What this means is that translation of the image results in corresponding translation in the output map (except maybe for boundary pixels). The reason for this is very intuitive: the same feature is being computed at all input points.</p><p>Note that convolution operation by itself is <strong>not equivariant to changes in scale or rotation</strong>. I’ve added a code snippet to demonstrate this. See the figure below that for more clarity on this:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/d91cede84f6073fea96a17701db9d44f/href">https://medium.com/media/d91cede84f6073fea96a17701db9d44f/href</a></iframe><figure><img alt="" src="https://cdn-images-1.medium.com/max/1008/1*wDoSGSKXaoQ5F5nYV_m3ew.png" /><figcaption>The output of a random 5x5 kernel on an image and its affine transforms is demonstrated. Note that the histogram difference plots represent <strong>point-wise absolute difference</strong> between the outputs of convolution applied to translated, rotated and scaled inputs and the corresponding transformation applied to the output of convolution on the original image. This demonstrates the equivariance to translation but not to rotation and scaling.</figcaption></figure><h3>3. Pooling</h3><p>A convolutional layer can be broken down into the following components:</p><ul><li>Convolution</li><li>Activation (detector stage)</li><li>Pooling</li></ul><p>The pooling function calculates a <strong>summary statistic</strong> of the nearby pixels at the point of operation. Some common statistics are max, mean, weighted average and <em>L²</em> norm of a surrounding rectangular window.</p><p>Pooling makes the representation slightly <strong>translation invariant</strong>, in that small translations in the input do not cause large changes in the output map. It allows detection of a particular feature if we only care about its existence, not its position in an image.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/5f5c7ca8a83ba170e02dc47da13177a8/href">https://medium.com/media/5f5c7ca8a83ba170e02dc47da13177a8/href</a></iframe><figure><img alt="" src="https://cdn-images-1.medium.com/max/720/1*zO6y6t5O_iUrmWnhWwPfCA.png" /><figcaption>For a 200x200 input image, notice the difference between the pooling outputs for 3 layers. The model used is 3 stages of <strong>conv[5x5] + pool[2x2] + sigmoid</strong>. kernel[1,2,3] are the three 5x5 convolution kernels used. pool1_[1,2,3] are the pooling stage outputs after each convolution on the original image. Similarly, pool2_[1,2,3] are the pooling stage outputs after each convolution on the shifted image. Note that input has been shifted by 15 pixels for the demonstration. The histograms represent the distribution of absolute difference between corresponding pooling stages, i.e. abs(pool1_1-pool2_1), abs(pool1_2-pool2_2), abs(pool1_3-pool2_3)</figcaption></figure><p>Pooling over feature channels can be used to develop <strong>invariance to certain transformations</strong> of the input. For e.g., units in a layer may be developed to learn rotated features and then pooled over. This property has been used in <a href="http://proceedings.mlr.press/v28/goodfellow13.pdf"><strong><em>Maxout networks</em></strong></a>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/441/1*n2TTA8pW88LQU03CVutNOQ.png" /><figcaption>Pooling over feature channels allows the model to become invariant to transformations of the input (<a href="http://www.deeplearningbook.org/contents/convnets.html#pf9">source</a>)</figcaption></figure><p>Pooling reduces the input size to the next layer in turn reducing the number of computations required upstream. Variable sized inputs are an issue when presented to a fully connected layer. To counter this, the pooling operation maybe performed on <strong>regions of the input</strong> (such as quadrants) thus allowing the model to work on variable sized inputs.</p><p><a href="http://www.di.ens.fr/willow/pdfs/icml2010b.pdf"><strong><em>Theoretical guidelines</em></strong></a> for which pooling to use have been studied. <a href="http://yann.lecun.com/exdb/publis/pdf/boureau-iccv-11.pdf"><strong><em>Dynamic pooling</em></strong></a> has also been studied.</p><h3>4. Convolution and Pooling as an Infinitely Strong Prior</h3><h4>What is a weight prior?</h4><p>Assumptions about the weights (before learning) in terms of acceptable values and range are encoded into the <strong>prior</strong> distribution of the weights. A <strong>weak prior</strong> is has a high variance and shows that there is low confidence in the initial value of the weight. A <strong>strong prior</strong> is turn shows a narrow range of values about which we are confident before learning begins. An <strong>infinitely strong prior</strong> demarkates certain values as forbidden completely assigning them zero probability.</p><p>If we view the convolutional layer as a fully connected layer, <strong>convolution imposes an infinitely strong prior</strong> by making the following restrictions on the weights:</p><ul><li>Adjacent units must have the same weight but shifted in space.</li><li>Except for a small spatially connected region, all other weights must be zero.</li></ul><p>Likewise the <strong>pooling stage imposes an infinitely strong prior</strong> by requiring features to be translation invariant.</p><h4>Insights:</h4><ul><li>Convolution and pooling can cause underfitting if the priors imposed are not suitable for the task. As an example, consider this scenario. We may want to learn different features for different parts of an input. But the compulsion to used tied weights (enforced by standard convolution) on all parts of an image, forces us to either compromise or use more kernels (extract more features).</li><li>Convolutional models should only be compared with other convolutional models. This is because other models which are <strong>permutation invariant</strong> can learn even when input features are permuted (thus loosing spatial relationships). Such models need to learn these spatial relationships (which are hard-coded in CNNs).</li></ul><h3>5. Variants of the Basic Convolution Function</h3><p>In practical implementations of the convolution operation, certain modifications are made which deviate from the discrete convolution formula mentioned above:</p><ul><li>In general a convolution layer consists of application of several different kernels to the input. This allows the extraction of several different features at all locations in the input. This means that in each layer, a single kernel (filter) isn’t applied. Multiple kernels (filters), usually a power of 2, are used as different feature detectors.</li><li>The input is generally not real-valued but instead vector valued (e.g. RGB values at each pixel or the feature values computed by the previous layer at each pixel position). Multi-channel convolutions are commutative only if number of output and input channels is the same.</li><li>In order to allow for calculation of features at a <strong>coarser level</strong> <em>strided convolutions</em> can be used. The effect of strided convolution is the same as that of a convolution followed by a downsampling stage. This can be used to reduce the representation size.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/294/0*heq9G8um8RY2vRvG.gif" /><figcaption>2D convolution 3x3 kernel and stride of 2 units (<a href="https://arxiv.org/abs/1603.07285">source</a>)</figcaption></figure><ul><li>Zero padding helps to make output dimensions and kernel size independent. 3 common zero padding strategies are:</li></ul><ol><li><strong>valid</strong>: The output is computed only at places where the entire kernel lies inside the input. Essentially, no zero padding is performed. For a kernel of size <strong>k</strong> in any dimension, the input shape of <strong>m</strong> in the direction will become <strong>m-k+1</strong> in the output. This shrinkage restricts architecture depth.</li><li><strong>same</strong>: The input is zero padded such that the spatial size of the input and output is same. Essentially, for a dimension where kernle size is <strong>k</strong>, the input is padded by <strong>k-1</strong> zeros in that dimension. Since the number of output units connected to border pixels is less than that for centre pixels, it may under-represent border pixels.</li><li><strong>full</strong>: The input is padded by enough zeros such that each input pixel is connected to the same number of output units.<br>In terms of test set accuracy, the optimal padding is somewhere between <em>same</em> and <em>valid.</em></li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/294/1*BMngs93_rm2_BpJFH2mS0Q.gif" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/395/1*1okwhewf5KCtIPaFib4XaA.gif" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/495/1*hOI0jW3CcS_yuxcmJIYjKw.gif" /><figcaption><strong>valid</strong>(left), <strong>same</strong>(middle) and <strong>full</strong>(right) padding (<a href="https://arxiv.org/abs/1603.07285">source</a>). The extreme left one is for stride=2.</figcaption></figure><ul><li>Besides locally-connected layers and tiled convolution, another extension can be to restrict the kernels to operate on certain input channels. One way to implement this is to connect the first <strong>m</strong> input channels to the first <strong>n</strong> output channels, the next <strong>m</strong> input channels to the next <strong>n</strong> output channels and so on. This method decreases the number of parameters in the model without dereasing the number of output units.</li><li>When max pooling operation is applied to locally connected layer or tiled convolution, the model has the ability to become <strong>transformation invariant</strong> because adjacent filters have the freedom to learn a transformed version of the same feature. <em>This essentially similar to the property leveraged by pooling over channels rather than spatially</em>.</li><li><strong>Bias</strong> terms can be used in different ways in the convolution stage. For locally connected layer and tiled convolution, we can use a bias per output unit and kernel respectively. In case of traditional convolution, a single bias term per output channel is used. <em>If the input size is fixed, a bias per output unit may be used to counter the effect of regional image statistics and smaller activations at the boundary due to zero padding</em>.</li></ul><h3>6. Structured Outputs</h3><p>Convolutional networks can be trained to output high-dimensional structured output rather than just a classification score. A good example is the task of image segmentation where each pixel needs to be associated with an object class. Here the output is the same size (spatially) as the input. The model outputs a tensor <strong><em>S</em></strong> where <strong><em>S[i,j,k]</em></strong> is the probability that pixel <strong>(j,k)</strong> belongs to class <strong>i</strong>.</p><p>To produce an output map as the same size as the input map, only <strong>same-padded</strong> convolutions can be stacked. Alternatively, a coarser segmentation map can be obtained by allowing the output map to shrink spatially.</p><p>The output of the first labelling stage can be refined successively by another convolutional model. If the models use tied parameters, this gives rise to a type of <strong>recursive model</strong> as shownbelow. (H¹, H², H³ share parameters)</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/343/1*Pxwx6LIzJ4d5e6wVXzl_Pw.png" /><figcaption>Recursive refinement of the segmentation map</figcaption></figure><p>The output can be further processed under the assumption that contiguous regions of pixels will tend to belong to the same label. Graphical models can describe this relationship. Alternately, <a href="https://www.robots.ox.ac.uk/~vgg/rg/papers/tompson2014.pdf"><em>CNNs can learn to optimize the graphical models training objective</em></a>.</p><p>Another model that has gained popularity for segmentation tasks (especially in the medical imaging community) is the<em> </em><a href="https://arxiv.org/abs/1505.04597"><em>U-Net</em></a>. The <em>up-convolution</em> mentioned is just a direct upsampling by repetition followed by a convolution with <em>same padding</em>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/678/1*Sm8pd0_peRxhzZ2pnQ63rg.png" /><figcaption>U-Net architecture for medical image segmentation (<a href="https://www.researchgate.net/publication/321251358_Deep_Learning-based_Inpainting_for_Virtual_DSA/figures?lo=1&amp;utm_source=google&amp;utm_medium=organic"><em>source</em></a>)</figcaption></figure><h3>7. Data Types</h3><blockquote>The data used with a convolutional network usually consist of several channels, each channel being the observation of a different quantity at some point in space or time.</blockquote><blockquote>One advantage to convolutional networks is that they can also process inputs with varying spatial extents.</blockquote><p>When the output is accordingly variable sized, no extra design change needs to be made. If however the output is fixed sized, as in the classification task, a pooling stage with kernel size proportional to the input size needs to be used.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/965/1*gHDzzPhtF8k0_YIPTdz4CA.png" /><figcaption>Different data types based on the number of spatial dimensions and channels</figcaption></figure><h3>8. Efficient Convolution Algorithms</h3><p>In some problem settings, performing convolution as pointwise multiplication in the frequency domain can provide a speed up as compared to direct computation. This is a result from the property of convolution:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/292/1*-XVHHLEmEhghxoGkc64Trg.png" /><figcaption>Convolution in the source domain is multiplication in the frequency domain. F is the transformation operation</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/529/1*8CHbRG7F0nDgLCJnT97asw.png" /></figure><p>When a <strong>d</strong>-dimensional kernel can be broken into the outer product of <strong>d</strong> vectors, the kernel is said to be separable. The corresponding convolution operations are more efficient when implemented as <strong>d</strong> 1-dimensional convolutions rather than a direct <strong>d</strong>-dimensional convolution. Note however, it may not always be possible to express a kernel as an outer product of lower dimensional kernels.</p><p>This is not to be confused with <strong>depthwise separable convolution</strong> (explained brilliantly <a href="https://www.youtube.com/watch?v=T7o3xvJLuHk"><em>here</em></a>). This method restricts convolution kernels to operate on only one input channel at a time followed by 1x1 convolutions on all channels of the intermediate output.</p><blockquote>Devising faster ways of performing convolution or approximate convolution without harming the accuracy of the model is an active area of research.</blockquote><h3>9. Random and Unsupervised Features</h3><p>To reduce the computational cost of training the CNN, we can use features not learned by supervised training.</p><ol><li><strong>Random initialization</strong> has been shown to create filters that are <a href="http://www.robotics.stanford.edu/~ang/papers/nipsdlufl10-RandomWeights.pdf"><em>frequency selective and translation invariant</em></a>. This can be used to inexpensively select the model architecture. Randomly initialize several CNN architectures and just train the last classification layer. Once a winner is determined, that model can be fully trained in a supervised manner.</li><li><strong>Hand designed kernels</strong> may be used; e.g. to detect edges at different orientations and intensities.</li><li><strong>Unsupervised training</strong> of kernels may be performed; e.g. <a href="https://www-cs.stanford.edu/people/ang/papers/nipsdlufl10-AnalysisSingleLayerUnsupervisedFeatureLearning.pdf"><em>applying k-means clustering to image patches</em></a> and using the centroids as convolutional kernels. <em>Unsupervised pre-training may offer regularization effect (not well established)</em>. It may also allow for training of larger CNNs because of reduced computation cost.</li></ol><p>Another approach for CNN training is <strong>greedy layer-wise pretraining</strong> most notably used in <a href="https://ai.stanford.edu/~ang/papers/icml09-ConvolutionalDeepBeliefNetworks.pdf"><em>convolutional deep belief network</em></a>. For example, in the case of multi-layer perceptrons, starting with the first layer, each layer is trained in isolation. Once the first layer is trained, its output is stored and used as input for training the next layer, and so on.</p><h3>10. The Neuroscientific Basis for Convolutional Networks</h3><p>Hubel and Wiesel studied the activity of neurons in a cat’s brain in response to visual stimuli. Their work characterized many aspects of brain function.</p><p>In a simplified view, we have:</p><ol><li>The light entering the eye stimulates the <strong>retina</strong>. The image then passes through the the optic nerve and a region of the brain called the <strong>LGN (lateral geniculate nucleus)</strong></li><li><strong>V1 (primary visual cortex)</strong>: The image produced on the retina is transported to the V1 with minimal processing. The properties of V1 that have been replicated in CNNs are:</li></ol><ul><li>The V1 response is localized spatially, i.e. the upper image stimulates the cells in the upper region of V1 <strong>[localized kernel]</strong>.</li><li>V1 has simple cells whose activity is a linear function of the input in a small neighbourhood <strong>[convolution]</strong>.</li><li>V1 has complex cells whose activity is invariant to shifts in the position of the feature <strong>[pooling]</strong> as well as some changes in lighting which cannot be captured by spatial pooling <strong>[cross-channel pooling]</strong>.</li></ul><p>3. There are several stages of V1 like operations <strong>[stacking convolutional layers]</strong>.</p><p>4. In the <strong>medial temporal lobe</strong>, we find <strong>grandmother cells</strong>. These cells respond to specific concepts and are invariant to several transforms of the input. In the <strong>medial temporal lobe</strong>, researchers also found neurons spiking on a particular concept, e.g. the <strong>Halle Berry neuron</strong> fires when looking at a photo/drawing of Halle Berry or even reading the text Halle Berry. Of course, there are neurons which spike at other concepts like Bill Clinton, Jennifer Aniston, etc.</p><p>The medial temporal neurons are more generic than CNN in that they respond even to specific ideas. A closer match to the function of the last layers of a CNN is the <strong>IT (inferotemporal cortex)</strong>. When viewing an object, information flows from the retina, through LGN, V1, V2, V4 and reaches IT. This happens within 100ms. When a person continues to look at an object, the brain sends top-down feedback signals to affect lower level activation.</p><p>Some of the major differences between the human visual system (HVS) and the CNN model are:</p><ul><li>The human eye is low resolution except in a region called <strong>fovea</strong>. Essentially, the eye does not receive the whole image at high resolution but stiches several patches through eye movements called <strong>saccades</strong>. This attention based gazing of the input image is an active research problem. <em>Note:</em> attention mechanisms have been shown to work on natural language tasks.</li><li>Integration of several senses in the HVS while CNNs are only visual.</li><li>The HVS processes rich 3D information, and can also determine relations between objects. CNNs for such tasks are in their early stages.</li><li>The feedback from higher levels to V1 has not been incorporated into CNNs with substantial improvement.</li><li>While the CNN can capture firing rates in the IT, the similarity between intermediate computations is not established. The brain probably uses different activation and pooling functions. Even the linearity of filter response is doubtful as recent models for V1 involve quadratic filters.</li></ul><p>Neuroscience tells us very little about the training procedure. Backpropogation which is a standard training mechanism today is not inspired by neuroscience and sometimes considered biologically implausible.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/344/0*zpJyaBciQiOa_dQs.png" /><figcaption>The heatmap of a 2D Gabor filter (<a href="https://en.wikipedia.org/wiki/Gabor_filter">source</a>)</figcaption></figure><p>In order to determine the filter parameters used by neurons, a process called <strong>reverse correlation</strong> is used. The neuron activations are measured by an electrode when viewing several white noise images and a linear model is used to approximate this behaviour. It has been shown experimentally that the weights of the fitted model of V1 neurons are described by <strong>Gabor functions</strong>. If we go by the simplified version of the HVS, if the simple cells detect Gabor-like features, then complex cells learn a function of simple cell outputs which is invariant to certain translations and magnitude changes.</p><p>A wide variety of statistical learning algorithms (from unsupervised (sparse code) to deep learning (first layer features)) learn features with Gabor-like functions when applied to natural images. This goes to show that while no algorithm can be touted as the <strong>right method</strong> based on Gabor-like feature detectors, a <strong>lack</strong> of such features may be taken as a <strong>bad sign</strong>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/983/1*Am2tW0yrzJan-5PT8sXpeQ.png" /><figcaption>(Left) Gabor functions with diﬀerent values of the parameters that control the coordinate system. (Middle) Weights learned by an unsupervised learning algorithm (Right) Convolution kernels learned by the ﬁrst layer of a fully supervised convolutional maxout network.</figcaption></figure><p>This concludes our discussion on one of the most important architectures that has caused a series of advancements in AI as described in <a href="http://www.deeplearningbook.org/contents/convnets.html"><em>Chapter 9</em></a>. We hope that this gave you a good understanding of the basics of convolution, CNNs and the various tweaks that have been made to improve its performance. We’re sure that if you understand this post thoroughly, you won’t have a lot of difficulty in understanding various papers on CNNs. To stay updated with our posts, <a href="https://medium.com/inveterate-learner"><em>follow</em></a> our publication, <strong>Inveterate Learner</strong>. If you’re looking for the summary of previous chapters or are more comfortable reading from a Jupyter Notebook, feel free to have a look over our repository <a href="https://github.com/dalmia/Deep-Learning-Book-Chapter-Summaries"><em>here</em></a>.</p><blockquote>I think it’s important to reason from first principles rather than by analogy. With analogy, we are doing a thing because it’s like something else that was done by other people. With first principles, you boil things down to the most fundamental truths and then reason up from there.</blockquote><blockquote>- Elon Musk</blockquote><blockquote>If there’s anything that you might want to share with me or give any sort of feedback on my writing/thoughts, I would love to hear it from you. Feel free to connect with me on <a href="https://in.linkedin.com/in/ameyag416">LinkedIn</a>, <a href="https://www.facebook.com/ameya.godbole.58">Facebook</a> or follow me on <a href="https://github.com/ameyagodbole">Github</a>.</blockquote><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=45e43bfc718d" width="1" height="1" alt=""><hr><p><a href="https://medium.com/inveterate-learner/deep-learning-book-chapter-9-convolutional-networks-45e43bfc718d">Deep Learning Book: Chapter 9— Convolutional Networks</a> was originally published in <a href="https://medium.com/inveterate-learner">Inveterate Learner</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Deep Learning Book: Chapter 8— Optimization For Training Deep Models Part I]]></title>
            <link>https://medium.com/inveterate-learner/deep-learning-book-chapter-8-optimization-for-training-deep-models-part-i-20ae75984cb2?source=rss----ba6eaa0b1544---4</link>
            <guid isPermaLink="false">https://medium.com/p/20ae75984cb2</guid>
            <category><![CDATA[deep-learning-book]]></category>
            <category><![CDATA[deep-learning]]></category>
            <category><![CDATA[neural-networks]]></category>
            <category><![CDATA[machine-learning]]></category>
            <category><![CDATA[optimization]]></category>
            <dc:creator><![CDATA[Aman Dalmia]]></dc:creator>
            <pubDate>Sat, 16 Jun 2018 05:53:41 GMT</pubDate>
            <atom:updated>2018-06-30T10:27:17.971Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/375/1*tE8dh8Zv0kc4e0xet41xYA.jpeg" /></figure><p><em>This is going to be a series of blog posts on the </em><a href="http://deeplearningbook.org/"><em>Deep Learning book</em></a><em> where </em><a href="https://medium.com/inveterate-learner"><em>we</em></a><em> are attempting to provide a summary of each chapter highlighting the concepts that we found to be the most important so that other people can use it as a starting point for reading the chapters, while adding further explanations on few areas that we found difficult to grasp. Please refer </em><a href="http://www.deeplearningbook.org/contents/notation.html"><em>this</em></a><em> for more clarity on notation</em>.</p><p>There are many types of optimization problems involved in deep learning, with the toughest one being that of <em>training</em> a neural network. The main theme of the chapter is to focus on one type of optimization — finding the parameters <strong><em>θ</em></strong> that reduce a cost function <strong><em>J</em>(<em>θ</em>)</strong>.</p><p>Since this is a very math intensive chapter, in order to make concepts crystal clear, explanations are required at a lot of places. To avoid making this post too long, we are presenting the summary in two parts. We do not want to compromise on the main goal which is to make Deep Learning accessible to the largest audience possible. The sections of the chapter presented in this part are listed below:</p><ul><li><a href="#bc1e"><strong><em>How Learning Differs from Pure Optimization</em></strong></a></li><li><a href="#d8ca"><strong><em>Challenges in Neural Network Optimization</em></strong></a></li><li><a href="#f1c7"><strong><em>Basic Algorithms</em></strong></a></li></ul><h4>1. <strong><em>How Learning Differs from Pure Optimization</em></strong></h4><ul><li>In Machine Learning (ML), we care about a certain performance measure (say <em>P, </em>for e.g. accuracy) defined w.r.t the test set and optimize <strong><em>J</em>(<em>θ</em>) </strong>(for e.g. cross-entropy loss) with the <em>hope</em> that it improves <em>P</em> as well. In pure optimization, optimizing <strong><em>J</em>(<em>θ</em>) </strong>is the final goal.</li><li>The expected <em>generalization error</em> (<strong>risk</strong>) is taken over the true data-generating distribution <em>p_data</em>. If we do have that, it becomes an optimization problem.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/356/1*q2SniUi60DkdBxIuCpca0Q.png" /><figcaption>Notice how the expectation is taken over the true data generating distribution.</figcaption></figure><p>When we don’t have <em>p_data</em> but a finite training set, we have a ML problem. The latter can be converted back to an optimization problem by replacing <em>p_data</em> with the empirical distribution with p<em>̂_data </em>obtained from the training set, thereby reducing the <em>empirical risk</em>. This is called <em>empirical risk minimization</em> (ERM):</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/980/1*oev5_GHnjUPDymCoENksIw.png" /><figcaption>Notice the change in distribution over which the expectation is taken.</figcaption></figure><p>Although this might look relatively similar to optimization, there are two main problems. Firstly, ERM is prone to overfitting with the possibility of the dataset being learned by high capacity models (models with the ability to learn extremely complex functions). Secondly, ERM might not be feasible. Most optimization algorithms now are based on <em>Gradient Descent</em> (GD) which requires a derivative calculation and hence, may not work with certain loss functions like the 0–1 loss (as it is not differentiable).</p><ul><li>It is for the reasons mentioned above that a <strong>surrogate loss function </strong>(SLF) is used instead, that acts as a proxy. For e.g. the <em>negative log-likelihood</em> of the true class is used as a surrogate for 0–1 loss. I’ve added a <em>code snippet</em> below that would help you understand why 0–1 loss won’t work for Gradient Descent but cross-entropy, being a smooth function, would.</li></ul><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/0f858e6c8a01d9894dd5b85f5059e6ec/href">https://medium.com/media/0f858e6c8a01d9894dd5b85f5059e6ec/href</a></iframe><figure><img alt="" src="https://cdn-images-1.medium.com/max/432/1*vV0YrjmWvA5zsvI_BYAYIg.png" /><figcaption>It can be seen that the 0–1 loss is a non-differentiable function and hence, not compatible with gradient-based algorithms like Gradient Descent. Cross-entropy is a smooth approximation of the 0–1 loss.</figcaption></figure><p>Using a SLF might even turn out to be beneficial as you can keep continuing to obtain a better test error by pushing the classes even further apart to get a more reliable classifier. By this, I mean that suppose we were using a 0–1 loss with a threshold of, say, 0.5 to assign each class. Here, in case the true class is 1, our model would have no motivation to push the prediction score close to 1 once it’s able to get it above 0.5. However, using cross-entropy, since we are using the raw prediction scores, the model keeps trying to push the prediction closer to the true class.</p><ul><li>Another common difference is that training might be halted following some convergence criterion based on Early Stopping to prevent overfitting, when the derivative of the surrogate loss function might still be <em>large</em>. This is different from pure optimization which is halted only when the derivative becomes very small. If you’re not familiar with Early Stopping, I’d recommend you to look at <a href="https://medium.com/inveterate-learner/deep-learning-book-chapter-7-regularization-for-deep-learning-937ff261875c"><em>our previous post</em></a> where we talk about Early Stopping and other regularization techniques.</li><li>In ML optimization algorithms, the objective function decomposes as a sum over the examples and we can perform updates by randomly sampling a batch of examples and taking the average over the examples in that batch. If we consider <em>n</em> random variables, each having the true mean given by <strong>μ</strong>, the Standard Error (S.E.) of the mean <em>estimated</em> from those <em>n</em> random variables(see <a href="https://github.com/dalmia/Deep-Learning-Book-Chapter-Summaries"><em>Appendix</em></a><em> </em>for derivation) is given as follows:</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/256/1*trW6cCW0zhLqQVIuyVM0Fg.png" /></figure><p>This indicates that as we include more examples for making an update, the <em>returns</em> of additional examples in improving the error is <em>less than linear</em>. Thus, if we use 100 and 10000 examples separately to make an update, the latter takes 100 times more compute, but reduces the error only by a factor of 10. Thus, it’s better to compute <em>rapid approximate updates</em> rather than a <em>slow exact update</em>.</p><ul><li>There are 3 types of sampling based algorithms — <em>batch</em> gradient descent (BGD), where the <strong>entire</strong> training set is used to make a single update, <em>stochastic</em> gradient descent (SGD), where a <strong>single</strong> example is used to make a weight update and <em>mini-batch</em> gradient descent (MBGD), where a batch (not to be confused with BGD) of examples is randomly sampled from the entire training set and is used to make an update. <em>Mini-batch GD is nowadays commonly referred to as Stochastic GD.</em></li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Fb3uGEhdG3Sw_e7mGQ8oMw.jpeg" /><figcaption>Taken from Andrew Ng’s Machine Learning <a href="https://www.youtube.com/watch?v=SPZALjgkxaw">course</a>. Here, as mentioned above, mini-batch gradient descent has been presented as stochastic gradient descent.</figcaption></figure><p>It is a common practise to use batch sizes of powers of 2 to offer better run-time with certain hardware. Small batches tend to have a regularizing effect because of the noise they inject as each update is made by seeing only a very small portion of the entire training set, a.k.a. a batch of samples.</p><ul><li>The mini-batches should be selected randomly. It is sufficient to shuffle the dataset once and iterate over it multiple times. In the first epoch, the network sees each example for the first time and hence, the estimate of gradient is an <em>unbiased</em> estimate of the gradient of the true generalization error. However, from the second epoch onward, the estimate becomes biased as it is re-sampling from data that it has already seen. Such a sampling algorithm is called Random Reshuffling and although their analysis even for generalized linear models, which are strongly convex, is an open problem till date, reasonable efforts have been made to show that this biased estimate of the gradient is decent enough (at least as good as i.i.d. based Batch SGD).</li></ul><h4>2. <strong><em>Challenges in Neural Network Optimization</em></strong></h4><p>The optimization problem for training neural networks is generally<a href="https://www.cs.ubc.ca/labs/lci/mlrg/slides/non_convex_optimization.pdf"> non-convex</a>. Some of the challenges faced are mentioned below:</p><ul><li><strong>Ill-conditioning of the Hessian Matrix</strong>: The Hessian matrix and condition number have been covered in our <a href="https://github.com/dalmia/Deep-Learning-Book-Chapter-Summaries/blob/master/Chapter%208%20-%20Optimization%20for%20Training%20Deep%20Models.ipynb"><em>summary</em></a> for Chapter 4. For the sake of completion, the Hessian matrix <strong>H </strong>of a function <strong><em>f</em></strong> with a vector-valued input<strong> <em>x</em> </strong>is given as:</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/524/1*aMQ5zgbdIMAKIZR4nWGM0A.png" /><figcaption>Source: <a href="https://en.wikipedia.org/wiki/Hessian_matrix">https://en.wikipedia.org/wiki/Hessian_matrix</a></figcaption></figure><p>The ill-conditioning of <strong>H</strong> (defined below) can cause the SGD to get stuck in a sense that even very small steps may increase the cost function. A more rigorous explanation of this, added by <a href="https://medium.com/u/314be6963dfe">Raghav Somani</a> is given next.</p><blockquote>Assuming local convexity, another way of looking at ill-conditioned Hessian is by considering its eigenvalues. Condition number of the Hessian is high if the largest positive eigenvalue of the local Hessian is too large, or when the lowest eigenvalue of the Hessian is very close to zero. It can be shown that the optimal step size is less than the inverse of the local smoothness constant of the function (smoothness, is informally proportional to the largest eigenvalue), so for the former case, if the largest eigenvalue of the Hessian is very large, the step-size required needs to be extremely small (leading to slow convergence). On the other hand, if the least eigenvalue is extremely small, then we again encounter slow convergence due to lack of enough convexity.</blockquote><blockquote>If local convexity is not assumed, it gets difficult to say just via first order optimization methods if we are converging to a saddle point or to a local minima.</blockquote><p>In Chapter 4, it was shown that moving by a factor of <strong><em>ϵg </em></strong>would <em>add</em> the term given below to the <em>cost</em> function:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/430/1*JzEe84rFItn9T32AwUB8yQ.png" /><figcaption>Derived using the Taylor Series Expansion</figcaption></figure><p><strong>Ill-conditioning</strong> is said to happen when the first term exceeds the second term as then the cost would be increasing. In many cases, the gradient might be large leading to a large gradient norm (i.e. <strong>g’g</strong>). However, <strong>g’Hg</strong> might be even larger than the gradient norm. This would lead to slower learning as we would need to reduce the learning rate to make the first term lower than the second. To clarify more on this, since the first term contains the 2nd power of <strong><em>ϵ</em></strong>, and<strong><em> ϵ </em></strong>being less than 1, <strong><em>ϵ² </em></strong>&lt;<strong><em> ϵ. </em></strong>So, to prevent ill-conditioning, the first term should be lower than the second, but given that<strong><em> </em>g’Hg &gt; g’g,<em> </em></strong>this can be achieved only by reducing the learning rate, leading to slower learning. Thus, although ideally the gradient norm should decrease during training (since our primary aim is to reach a global minima where the gradient is 0), we can still get successful training even with the gradient norm increasing as shown below:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/862/1*hXjKd57kXl5-FxUwOE9Btg.png" /></figure><ul><li><strong>Local minima</strong>: Nearly any Deep Learning (DL ) model is guaranteed to have an extremely large number of local minima (LM) arising due to the <em>model identifiability</em> problem.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/408/1*4Wxd2igoG3RR_0IyGjYDvg.gif" /><figcaption>There might be many local minima where the model may get stuck due to zero gradient. Source: <a href="http://www.yaldex.com/game-development/1592730043_ch18lev1sec4.html">http://www.yaldex.com/game-development/1592730043_ch18lev1sec4.html</a></figcaption></figure><p>A model is said to be <em>identifiable</em> if a <em>sufficiently large</em> training set can rule out <em>all but one</em> setting of the model parameters. In case of neural networks, we can obtain equivalent models by swapping the position of the neurons. Thus, they are not identifiable.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/736/1*ElG_Qnylg9GI_Dflc80xjA.png" /><figcaption>Swapping the two hidden nodes leads to equivalent models. Thus, even after having a sufficiently large training set, there is not a unique setting of parameters. This is the model identifiability problem that neural networks suffer from.</figcaption></figure><p>However, all the local minima caused due to this have the same value of the cost function, thus not being a problem. However, if local minima with high cost are common, it becomes a serious problem as shown above. Many points other than local minima can lead to low gradients. Nowadays, it’s common to aim for a <em>low</em> <em>but not</em> <em>minimal</em> cost value.</p><ul><li><strong>Plateaus, Saddle Points and Other Flat Regions</strong>: Saddle point (SP) is another type of point with zero gradient where some points around it have higher value and the others have lower. Intuitively, this means that a saddle point acts as both a local minima for some neighbors and a local maxima for the others. Thus, Hessian at SP has both positive and negative eigenvalues (a very good explanation for this can be found <a href="https://math.stackexchange.com/questions/1985889/why-how-does-the-determinant-of-the-hessian-matrix-combined-with-the-2nd-deriva"><em>here</em></a><em>. </em>TL;DR — for a function to curve upwards or downwards around a point as in the case of local minima and local maxima, the eigenvalues should have the same sign, positive for local minima and negative for local maxima).</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/534/1*TjVePm1Fn0F5C2Uxvh79YQ.png" /><figcaption>It’s called a saddle point as it looks like the saddle of a horse. Source: <a href="http://deeplearning.ai/">deeplearning.ai</a>. I know Andrew Ng is awesome ;)</figcaption></figure><p>For many classes of random functions, saddle points <a href="https://datascience.stackexchange.com/a/30673"><em>become more common</em></a> at high dimensions with the ratio of number of SPs to LMs growing exponentially with <em>n</em> for an n-dimensional space. Many random functions have an amazing property that near points with low cost, the Hessian tends to take up mostly positive eigenvalues. SGD empirically tends to rapidly avoid encountering a high-cost saddle point. For SGD to rapidly avoid saddle points, it needs to have sufficiently high stochastic variance along all directions. Langevin dynamics stochastic gradient, is a set of SGD based algorithms that play around with SGD with added white noise to get off local minimas and saddles with high probability under mind conditions. There also might be wide, flat regions of constant value, thereby having a zero gradient. These can be problematic if the cost is high in these regions.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*TfQG_ELI1qIkuisxpCapoA.png" /><figcaption>It is problematic to get stuck in a plateau where the value of the cost function is high. Source: <a href="https://en.wikipedia.org/wiki/Local_search_(constraint_satisfaction)">https://en.wikipedia.org/wiki/Local_search_(constraint_satisfaction)</a></figcaption></figure><ul><li><strong>Cliffs and Exploding Gradients</strong>: Neural Networks (NNs) might sometimes have extremely steep regions resembling cliffs due to the repeated multiplication of weights. Suppose we use a 3-layer (input-hidden-output) neural network with all the activation functions as linear. We choose the same number of input, hidden and output neurons, thus, using the same weight W for each layer. The output layer y = W*h where h = W*x represents the hidden layer, finally giving y = W*W x. So, deep neural networks involve multiplication of a large number of parameters leading to sharp non-linearities in the parameter space. These non-linearities give rise to high gradients in some places. At the edge of such a cliff, an update step might throw the parameters extremely far.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/988/1*sdFtWM12llhRE75Sh9lz5g.png" /><figcaption>Image depicting the problem of exploding gradients when approaching a cliff. 1) Usual training going on with the parameters moving towards the lower cost region. 2) The gradient at the bottom left-most point pointed downwards (correct direction) but the step-size was too large, which caused the parameters to land at a point having large cost value. 3) The gradient at this new point moved the parameters in a completely different position undoing most of the training done until that point.</figcaption></figure><p>It can be taken care of by using <strong>Gradient Clipping (GC)</strong>.<strong> </strong>The gradient indicates only the direction in which to make the update. If the GD update proposes making a very large step, GC intervenes to reduce the step size.</p><ul><li><strong>Long-Term Dependencies</strong>: This problem is encountered when the NN becomes sufficiently deep. For example, if the same weight matrix W is used in each layer, after <em>t</em> steps, we’d get W *W * W … (<em>t</em> times). Using the eigendecomposition of W:</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/267/1*icjfmaGobKCc57Jq1MZ7Cw.png" /><figcaption>Here, <strong>V</strong> is an orthonormal matrix, i.e. V V’ = I</figcaption></figure><p>Thus, any eigenvalues not near an absolute value of one would either explode or vanish leading to the <a href="https://machinelearningmastery.com/exploding-gradients-in-neural-networks/"><em>Vanishing and Exploding Gradient</em></a><strong><em> </em></strong>problem. The use of the same weight matrix is especially the case in Recurrent NNs (RNNs), where this is a serious problem.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*trDihGTCdMaLwtTn0hyQ-A.jpeg" /><figcaption>Values near 1 either explode or vanish upon being compounded. You might have seen this poster in a separate <a href="http://www.blog.400contacts.com/uncategorized/the-most-motivational-poster-ever/">context</a>.</figcaption></figure><ul><li><strong>Inexact Gradients</strong>: Most optimization algorithms use a noisy/biased estimate of the gradient in cases where the estimate is based on sampling, or in cases where the true gradient is intractable for e.g. in the case of training a <a href="https://deeplearning4j.org/restrictedboltzmannmachine"><em>Restricted Boltzmann Machine</em></a> (RBM), an approximation of the gradient is used. For RBM, the <a href="https://deeplearning4j.org/glossary.html#contrastivedivergence"><em>contrastive divergence</em></a> algorithm gives a technique for approximating the gradient of its intractable log-likelihood.</li><li>Neural Networks might not end up at any critical point at all and such critical points might not even necessarily exist. A lot of the problems might be avoided if there exists a space connected reasonably directly to the solution by a path that local descent can follow and if we are able to initialize learning within that well-behaved space. Thus, choosing good initial points should be studied.</li></ul><h4>3. <strong><em>Basic Algorithms</em></strong></h4><ul><li><strong>Stochastic Gradient Descent</strong>: This has already been described before but there are certain things that should be kept in mind regarding SGD. The learning rate <strong><em>ϵ</em></strong> is a very important parameter for SGD. <strong><em>ϵ</em></strong> should be reduced after each epoch in general. This is due to the fact that the random sampling of batches acts as a source of noise which might make SGD keep oscillating around the minima without actually reaching it. This is shown below:</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/383/1*cijC0y2eu_750lIZeM_z7g.png" /><figcaption>Source: <a href="https://goo.gl/tq6Xof">https://goo.gl/tq6Xof</a></figcaption></figure><p>The true gradient of the total cost function (involving the entire dataset) <em>actually becomes 0 </em>when we reach the minimum. Hence, BGD can use a fixed learning rate. The following conditions guarantee convergence under convexity assumptions in case of SGD:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/360/1*aqW0OISFB5ywK6qrwJVovg.png" /></figure><p>Setting it too low makes the training proceed slowly which might lead to the algorithm being stuck at a high cost value. Setting it too high would lead to large oscillations which might even push the learning outside the optimal region. The best way is to monitor the first several iterations and set the learning rate to be higher than the best performing one, but not too high to cause instability.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*An4tZEyQAYgPAZl396JzWg.png" /><figcaption>Source: <a href="https://www.jeremyjordan.me/nn-learning-rate/">https://www.jeremyjordan.me/nn-learning-rate/</a></figcaption></figure><p>A big advantage of SGD is that the time taken to compute a weight update doesn’t grow with the number of training examples as each update is computed after observing a batch of samples which is independent of the total number of training examples. Theoretically, for a convex problem, BGD makes the error rate <strong>O(1/k)</strong> after <em>k</em> iterations whereas SGD makes it <strong>O(1/√k).</strong> However, SGD compensates for this with its advantages after a few iterations along with the ability to make rapid updates in the case of a large training set.</p><ul><li><strong>Momentum</strong>: The momentum algorithm accumulates the exponentially decaying moving average of past gradients (called as <strong>velocity</strong>) and uses it as the direction in which to take the next step. Momentum is given by mass times velocity, which is <em>equal</em> to velocity if we’re using unit mass. The momentum update is given by:</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/661/1*F-Nr_9NDG2oBp-Suwvn11w.png" /><figcaption>Momentum weight update</figcaption></figure><p>The step size (earlier equal to learning rate * gradient) now depends on how <em>large</em> and <em>aligned</em> the <em>sequence of gradients</em> are. If the gradients at each iteration point in the same direction (say <strong><em>g</em></strong>), it will lead to a higher value of the step size as they just keep accumulating. Once it reaches a constant (terminal) velocity, the step size becomes <strong>ϵ || g|| / (1 — α)</strong>. Thus, using α as 0.9 makes the speed 10 times. Common values of α are 0.5, 0.9 and 0.99.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/481/1*HefSbCpOxnVOAsyTnXcdkQ.png" /></figure><p>Viewing it as the Newtonian dynamics of a particle sliding down a hill, the momentum algorithm consists of solving a set of differential equations via numerical simulation. There are two kinds of forces involved as shown below:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/693/1*Y9y2BRFYTqSmpeSC_uZAaQ.png" /><figcaption>Momentum can be seen as two forces operating together. 1) Proportional to the negative of the gradient such that whenever it descends a steep part of the surface, it gathers speed and continues sliding in that direction until it goes uphill again. 2) A viscous drag force (friction) proportional to <strong>-v(t)</strong> without the presence of which the particle would keep oscillating back and forth as the negative of the gradient would keep forcing it to move downhill . Viscous force is suitable as it is weak enough to allow the gradient to cause motion and strong enough to resist any motion if the gradient doesn’t justify moving</figcaption></figure><p>Read more about momentum in this excellent blog post by <a href="http://distill.ai/"><em>distill.ai</em></a>: <a href="https://distill.pub/2017/momentum"><em>Why Momentum Really Works</em></a>.</p><ul><li><strong>Nesterov Momentum</strong>: This is a slight modification of the usual momentum equation. Here, the gradient is calculated after applying the current velocity to the parameters, which can be viewed as adding a correction factor:</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/735/1*u6-CeQiYysQBdRaj9uv8gA.png" /><figcaption>Nesterov momentum weight update</figcaption></figure><p>The intuition behind Nesterov momentum is that upon being at a point <strong><em>θ </em></strong>in the parameter space, the momentum update is going to shift the point by <strong>α<em>v. </em></strong>So, we are soon going to end up in the vicinity of <strong><em>(θ + </em>α<em>v)</em></strong>. Thus, it might be better to compute the gradient from that point onward. The figure below describes this visually:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/800/1*hJSLxZMjYVzgF5A_MoqeVQ.jpeg" /><figcaption>Source: <a href="http://cs231n.github.io/neural-networks-3/#sgd">http://cs231n.github.io/neural-networks-3/#sgd</a></figcaption></figure><p>This concludes the 1st part of our summary for <a href="http://www.deeplearningbook.org/contents/optimization.html"><em>Chapter 8</em>.</a> We hope that this gave you a good intuition and understanding on the fundamental concepts behind Optimization used in Deep Learning. Part II of the summary would contain more advanced concepts like algorithms with adaptive learning rates and batch-normalization which are also fundamental in making Deep Learning practically applicable to real-world problems. To stay updated with our posts, <a href="https://medium.com/inveterate-learner"><em>follow</em></a> our publication, <strong>Inveterate Learner</strong>. If you’re looking for the summary of previous chapters or are more comfortable reading from a Jupyter Notebook, feel free to have a look over our repository <a href="https://github.com/dalmia/Deep-Learning-Book-Chapter-Summaries"><em>here</em></a>. Finally, I thank my co-author for the publication, <a href="https://medium.com/u/6b3fcf7407c8">Ameya Godbole</a>, for reviewing the post and suggesting many important areas for further explanations along with several nip ticks. A special thanks to <a href="https://medium.com/u/314be6963dfe">Raghav Somani</a> for providing deeper mathematical insights and clarity in a lot of places that gave me (and I hope everyone else too) a better understanding of the concepts.</p><blockquote>When something is important enough, you do it even if the odds are not in your favor.</blockquote><blockquote>- Elon Musk</blockquote><blockquote>If there’s anything that you might want to share with me or give any sort of feedback on my writing/thoughts, I would love to hear it from you. Feel free to connect with me on <a href="https://www.linkedin.com/in/aman-dalmia">LinkedIn</a>, <a href="https://www.facebook.com/aman.dalmia.8">Facebook</a> or follow me on <a href="http://github.com/dalmia">Github</a>.</blockquote><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=20ae75984cb2" width="1" height="1" alt=""><hr><p><a href="https://medium.com/inveterate-learner/deep-learning-book-chapter-8-optimization-for-training-deep-models-part-i-20ae75984cb2">Deep Learning Book: Chapter 8— Optimization For Training Deep Models Part I</a> was originally published in <a href="https://medium.com/inveterate-learner">Inveterate Learner</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Deep Learning Book: Chapter 7 — Regularization for Deep Learning]]></title>
            <link>https://medium.com/inveterate-learner/deep-learning-book-chapter-7-regularization-for-deep-learning-937ff261875c?source=rss----ba6eaa0b1544---4</link>
            <guid isPermaLink="false">https://medium.com/p/937ff261875c</guid>
            <category><![CDATA[regularization]]></category>
            <category><![CDATA[artificial-intelligence]]></category>
            <category><![CDATA[machine-learning]]></category>
            <category><![CDATA[deep-learning]]></category>
            <category><![CDATA[deep-learning-book]]></category>
            <dc:creator><![CDATA[Aman Dalmia]]></dc:creator>
            <pubDate>Mon, 04 Jun 2018 12:54:32 GMT</pubDate>
            <atom:updated>2018-06-08T01:58:44.389Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/375/1*tE8dh8Zv0kc4e0xet41xYA.jpeg" /></figure><p><em>This is going to be a series of blog posts on the </em><a href="http://deeplearningbook.org/"><em>Deep Learning book</em></a><em> where </em><a href="https://medium.com/inveterate-learner"><em>we</em></a><em> are attempting to provide a summary of each chapter highlighting the concepts that we found to be the most important so that other people can use it as a starting point for reading the chapters, while adding further explanations on few areas that we found difficult to grasp. Please refer </em><a href="http://www.deeplearningbook.org/contents/notation.html"><em>this</em></a><em> for more clarity on notation</em>.</p><p>In Machine Learning, and more so in Deep Learning, <strong><em>overfitting</em></strong> is a major issue that occurs during training. A model is considered as overfitting the training data when the training error keeps decreasing but the test error (or the <em>generalisation</em> error) starts increasing. At this point we tend to believe that the model is learning the training data distribution and not generalising to unseen data. <strong><em>Regularization</em></strong> is a modification we make to the learning algorithm or the model architecture that reduces its generalisation error, possibly at the expense of increased training error. There are various ways of doing this, some of which include restriction on parameter values or adding terms to the objective function, etc.</p><p>These constraints are designed to encode some sort of prior knowledge, with a preference towards simpler models to promote generalisation (see <a href="https://en.wikipedia.org/wiki/Occam%27s_razor">Occam’s Razor</a>). The sections present in this chapter are listed below:</p><ul><li><a href="#a494"><strong><em>Parameter Norm Penalties</em></strong></a></li><li><a href="#f1ca"><strong><em>Norm Penalties as Constrained Optimization</em></strong></a></li><li><a href="#8e94"><strong><em>Regularization and Under-Constrained Problems</em></strong></a></li><li><a href="#14a7"><strong><em>Dataset Augmentation</em></strong></a></li><li><a href="#b669"><strong><em>Noise Robustness</em></strong></a></li><li><a href="#2cb4"><strong><em>Semi-Supervised Learning</em></strong></a></li><li><a href="#1fe4"><strong><em>Mutlitask Learning</em></strong></a></li><li><a href="#7f3e"><strong><em>Early Stopping</em></strong></a></li><li><a href="#fcf6"><strong><em>Parameter Tying and Parameter Sharing</em></strong></a></li><li><a href="#cba1"><strong><em>Sparse Representations</em></strong></a></li><li><a href="#fe8b"><strong><em>Bagging and Other Ensemble Methods</em></strong></a></li><li><a href="#1ec0"><strong><em>Dropout</em></strong></a></li><li><a href="#6ec5"><strong><em>Adversarial Training</em></strong></a></li><li><a href="#107d"><strong><em>Tangent Distance, Tangent Prop and Manifold Tangent Classifier</em></strong></a></li></ul><h4>1. Parameter Norm Penalties</h4><p>The idea here is to limit the capacity (the space of all possible model families) of the model by adding a parameter norm penalty, <strong>Ω(θ)</strong>, to the objective function, <strong><em>J</em></strong>:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/509/1*sUsuKyXHjEL7OakzTp8fpw.png" /></figure><p>Here, <strong>θ</strong> represents only the weights and not the biases, the reason being that the biases require much less data to fit and do not add much variance.</p><p><strong>1.1 L² Parameter Regularization</strong></p><p>Here, we have the following parameter norm penalty:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/303/1*eVIiuom3WCG4ybzoidD6hA.png" /></figure><p>Applying the 2nd order Taylor-Series approximation (ignoring all terms of order greater than 2 in the Taylor-Series expansion) at the point <strong><em>w*</em></strong> (where <strong><em>J̃</em></strong><em>(</em><strong><em>θ; X, y)</em></strong><em> </em>assumes the minimum value, i.e., ∇<strong><em>J̃ </em></strong><em>(</em><strong><em>w*</em></strong><em>)</em>= 0), we get the following expression (as the first order gradient term is 0):</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/774/1*yhSQCLrb3OjaNbnD83yG5g.png" /></figure><p>Finally,<strong><em> ∇ Ĵ(w)</em></strong> =<strong><em> H(w — w*) </em></strong>since the first term is just a constant and the derivative of <strong><em>X’ H X</em></strong> (’ represents the transpose) is <strong><em>2 H X</em></strong>. The overall gradient of the objective function (gradient of <strong><em>Ĵ </em></strong>+ gradient of <strong>Ω(θ)</strong>)becomes:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/685/1*q44L6JgdYOZjMmFFmtFXeQ.png" /></figure><p>As <em>α</em> approaches 0, <em>w</em> comes closer to <em>w*</em>. Finally, since <em>H</em> is real and symmetric, it can be decomposed into a diagonal matrix ∧ and an orthonormal set of eigenvectors, <em>Q</em>.That is, <em>H = Q’ </em>∧<em> Q.</em></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/429/1*QtBSkNsDXr3U1VtHVi5NrQ.png" /></figure><p>Because of the marked term, the value of each weight is rescaled along the eigenvectors of <em>H</em>. The value of the weights along the eigenvector <em>i</em>,is rescaled by λi /(λi+α), where λi represents the eigenvalue corresponding to that eigenvector.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/436/1*RaRsRch6xhWxPtW4sOPOVA.png" /></figure><p>The diagram below illustrates this well:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/566/1*v1-X9mAc004GerFA6dDsrg.png" /></figure><p>To look at its application to Machine Learning, we have to look at linear regression. The objective function there is exactly quadratic, given by:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/410/1*pSlnjub9UiDkqDRnwD3G8w.png" /></figure><p><strong>1.2 L¹ parameter regularization</strong></p><p>Here, the parameter norm penalty is given by: Ω(θ)<strong> </strong>= ||w||¹</p><p>This makes the gradient of the overall objective function:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/604/1*P3eg0je1zgoTJU4-4IgceQ.png" /></figure><p>Now, the last term, sign(w), creates some difficulty as the gradient no longer scales linearly with <em>w</em>. This leads to a few complexities in arriving at the optimal solution (details of which can be found in this <a href="https://github.com/dalmia/Deep-Learning-Book-Chapter-Summaries/blob/master/Appendix.ipynb"><em>Appendix notebook</em></a>):</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/433/1*ppbZZj_tOIDV83IsbpU-Pw.png" /></figure><p>My current interpretation of the max term is that, there shouldn’t be a zero crossing, as the gradient of the absolute value function is not differentiable at zero.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/534/1*wzWNY2uPHzG20w5C2mUbeQ.png" /></figure><p>Thus, L¹ regularization has the property of sparsity, which is its fundamental distinguishing feature from L². Hence, L¹ is used for feature selection as in LASSO.</p><h4>2. Norm penalties as constrained optimization</h4><p>From chapter 4’s section 4, we know that to minimize any function under some constraints, we can construct a generalized Lagrangian function containing the objective function along with the penalties. Suppose we wanted <strong>Ω(θ) &lt; k</strong>, then we could construct the following Lagrangian:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/302/1*Sm5tMOJp7YGtrSBq31O7Mw.png" /></figure><p>We get optimal θ by solving the Lagrangian. If Ω(θ) &gt; k, then the weights need to be compensated highly and hence, α should be large to reduce its value below k. Likewise, if Ω(θ)&lt;k, then the norm shouldn’t be reduced too much and hence, α should be small. This is now similar to the parameter norm penalty regularized objective function as both of them encourage lower values of the norm. Thus, parameter norm penalties naturally impose a constraint, like the L²-regularization, defining a constrained L²-ball. Larger α implies a smaller constrained region as it pushes the values really low, hence, allowing a small radius and vice versa. The idea of constraints over penalties is important for several reasons. Large penalties might cause non-convex optimization algorithms to get stuck in local minima due to small values of <strong>θ</strong>, leading to the formation of so-called <em>dead cells</em>, as the weights entering and leaving them are too small to have an impact. Constraints don’t enforce the weights to be near zero, rather being confined to a constrained region.</p><p>Another reason is that constraints induce higher stability. With higher learning rates, there might be a large weight, leading to a large gradient, which could go on iteratively leading to numerical overflow in the value of θ.<strong> </strong>Constrains, along with reprojection (to the corresponding ball), prevent the weights from becoming too large, thus, maintaining stability.</p><p>A final suggestion made by Hinton was to restrict the individual column norms of the weight matrix rather than the Frobenius norm of the entire weight matrix, so as to prevent any hidden unit from having a large weight. The idea here is that if we restrict the Frobenius norm, it doesn’t guarantee that the individual weights would be small, just their norm. So, we might have large weights being compensated by extremely small weights to make the overall norm small. Restricting each hidden unit individually gives us the required guarantee.</p><h4>3. Regularized &amp; Under-constrained problems</h4><p><em>Underdetermined problems</em> are those problems that have infinitely many solutions. A logistic regression problem having linearly separable classes with <em>w</em> as a solution, will always have <em>2w</em> as a solution and so on. In some machine learning problems, regularization is necessary. For e.g., many algorithms (e.g. PCA) require the inversion of X’ X, which might be singular. In such a case, we can use a regularized form instead. (X’ X + αI) is guaranteed to be invertible.</p><p>Regularization can solve underdetermined problems. For e.g. the Moore-Pentose pseudoinverse defined earlier as:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/341/1*h7Nt2LvGjGF1J1XNN0vZcA.png" /></figure><p>This can be seen as performing a linear regression with L²-regularization.</p><h4>4. Data augmentation</h4><p>Having more data is the most desirable thing to improving a machine learning model’s performance. In many cases, it is relatively easy to artificially generate data. For a classification task, we desire for the model to be invariant to certain types of transformations, and we can generate the corresponding (x,y)pairs by translating the input <em>x</em>. But for certain problems, like density estimation, we can’t apply this directly unless we have already solved the density estimation problem.</p><p>However, caution needs to be maintained while augmenting data to make sure that the class doesn’t change. For e.g., if the labels contain both “b” and “d”, then horizontal flipping would be a bad idea for data augmentation. Adding random noise to the inputs is another form of data augmentation, while adding noise to hidden units can be seen as doing data augmentation at multiple levels of abstraction.</p><p>Finally, when comparing machine learning models, we need to evaluate them using the same hand-designed data augmentation schemes or else it might happen that algorithm A outperforms algorithm B, just because it was trained on a dataset which had more / better data augmentation.</p><h4>5. Noise Robustness</h4><p>Noise with infinitesimal variance imposes a penalty on the norm of the weights. Noise added to hidden units is very important and is discussed later in <a href="#1ec0"><strong><em>Dropout</em></strong></a>. Noise can even be added to the weights. This has several interpretations. One of them is that adding noise to weights is a stochastic implementation of Bayesian inference over the weights, where the weights are considered to be uncertain, with the uncertainty being modelled by a probability distribution. It is also interpreted as a more traditional form of regularization by ensuring stability in learning.</p><p>For e.g. in the linear regression case, we want to learn the mapping <em>y(x)</em> for each feature vector <em>x</em>, by reducing the mean square error.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/306/1*2MLxP-ejbh1nXxbX65NUVA.png" /></figure><p>Now, suppose a zero mean unit variance Gaussian random noise, <em>ϵ, </em>is added to the weights. We till want to learn the appropriate mapping through reducing the mean square. Minimizing the loss after adding noise to the weights is equivalent to adding another regularization term which makes sure that small perturbations in the weight values don’t affect the predictions much, thus stabilising training.</p><p>Sometimes we may have the wrong output labels, in which case maximizing p(y | x)may not be a good idea. In such a case, we can add noise to the labels by assigning a probability of (1-<em>ϵ</em>) that the label is correct and a probability of <em>ϵ</em> that it is not. In the latter case, all the other labels are equally likely. <em>Label Smoothing</em> regularizes a model with <em>k</em> softmax outputs by assigning the classification targets with probability (1-<em>ϵ </em>) or choosing any of the remaining (k-1) classes with probability <em>ϵ / (k-1)</em>.</p><h4>6. Semi-Supervised Learning</h4><p>P(x,y) denotes the joint distribution of <em>x</em> and <em>y</em>, i.e., corresponding to a training sample <em>x</em>, I have a label <em>y</em>. P(x) denotes the marginal distribution of <em>x</em>, i.e., just the training examples without any labels. In <em>Semi-supervised Learning</em>, we use both P(x,y)(some labelled samples) and P(x)(unlabelled samples) to estimate P(y|x)(since we want to predict the class, <em>given</em> the training sample). We want to learn some representation h = f(x)such that samples which are closer in the input space have similar representations and a linear classifier in the new space achieves better generalization error.</p><p>Instead of separating the supervised and unsupervised criteria, we can instead have a generative model of P(x) (or P(x, y)) which shares parameters with the discriminative model. The idea is to share the unsupervised/generative criterion with the supervised criterion to express a prior belief that the structure of P(x) (or P(x, y)) is connected to the structure of P(y|x), which is expressed by the shared parameters.</p><h4>7. Multitask Learning</h4><p>The idea is to improve the generalization error by pooling together examples from multiple tasks. Similar to how more data leads to more generalization, using a part of the model for different tasks constrains that part to learn good values. There are two types of model parameters:</p><ul><li><em>Task-specific</em>: These parameters benefit only from that particular task.</li><li><em>Generic</em>, shared across all tasks: These are the ones which benefit from learning through various tasks.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/189/1*hNU50PFTAOiXsK9P_9wDMw.png" /></figure><p>Multitask learning leads to better generalization when there is actually some relationship between the tasks, which actually happens in the context of Deep Learning where some of the factors, which explain the variation observed in the data, are shared across different tasks.</p><h4>8. Early Stopping</h4><p>As mentioned at the start of the post, after a certain point of time during training, for a model with extremely high representational capacity, the training error continues to decrease but the validation error begins to increase (which we referred to as overfitting). In such a scenario, a better idea would be to return back to the point where the validation error was the least. Thus, we need to keep calculating the validation metric after each epoch and if there is any improvement, we store that parameter setting. Upon termination of training, we return the last <em>saved</em> parameters.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/485/1*F6WHrngq2WeqIDWYaSRmdA.png" /></figure><p>The idea of <em>Early Stopping</em> is that if the validation error doesn’t improve over a certain fixed number of iterations, we <em>terminate</em> the algorithm. This effectively reduces the capacity of the model by reducing the number of steps required to fit the model. The evaluation on the validation set can be done both on another GPU in parallel or done after the epoch. A drawback of weight decay was that we had to manually tweak the weight decay coefficient, which, if chosen wrongly, can lead the model to local minima by squashing the weight values too much. In Early Stopping, no such parameter needs to be tweaked which reduces the number of hyperparameters that we need to tune.</p><p>However, since we are setting aside some part of the training data for validation, we are not using the complete training set. So, once Early Stopping is done, a second phase of training can be done where the complete training set is used. There are two choices here:</p><ul><li>Train from scratch for the same number of steps as in the Early Stopping case.</li><li>Use the weights learned from the first phase of training and retrain using the complete data.</li></ul><p>Other than lowering the number of training steps, it reduces the computational cost also by regularizing the model without having to add additional penalty terms. It affects the optimization procedure by restricting it to a small volume of the parameter space, in the neighbourhood of the initial parameters. Suppose 𝛕 and <em>ϵ</em> represent the number of iterations and the learning rate respectively. Then, <em>ϵ</em>𝛕 effectively represents the capacity of the model. Intuitively, this can be seen as the inverse of the weight decay co-efficient λ. When <em>ϵ</em>𝛕 is small (or λ is large), the parameter space is small and vice versa. This equivalence holds true for a linear model with quadratic cost function (initial parameters w⁰ = 0). Taking the Taylor Series Approximation of <strong><em>J(w)</em></strong> around the empirically optimal weights <em>w*</em>:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/259/1*KLUDN1flt0zMYfsujTq2HQ.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/166/1*FMSXzUHDChZYrlrU6yUiqQ.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/273/1*8DPfmDnju03O5cMoZ_iESw.png" /></figure><p>multiplying with Q’ on both sides and using the fact that Q’Q = I (Q is orthonormal):</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/406/1*8PWVojRp_-auhgrlr9cHNQ.png" /></figure><p>Assuming <em>ϵ to be small enough:</em></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/276/1*r0ffDgxvDSec2jIVshAM1g.png" /></figure><p>The equation for L² regularization is given by:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/388/1*VPY7RCS8usbYKipuDHrlyQ.png" /></figure><p>Thus, if the hyperparameters are such that:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/232/1*yXKse4QPQv5qFMJPYnHD6w.png" /></figure><p>L²-regularization can be seen as equivalent to Early Stopping.</p><h4>9. Parameter Tying and Parameter Sharing</h4><p>Till now, most of the methods focused on bringing the weights to a fixed point, e.g. 0 in the case of norm penalty. However, there might be situations where we might have some prior knowledge on the kind of dependencies that the model should encode. Suppose, two models A and B, perform a classification task on similar input and output distributions. In such a case, we’d expect the parameters for both the models to be similar to each other as well. We could impose a norm penalty on the distance between the weights, but a more popular method is to <em>force</em> the set of parameters to be equal. This is the essence behind <em>Parameter Sharing</em>. A major benefit here is that we need to store only a subset of the parameters (e.g. storing only the parameters for model A instead of storing for both A and B) which leads to large memory savings. In the example of Convolutional Neural Networks or CNNs (discussed in Chapter 9), the same feature is computed across different regions of the image and hence, a cat is detected irrespective of whether it is at position ior i+1 .</p><h4>10. Sparse Representations</h4><p>We can place penalties on even the activation values of the units which indirectly imposes a penalty on the parameters. This leads to representational sparsity, where many of the activation values of the units are zero. In the figure below, <em>h </em>is a representation of <em>x, </em>which is sparse. Representational sparsity is obtained similarly to the way parameter sparsity is obtained, by placing a penalty on the representation <em>h </em>instead of the weights<em>.</em></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/445/1*C_padvQLEQa2mQ9b6p15wg.png" /></figure><p>Another idea could be to average the activation values across various examples and push it towards some value. An example of getting representational sparsity by imposing hard constraint on the activation value is the <strong>Orthogonal Matching Pursuit (OMP) </strong>algorithm, where a representation <em>h</em> is learned for the input <em>x</em> by solving the constrained optimization problem:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/330/1*vXORa2fV9luAAeacNNojwA.png" /></figure><p>where the constraint is on the the number of non-zero entries indicated by<em> b</em>. The problem can be solved efficiently when <em>W</em> is restricted to be orthogonal</p><h4>11. Bagging and Other Ensemble Methods</h4><p>The techniques which train multiple models and take the maximum vote across those models for the final prediction are called <em>ensemble</em> methods. The idea is that it’s highly unlikely that multiple models would make the same error in the test set.</p><p>Suppose that we have <em>K </em>regression models, with the model #i making an error ϵi on each example, where ϵi is drawn from a zero mean, multivariate normal distribution such that: 𝔼(ϵi²)=v and 𝔼(ϵiϵj)=c. The error on each example is then the average across all the models: (∑ ϵi)/K.</p><p>The mean of this average error is 0 (as the mean of each of the individual ϵiϵi is 0). The variance of the average error is given by:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/585/1*Yfw07dtSODyrYPD-E4vm7w.png" /></figure><p>Thus, if c = v, then there is no change. If c = 0, then the variance of the average error decreases with K. There are various ensembling techniques. In the case of <em>Bagging</em> (Bootstrap Aggregating), the same training algorithm is used multiple times. The dataset is broken into K parts by sampling with replacement (see figure below for clarity) and a model is trained on each of those K parts. Because of sampling with replacement, the K parts have a few similarities as well as a few differences. These differences cause the difference in the predictions of the K models. Model averaging is a very strong technique.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/881/1*BcCZMBNQHGP0YBnuQQHe1Q.png" /></figure><h4>12. Dropout</h4><p><em>Dropout</em> is a computationally inexpensive, yet powerful regularization technique. The problem with bagging is that we can’t train an exponentially large number of models and store them for prediction later. Dropout makes bagging practical by making an inexpensive approximation. In a simplistic view, dropout trains the ensemble of all sub-networks formed by randomly removing a few non-output units by multiplying their outputs by 0. For every training sample, a mask is computed for all the input and hidden units independently. For clarification, suppose we have <em>h</em> hidden units in some layer. Then, a mask for that layer refers to a <em>h </em>dimensional vector with values either 0(remove the unit) or 1(keep the unit).</p><p>There are a few differences from bagging though:</p><ul><li>In bagging, the models are independent of each other, whereas in dropout, the different models share parameters, with each model taking as input, a sample of the total parameters.</li><li>In bagging, each model is trained till convergence, but in dropout, each model is trained for just one step and the parameter sharing makes sure that subsequent updates ensure better predictions in the future.</li></ul><p>At test time, we combine the predictions of all the models. In the case of bagging with K models, this was given by the arithmetic mean. In case of dropout, the probability that a model is chosen is given by p(μ), with μ denoting the mask vector. The prediction then becomes ∑ p(μ)p(y|x, μ). This is not computationally feasible, and there’s a better method to compute this in one go, using the <em>geometric mean</em> instead of the arithmetic mean.</p><p>We need to take care of two main things when working with geometric mean:</p><ul><li>None of the probabilities should be zero.</li><li>Re-normalization to make sure all the probabilities sum to 1.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/268/1*Q4NLOq6aCb_dWrrwSyabuw.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/305/1*LmXxOe8tosiyotlFtCuCiA.png" /></figure><p>The advantage for dropout is that first term can be approximated in one pass of the complete model by dividing the weight values by the keep probability (<em>weight scaling inference rule</em>). The motivation behind this is to capture the right expected values from the output of each unit, i.e. the total expected input to a unit at train time is equal to the total expected input at test time. A big advantage of dropout then is that it doesn’t place any restriction on the <em>type</em> of model or training procedure to use.</p><p><strong><em>Points to note</em></strong>:</p><ul><li>Reduces the representational capacity of the model and hence, the model should be large enough to begin with.</li><li>Works better with more data.</li><li>Equivalent to L² for linear regression, with different weight decay coefficient for each input feature.</li></ul><p><strong><em>Biological Interpretration</em></strong>:</p><p>During sexual reproduction, genes could be swapped between organisms if they are unable to correctly adapt to the unusual features of any organism. Thus, the units in dropout learn to perform well regardless of the presence of other hidden units, and also in many different contexts.</p><p>Adding noise in the hidden layer is more effective than adding noise in the input layer. For e.g. let’s assume that some unit learns to detect a nose in a face recognition task. Now, if this unit is removed, then some other unit either learns to redundantly detect a nose or associates some other feature (like mouth) for recognising a face. In either way, the model learns to make more use of the information in the input. On the other hand, adding noise to the input won’t completely removed the nose information, unless the noise is so large as to remove most of the information from the input.</p><h4>13. Adversarial Training</h4><p>Deep Learning has <a href="https://www.microsoft.com/en-us/research/blog/microsoft-researchers-algorithm-sets-imagenet-challenge-milestone/"><em>outperformed</em></a> humans in the task of Image Recognition, which might lead us to believe that these models have acquired a human-level understanding of an image. However, experimentally searching for an <em>x′</em> (given an <em>x</em>), such that prediction made by the model changes, shows otherwise. As shown in the image below, although the newly formed image (adversarial image) looks almost exactly the same to a human, the model classifies it wrongly and that too with very high confidence:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/431/1*TdCaHMUJjoE5bjtqkUlIMA.png" /></figure><p><strong>Adversarial training</strong> refers to training on images which are adversarially generated and it has been shown to reduce the error rate. The main factor attributed to the above mentioned behaviour is the linearity of the model (say y = Wx), caused by the main building blocks being primarily linear. Thus, a small change of ϵ in the input causes a drastic change of <em>W</em>ϵ in the output. The idea of adversarial training is to avoid this jumping and induce the model to be locally constant in the neighborhood of the training data.</p><p>This can also be used in semi-supervised learning. For an unlabelled sample <em>x</em>, we can assign the label ŷ (<em>x</em>) using our model. Then, we find an adversarial example, x′, such that y(x′)≠ŷ (x) (an adversary found this way is called <em>virtual adversarial example</em>). The objective then is to assign the same class to both <em>x</em> and <em>x′</em>. The idea behind this is that different classes are assumed to lie on disconnected manifolds and a little push from one manifold shouldn’t land in any other manifold.</p><h4>14. Tangent Distance, Tangent Prop and manifold Tangent Classifier</h4><p>Many ML models assume the data to lie on a low dimensional manifold to overcome the curse of dimensionality. The inherent assumption which follows is that small perturbations that cause the data to move along the manifold (it originally belonged to), shouldn’t lead to different class predictions. The idea of the <strong>tangent distance</strong> algorithm to find the K-nearest neighbors using the distance metric as the distance between manifolds. A manifold <em>Mi</em> is approximated by the tangent plane at <em>Xi</em>, hence, this technique needs tangent vectors to be specified.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/516/1*7aWquHigoWqLAhxgMnjGPw.png" /></figure><p>The <strong>tangent prop</strong> algorithm proposed to learn a neural network based classifier, <em>f(x)</em>, which is invariant to known transformations causing the input to move along its manifold. Local invariance would require that ▽ <em>f(x)</em> is perpendicular to the tangent vectors <em>V(i)</em>. This can also be achieved by adding a penalty term that minimizes the directional directive of <em>f(x)</em> along each of the <em>V(i).</em></p><p>It is similar to data augmentation in that both of them use prior knowledge of the domain to specify various transformations that the model should be invariant to. However, tangent prop only resists infinitesimal perturbations while data augmentation causes invariance to much larger perturbations.</p><p><strong>Manifold Tangent Classifier</strong> works in two parts:</p><ul><li>Use Autoencoders to learn the manifold structures using Unsupervised Learning.</li><li>Use these learned manifolds with tangent prop.</li></ul><p>I have missed out on many details along the way in the trade-off for explaining the ones I found the most relevant today. If you’re looking for the summary of previous chapters or are more comfortable reading from a Jupyter Notebook, feel free to have a look over our repository <a href="https://github.com/dalmia/Deep-Learning-Book-Chapter-Summaries"><em>here</em></a>. If you are interested in reading more such summaries and/or receiving research paper implementations/explanations, <a href="https://medium.com/inveterate-learner"><em>follow</em></a> our publication, Inveterate Learner. Finally, I thank my co-author for the publication, <a href="https://medium.com/u/6b3fcf7407c8">Ameya Godbole</a>, for reviewing the post and doing several important corrections. A special thanks to <a href="https://medium.com/u/7ad4b11dba95">Harsh Patel</a> for pointing out the mistake in my definition of regularization and <a href="https://medium.com/u/314be6963dfe">Raghav Somani</a> for providing clarification in the norm notation of OMP’s constrained optimization problem.</p><blockquote>Persistence is very important. You should not give up unless you are forced to give up.</blockquote><blockquote>-Elon Musk</blockquote><blockquote>If there’s anything that you might want to share with me or give any sort of feedback on my writing/thoughts, I would love to hear it from you. Feel free to connect with me on <a href="https://www.linkedin.com/in/aman-dalmia">LinkedIn</a>, <a href="https://www.facebook.com/aman.dalmia.8">Facebook</a> or follow me on <a href="http://github.com/dalmia">Github</a>.</blockquote><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=937ff261875c" width="1" height="1" alt=""><hr><p><a href="https://medium.com/inveterate-learner/deep-learning-book-chapter-7-regularization-for-deep-learning-937ff261875c">Deep Learning Book: Chapter 7 — Regularization for Deep Learning</a> was originally published in <a href="https://medium.com/inveterate-learner">Inveterate Learner</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>