<?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[Deep Learning made easy - Medium]]></title>
        <description><![CDATA[Deep learning concepts explained in a simple and practical way - Medium]]></description>
        <link>https://medium.com/deeplearningmadeeasy?source=rss----50ba1a5b3417---4</link>
        <image>
            <url>https://cdn-images-1.medium.com/proxy/1*TGH72Nnw24QL3iV9IOm4VA.png</url>
            <title>Deep Learning made easy - Medium</title>
            <link>https://medium.com/deeplearningmadeeasy?source=rss----50ba1a5b3417---4</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Fri, 13 Nov 2026 22:25:41 GMT</lastBuildDate>
        <atom:link href="https://medium.com/feed/deeplearningmadeeasy" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com/" rel="hub"/>
        <item>
            <title><![CDATA[How to use a custom loss with hugging face]]></title>
            <link>https://medium.com/deeplearningmadeeasy/how-to-use-a-custom-loss-with-hugging-face-fc9a1f91b39b?source=rss----50ba1a5b3417---4</link>
            <guid isPermaLink="false">https://medium.com/p/fc9a1f91b39b</guid>
            <dc:creator><![CDATA[Alvaro Durán Tovar]]></dc:creator>
            <pubDate>Wed, 07 Jun 2023 05:34:54 GMT</pubDate>
            <atom:updated>2023-06-11T16:49:05.571Z</atom:updated>
            <content:encoded><![CDATA[<p>Recently I helped a colleague at work to fix an issue to setup a custom loss when using hugging face. We couldn’t find much information about it, so we had to figure it out ourselves. Here I want to share it so others can find it next time.</p><p>Let&#39;s start by setting up a dummy model, dataset, and hugging face trainer (forget about optimality, or if it makes sense at all, we just want to make sure it works end to end without failing).</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/0f557eea0e995f8561df1b9f9952c876/href">https://medium.com/media/0f557eea0e995f8561df1b9f9952c876/href</a></iframe><p>Ok, so we are using IMDB dataset to classify reviews as good or bad. This a classification problem and hugging face correctly setup the loss function and everything else for us… But! Let&#39;s go the hard way, now we are going to use our own loss function, how?</p><p>Subclass Trainer and implement the method <strong>compute_loss:</strong></p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/993339351473f399dc7f388d3968eff9/href">https://medium.com/media/993339351473f399dc7f388d3968eff9/href</a></iframe><h3>What if my custom trainer is not receiving the labels?</h3><p>This happened to us. You might have “remove_unused_columns=True”, meaning the trainer is dropping the inputs that are not expected on the forward function, so either set “remove_unused_columns=False” or add the labels arguments to your module:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/82abb271288a508a4cc9776f9d3997e6/href">https://medium.com/media/82abb271288a508a4cc9776f9d3997e6/href</a></iframe><p>How that works is by using “inspect.signature”, which gives you the ability to read the parameters of the given function: <a href="https://github.com/huggingface/transformers/blob/f1660d7e23d4432513fe060bde4f9b7b29f05204/src/transformers/trainer.py#L755">https://github.com/huggingface/transformers/blob/f1660d7e23d4432513fe060bde4f9b7b29f05204/src/transformers/trainer.py#L755</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=fc9a1f91b39b" width="1" height="1" alt=""><hr><p><a href="https://medium.com/deeplearningmadeeasy/how-to-use-a-custom-loss-with-hugging-face-fc9a1f91b39b">How to use a custom loss with hugging face</a> was originally published in <a href="https://medium.com/deeplearningmadeeasy">Deep Learning made easy</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[MLFlow for MLOps]]></title>
            <link>https://medium.com/deeplearningmadeeasy/mlflow-for-mlops-414be83b33d2?source=rss----50ba1a5b3417---4</link>
            <guid isPermaLink="false">https://medium.com/p/414be83b33d2</guid>
            <category><![CDATA[machine-learning]]></category>
            <category><![CDATA[mlops]]></category>
            <category><![CDATA[engineering]]></category>
            <category><![CDATA[mlflow]]></category>
            <category><![CDATA[data-science]]></category>
            <dc:creator><![CDATA[Alvaro Durán Tovar]]></dc:creator>
            <pubDate>Fri, 04 Jun 2021 10:02:53 GMT</pubDate>
            <atom:updated>2021-06-04T10:02:33.393Z</atom:updated>
            <content:encoded><![CDATA[<p>Recently I have been looking for different alternatives for mlops at my job. We end up choosing mlflow and with this article I want to summarise my findings.</p><h3>Resources</h3><p>By far the best way to learn about it is watching this three videos from databricks:</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2Fvideoseries%3Flist%3DPLDIht0f-JGK-BlauP79pQjeeEuAAoC-J0&amp;display_name=YouTube&amp;url=https%3A%2F%2Fwww.youtube.com%2Fplaylist%3Flist%3DPLDIht0f-JGK-BlauP79pQjeeEuAAoC-J0&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2Fx3cxvsUFVZA%2Fhqdefault.jpg%3Fsqp%3D-oaymwEWCKgBEF5IWvKriqkDCQgBFQAAiEIYAQ%3D%3D%26rs%3DAOn4CLAp7QE81HPDbH3atRslj0FWD6574Q%26days_since_epoch%3D18773&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="853" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/22c0f5316c341fa1e8fc660971465caa/href">https://medium.com/media/22c0f5316c341fa1e8fc660971465caa/href</a></iframe><p>And here you have the documentation: <a href="https://www.mlflow.org/docs/latest/quickstart.html">https://www.mlflow.org/docs/latest/quickstart.html</a></p><h3>Index</h3><ol><li>What is mlflow?</li><li>Server mode<br>2.1. Experiments tracking<br>2.2. Model tracking</li><li>Client mode<br>3.1. Tracking experiments<br>3.2. Running models</li><li>What else can you do with mlflow?</li></ol><h3>1. What is mlflow?</h3><p>Basically it’s a library and through the library you can do a ton of things. It can be used as a client library to run experiments, execute projects, build models, etc. And is possible to run it as a server to receive experiment metrics, artifacts and even start a http server to serve a machine learning model… All from the same package.</p><h3>2. Server mode</h3><h4>2.1 Experiments tracking</h4><p>By running mlflow server you will start a http server that can receive tracking information to be stored on a database (sqlite, mysql, progresql…) and artifacts (google cloud, s3…). Example:</p><pre>mlflow server \<br>--default-artifact-root gs://&lt;bucket&gt;/&lt;folder&gt; \<br>--backend-store-uri postgresql://user:pass@host:port/db</pre><p>The UI offers very a nice and intuitive way to interact with the uploaded information.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*PyHarfmUm32HTYrvj1uqwg.png" /><figcaption>Image from <a href="https://www.pye.ai/">https://www.pye.ai/</a></figcaption></figure><p>You can compare different runs to find out what performed better using different models and/or different set of parameters.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*SGXarWFTMGQyf5G1AMYt8Q.png" /></figure><p>Even includes a section for hyperparameter tuning.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*P5gzSqSZ-jpbCiYpUUiovg.png" /></figure><h4>2.2 Model tracking</h4><p>For each experiment you can (and should) log artifacts including the model used. MLflow offers functions for automatically logging models to make it easier, but you can log anything you want (images, text, audio, binaries, parameters, metrics…). The cool thing about this models is that it adds a conda.yaml file to specify the dependencies. No more headaches with conflicting package versions or figuring out the setup of the author! (you might have headaches to setup the file correctly tho).</p><p>Another cool feature is the ability to upload a sample input and the schema for the expected input and output. If the schema is provided mlflow can validate it on inference time to reject invalid calls.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*350fKn_eP4hFSZiKcTIDjQ.png" /><figcaption>Image from <a href="https://docs.databricks.com/">https://docs.databricks.com/</a></figcaption></figure><p>From the above interface you can create a model. A model is just a promoted experiment. Models have a unique name, are versioned and have stages so you know which one is in production stage easily.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*F_8QwLUOSPLVkegTr9gl5A.png" /></figure><h3>3. Client mode</h3><h4>3.1 Tracking experiments</h4><p>Tracking experiments is as simple as doing this:</p><pre><strong>with</strong> mlflow<strong>.</strong>start_run() <strong>as</strong> run:<br>   rfr <strong>=</strong> RandomForestRegressor(<strong>**</strong>params)<strong>.</strong>fit([[0, 1]], [1])<br>   mlflow<strong>.</strong>log_params(params)<br>   mlflow<strong>.</strong>sklearn<strong>.</strong>log_model(rfr, artifact_path<strong>=</strong>&quot;sklearn-model&quot;)</pre><p>This will record all parameters used to create the RandomForest (including the default values) and upload the model fitted with some extra parameters like the train set scores, oob score, etc.</p><p>After doing this multiple times you can go to the dashboard, select the model that performs better and promote it to a mlflow model.</p><h4>3.2 Running models</h4><p>Once you have a model you can load it with the command line executable:</p><pre>mlflow models serve -m models:/model-name/version</pre><p>The model might or not might contain a conda.yaml file. If it contains a conda.yaml all the dependencies and the correct python version will be installed automatically, that means the inference environment will be the same the research environment used to train the model.</p><h3>4. What else can you do with mlflow?</h3><p>This is just an introduction to the many features mlflow offers. There are many more things you can do with it:</p><ul><li>Parameterized tasks</li><li>Execute jobs on kubernetes</li><li>Create docker files</li><li>Authenticated connection to the tracking server via http basic auth or ssl certificates</li><li>Dataset versioning</li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=414be83b33d2" width="1" height="1" alt=""><hr><p><a href="https://medium.com/deeplearningmadeeasy/mlflow-for-mlops-414be83b33d2">MLFlow for MLOps</a> was originally published in <a href="https://medium.com/deeplearningmadeeasy">Deep Learning made easy</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Sparsemax: from paper to code]]></title>
            <link>https://medium.com/deeplearningmadeeasy/sparsemax-from-paper-to-code-351e9b26647b?source=rss----50ba1a5b3417---4</link>
            <guid isPermaLink="false">https://medium.com/p/351e9b26647b</guid>
            <category><![CDATA[sparsemax]]></category>
            <category><![CDATA[pytorch]]></category>
            <category><![CDATA[paper-implementation]]></category>
            <category><![CDATA[deep-learning]]></category>
            <category><![CDATA[paper]]></category>
            <dc:creator><![CDATA[Alvaro Durán Tovar]]></dc:creator>
            <pubDate>Tue, 25 May 2021 14:30:01 GMT</pubDate>
            <atom:updated>2021-05-25T14:29:19.701Z</atom:updated>
            <content:encoded><![CDATA[<p>Here we are with another paper implementation. Veeeery slowly, but I’m on my way to implement TabNet paper. I think this will be the last component I need for it.</p><p>Paper: <a href="https://arxiv.org/abs/1602.02068">From Softmax to Sparsemax: A Sparse Model of Attention and Multi-Label Classification</a></p><p>Another github repo implementing sparsemax:<br>* <a href="https://github.com/aced125/sparsemax">https://github.com/aced125/sparsemax</a></p><h3>What can we learn from implementing this paper?</h3><ol><li>A new layer capable of producing sparse outputs while being differentiable everywhere.</li><li>How to implement the backward step.</li><li>How check the gradient is correct.</li></ol><h3>1) Sparsemax, a new layer</h3><p>From the abstract:</p><blockquote>We propose sparsemax, a new activation function similar to the traditional softmax, but able to output sparse probabilities. […] We obtain promising empirical results in multi-label classification problems and in attention-based neural networks for natural language inference. For the latter, we achieve a similar performance as the traditional softmax, but with a selective, more compact, attention focus.</blockquote><p>So it can be an useful tool used on the intermediate layers (like for TabNet as an attention mechanism) or as the last layer for multi classification problems.</p><p>The algorithm is:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*yvXNlDvbRt6sWhmsp7K4Bw.png" /></figure><p>It’s pretty straight forward:</p><ol><li>Sort the input on descending order.</li><li>Find the maximum index (from the sorted set) that meets some condition.</li><li>Calculate the threshold (tau(z)).</li><li>Subtract the threshold to each element of the original set and apply relu operation (convert negative values to 0).</li></ol><p>A naive way of implementing it might look like this in numpy:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/85f9c433daa66a85ab911d0c7a77bb7e/href">https://medium.com/media/85f9c433daa66a85ab911d0c7a77bb7e/href</a></iframe><p>But this won’t work well when using a batch. With batch execution (2d case) where we have “columns” and “rows” looks as this in pytorch:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/50edb512532a8758b3b11870ebf13722/href">https://medium.com/media/50edb512532a8758b3b11870ebf13722/href</a></iframe><p>We can confirm it’s working fine by using the same test data with other existing implementations like I do on the demo notebook:…</p><h3>2) The backward step</h3><p>Typically custom pytorch functions are implemented this way:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/885340cb5d89300b6de35cb5883542fd/href">https://medium.com/media/885340cb5d89300b6de35cb5883542fd/href</a></iframe><p>ctx: is a “bag” where you can store information required for the backward step. So if you need something from the forward like the output, the input, etc you can store it on the “ctx” variable to use it later.</p><p>grad_output: the gradient of the previous step.</p><p>grad_input: the gradient of this function with respect to the output. Yeah it’s bit confusing to call something grad_input when is a variable you are returning.</p><p>Now the tricky thing is… how to implement it for sparsemax? On the paper you’ll find this formula that looks promising:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*YIFZjDQzFO5C96E9j1WDbw.png" /></figure><p>Ok, that’s the jacobian matrix of the function. Oh wait that’s sounds scary, what is a jacobian matrix? It’s a matrix composed of all partial derivatives of the output with respect to each element of the input.</p><p>Now that we have how to implement the backward step… not so fast! Actually if you implement that won’t work (trust me I already tried :D). We are missing to include the gradient of the previous step.</p><p>Lucky us the authors mention how to do it on the paper:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*0KU0F51IeD3LfrSXaqK7GQ.png" /></figure><p>It can be implemented like:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/6d856dac973dac750b73f4ab4199c56d/href">https://medium.com/media/6d856dac973dac750b73f4ab4199c56d/href</a></iframe><h3>3) Checking the gradient.</h3><p>Pytorch offers the function “pytorch.autograd.gradcheck” to check the gradients are correct: <a href="https://pytorch.org/docs/stable/autograd.html#torch.autograd.gradcheck">https://pytorch.org/docs/stable/autograd.html#torch.autograd.gradcheck</a></p><p>Using it is pretty straight forward.</p><h3>Conclusion</h3><p>Implementing the gradient is much easier than I expected.</p><p>Google colab notebook with the code:<br><a href="https://colab.research.google.com/drive/1YMIQgegWN2b_m1k5nwrOHOBd5B9ASV9E?usp=sharing">https://colab.research.google.com/drive/1YMIQgegWN2b_m1k5nwrOHOBd5B9ASV9E?usp=sharing</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=351e9b26647b" width="1" height="1" alt=""><hr><p><a href="https://medium.com/deeplearningmadeeasy/sparsemax-from-paper-to-code-351e9b26647b">Sparsemax: from paper to code</a> was originally published in <a href="https://medium.com/deeplearningmadeeasy">Deep Learning made easy</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Ghost BatchNorm explained]]></title>
            <link>https://medium.com/deeplearningmadeeasy/ghost-batchnorm-explained-e0fa9d651e03?source=rss----50ba1a5b3417---4</link>
            <guid isPermaLink="false">https://medium.com/p/e0fa9d651e03</guid>
            <category><![CDATA[deep-learning]]></category>
            <category><![CDATA[implementation]]></category>
            <category><![CDATA[ghost-batchnorm]]></category>
            <category><![CDATA[code]]></category>
            <category><![CDATA[paper]]></category>
            <dc:creator><![CDATA[Alvaro Durán Tovar]]></dc:creator>
            <pubDate>Thu, 17 Dec 2020 09:15:56 GMT</pubDate>
            <atom:updated>2020-12-17T09:15:09.717Z</atom:updated>
            <content:encoded><![CDATA[<h4>From paper to code</h4><p>Related papers:</p><ul><li><a href="https://arxiv.org/abs/1705.08741">https://arxiv.org/abs/1705.08741</a>: Train longer, generalize better: closing the generalization gap in large batch training of neural networks</li><li><a href="https://arxiv.org/abs/1908.07442">https://arxiv.org/abs/1908.07442</a>: TabNet: Attentive Interpretable Tabular Learning</li></ul><h3>Description</h3><p>This paper aims to solve the issue of the “generalization gap”. It seems neural networks tends to do worse for unseen data when being trained on large batch sizes.</p><p>One of the ways proposed to fix this is changing batchnorm layers from calculating statistics (remember BatchNorm layers changes the input data to make it “normally distributed”, 0 mean 1 standard deviation) from using the whole batch, to use small parts of the batch, what we can call <em>nano batches</em> (I just make it up, this term doesn’t appear on the paper).</p><h3>Why this work?</h3><p>It isn’t mentioned on the paper why this helps. My intuition is that as we will be changing small parts of the batch independently (and differently for each epoch) it’s like adding noise or maybe doing random data augmentation. We make it harder for the network to learn so it must become smarter!</p><blockquote>I wonder if it’s the same as adding different noise to different part of the batch</blockquote><p>Indeed it seems to be the case!! I did some tests on this colab notebook <a href="https://colab.research.google.com/drive/1cRNltVKTpkO47Wk85AaGPdmAkQmNHpyP#scrollTo=jtVydfmCY-2X">https://colab.research.google.com/drive/1cRNltVKTpkO47Wk85AaGPdmAkQmNHpyP#scrollTo=jtVydfmCY-2X</a> and found similar results between GhostBatchNorm and what I’ll call NoisyBatchNorm, a method to add different noise to different slices of the batch.</p><h3>The algorithm</h3><p>Now let go for the meat and potatoes. The algorithm from the paper:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*7tmr4nb5MB0egWLE9_gUow.png" /></figure><p>Might look bit cryptic, but the idea is simple.</p><ul><li>Calculate mean of each nano batch.</li><li>Calculate std of each nano batch.</li><li>Update running mean using an exponential moving average.</li><li>Update running std using an exponential moving average.</li><li>Return whole batch normalized.</li></ul><p>Knowing this the following image should be easier to understand:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*TyFA2MAt0m6mXdrt_hlLrA.png" /></figure><p>There is not much to say about mean and standard deviation, it’s what it is. Note the blue lines, I put them to make clear the <strong>𝜖</strong> is not inside the sum.</p><p>What does <strong>𝜖</strong> here? It helps with numerical stability. What if for whatever reason the operation under the square root is 0? Everything will fail. Instead adding a small value (like 1e-5) ensure we never have 0. This is one of those little details you must know when implementing papers, but it isn’t mentioned.</p><p>The exponential moving average is a simple trick to calculate a moving average using only the last value and the new value:</p><blockquote>momentum = 0.1<br>old * (1- momentum) + new * momentum</blockquote><h3>Reviewing the algorithm</h3><p>First of all this paper is pretty cool, I don’t consider myself smarter than the authors! But we all can make mistakes, that’s why there are reviews, etc. You can expect to see errors or things that aren’t well explained on papers (indeed papers have different versions with fixes). I think doing the following changes fix some problems with the original algorithm, missing/incorrect indexes.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*5Hra8rgnC6-_0qF6KaJ37w.png" /><figcaption>Look the red indexes.</figcaption></figure><h3>Implementation</h3><p>One naive way to implement this would be by doing everything with loops and that will be very very inefficient. Instead I’m going to show you the vectorized version directly:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/d8cc8ef521370ca21c72341fd07a441b/href">https://medium.com/media/d8cc8ef521370ca21c72341fd07a441b/href</a></iframe><p>And now the super simple &amp; smart way:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/192fa30059033a96ce102bcf8d939722/href">https://medium.com/media/192fa30059033a96ce102bcf8d939722/href</a></iframe><p>What a difference! This last option is pretty cool. It takes every nano batch and calls an embedded batchnorm, instead of re-implenting batchnorm from scratch. This is from <a href="https://github.com/dreamquark-ai/tabnet/blob/develop/pytorch_tabnet/tab_network.py#L21">pytorch-tabnet</a> repo.</p><h4>Benchmark time</h4><p>Which option is faster? Running both versions gives me this:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*3udUjFHTFzzjt7DiuQUjPg.png" /></figure><p>We can see for ghost batch sizes (&lt; 512) the vectorized version is faster because we aren’t using loops, and as we get closer to the real batch size the second option (calling a batchnorm layer multiple times) is better. This is due to the fact that the pytorch implementation of batchnorm is highly optimized in C.</p><h3>Conclusions</h3><ul><li>Implementing papers can be pretty hard, even for simple algorithms like this one. Isn’t always easy to explain with math what you can explain quite easily with few words.</li><li>It’s worth it to know how to write vectorized code, the improvement can be substantial.</li><li>If you want to use large batch sizes consider using GhostBatchNorm.</li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=e0fa9d651e03" width="1" height="1" alt=""><hr><p><a href="https://medium.com/deeplearningmadeeasy/ghost-batchnorm-explained-e0fa9d651e03">Ghost BatchNorm explained</a> was originally published in <a href="https://medium.com/deeplearningmadeeasy">Deep Learning made easy</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[GLU: Gated Linear Unit]]></title>
            <link>https://medium.com/deeplearningmadeeasy/glu-gated-linear-unit-21e71cd52081?source=rss----50ba1a5b3417---4</link>
            <guid isPermaLink="false">https://medium.com/p/21e71cd52081</guid>
            <category><![CDATA[paper]]></category>
            <category><![CDATA[gated-linear-unit]]></category>
            <category><![CDATA[activation-functions]]></category>
            <category><![CDATA[deep-learning]]></category>
            <dc:creator><![CDATA[Alvaro Durán Tovar]]></dc:creator>
            <pubDate>Thu, 03 Dec 2020 16:21:52 GMT</pubDate>
            <atom:updated>2020-12-07T07:23:33.177Z</atom:updated>
            <content:encoded><![CDATA[<h3>GLU: Gated Linear Unit implementation</h3><p>From paper to code</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*2d2xoFJrtXovUExrr0SjvA.jpeg" /><figcaption>Photo by <a href="https://unsplash.com/@pechka?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Dima Pechurin</a> on <a href="https://unsplash.com/s/photos/door?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure><p>I have started looking into an architecture called TabNet that aims for tabular problems interpretability. As part of it I’ll do couple of posts about some of its components, in this case about GLU activation (gated linear units). Next one will be about Ghost BatchNorm.</p><h3>Gated Linear Unit</h3><p>Related papers:<br>* TabNet: <a href="https://arxiv.org/abs/1908.07442">https://arxiv.org/abs/1908.07442</a><br>* Language modeling with Gated Convolutional Networks: <a href="https://arxiv.org/abs/1612.08083">https://arxiv.org/abs/1612.08083</a></p><p>The idea is simple. I want to allow the network to decide how much information should flow through a given path, like a logical gate, hence the name. How?</p><ul><li>If we multiply X by 0, nothing passes.</li><li>If we multiply X by 1, everything passes.</li><li>If we multiply X by 0.5, half of it passes.</li><li>…</li></ul><p>Does this reminds you something? It does right? LSTMs! Because it’s inspired by the idea of the gates of LSTMs, but applied to convolutions and linear layers, but it’s the same idea.</p><blockquote>How can we obtain a value between 0 and 1?</blockquote><p>C’mon that’s an easy one!… Yes! The sigmoid function!</p><h3>Implementation</h3><p>The formula from the paper looks as this:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/820/1*EwUvi3ATcVoa9Lm-2FwNUA.png" /></figure><p>Sigma means the sigmoid function. So we have two set of weights <strong>W</strong> and <strong>V</strong>, and two biases, <strong>b</strong> and <strong>c</strong>. One naive way to implement this is:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*4UZTVLQZSDV7gCsw2cn16Q.png" /></figure><ul><li>X*W + b is just a linear transformation, we can use a linear layer for it.</li><li>Same for X*V + c.</li><li>Then apply the sigmoid to one of them and we are done.</li></ul><h4>Making it faster</h4><p>I said naive because there is a better (faster) way to implement it, using a fancy name like FastGLU it becomes:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*NFuBHuB-8eOyzbNRq4C5dQ.png" /></figure><p>What’s the difference? On the first snippet we do two matrix multiplications (when calling <em>linear1</em> and <em>linear2</em>), and for this last one only one matrix multiplication, followed by splitting the output appropriately, but it’s the same thing.</p><h4>How well does this compared with other activations?</h4><p>From the paper:</p><blockquote>[…]<br>In contrast, the gradient of the gated linear unit ∇[X ⊗ σ(X)] = ∇X ⊗ σ(X) + X ⊗ σ 0 (X)∇X (3) has a path ∇X ⊗ σ(X) without downscaling for the activated gating units in σ(X). This can be thought of as a multiplicative skip connection which helps gradients flow through the layers.<br>[…]</blockquote><p>It reminds me ResNets.</p><h4>Experiment time</h4><p>I run some experiments to know what will happen if I compare it other activations: Sigmoid (because we are using a sigmoid here) and ReLU (because is the de facto standard).</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*r9V1UqJ4E2Byz3NA0zLjQQ.png" /></figure><p>If we ignore green and purple by now (2 linear layers + relu) we can see that FastGLU and SlowGLU versions perform quite similar, and better than the sigmoid version.</p><p>The purple line is so bumpy because values are too small (y axis is in log scale), it doesn’t really change much. Green line suffers from dead relus (must read <a href="https://medium.com/@karpathy/yes-you-should-understand-backprop-e2f06eab496b">https://medium.com/@karpathy/yes-you-should-understand-backprop-e2f06eab496b</a>).</p><p>Notebook can be found here: <a href="https://github.com/hermesdt/machine_learning/blob/master/GLU.ipynb">https://github.com/hermesdt/machine_learning/blob/master/GLU.ipynb</a></p><h4>Conclusions</h4><p>Not much conclusions to made from this to be honest, but here are some:</p><ul><li>ReLU actually for this specific case did amazingly well, but it’s very unstable. This is just a toy to play with, but still this applies to real world project, there is no silver bullet.</li><li>GLU is far more stable than ReLU and learns faster than sigmoid.</li><li>I already tried with other fancy activations like Mish, not better than GLU here.</li><li>Watch out for dead ReLU.</li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=21e71cd52081" width="1" height="1" alt=""><hr><p><a href="https://medium.com/deeplearningmadeeasy/glu-gated-linear-unit-21e71cd52081">GLU: Gated Linear Unit</a> was originally published in <a href="https://medium.com/deeplearningmadeeasy">Deep Learning made easy</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[List of deep learning losses for regression]]></title>
            <link>https://medium.com/deeplearningmadeeasy/list-of-deep-learning-losses-for-regression-7b1bb22f5f71?source=rss----50ba1a5b3417---4</link>
            <guid isPermaLink="false">https://medium.com/p/7b1bb22f5f71</guid>
            <category><![CDATA[regression]]></category>
            <category><![CDATA[numpy]]></category>
            <category><![CDATA[pytorch]]></category>
            <category><![CDATA[deep-learning]]></category>
            <dc:creator><![CDATA[Alvaro Durán Tovar]]></dc:creator>
            <pubDate>Tue, 01 Dec 2020 21:00:20 GMT</pubDate>
            <atom:updated>2021-04-24T13:25:39.197Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*fE8LcR2i_lusGoHtjMaMgw.jpeg" /><figcaption>Photo by <a href="https://unsplash.com/@markusspiske?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Markus Spiske</a> on <a href="https://unsplash.com/s/photos/meter?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure><h4>Mean absolute value</h4><p>Useful when having outliers but you don’t want them to have a big influence.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/390/1*fYNhlncTwLYqUl-_H6YElA.png" /></figure><blockquote>(y-ŷ).abs().mean()</blockquote><p>Couple downsides with this loss:</p><ul><li>The derivative is always the same (+/- 1).</li><li>The function isn’t differentiable at 0.</li></ul><p>Huber loss is a good alternative for this reasons.</p><h4>Mean squared error</h4><p>Useful when you want to penalize big differences (high errors).</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/638/1*5k3cfkLDu_EH88kzynqBjA.gif" /></figure><blockquote>(y-ŷ).pow(2).mean()</blockquote><h4>Root mean squared error</h4><p>The problem with MSE is that the obtained value is not in the original unit but on the root of the original unit, that means if we are using seconds, the value will be in seconds², which isn’t really useful.</p><p>To recover the original unit we take the square root obtaining something like an average where we strongly penalize big values. RMSE can be useful to use on reports in combination with other metrics like the MAE.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/412/1*RSYTYpqyGDYWPmI0rD8zqA.png" /></figure><blockquote>(y-ŷ).pow(2).mean().sqrt()</blockquote><h4>Huber loss</h4><p>Similar to MAE, but differentiable everywhere with a smooth change in trend near 0. Stronger against outliers than MSE. It’s like a combination of L1 and L2 (MAE and MSE), depending on the magnitude of the difference between the target value and the predicted value. <strong>𝛿 </strong>is another hyperparameter that indicates where to start applying a calculation similar to L2 (when approaching 0), L1 like otherwise.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*vAwUT5HCXr9LWHs1srZUBA.png" /></figure><blockquote>delta = 1<br>mask = (y — ŷ).abs() &lt;= delta</blockquote><blockquote>up = (0.5 * (y — ŷ)**2) * mask<br>down = (delta * (y -ŷ).abs() — 0.5 * delta**2) * ~mask<br>(up + down).mean()</blockquote><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ZgOn0Gs0k5pEj2F9TDsVLA.png" /></figure><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=7b1bb22f5f71" width="1" height="1" alt=""><hr><p><a href="https://medium.com/deeplearningmadeeasy/list-of-deep-learning-losses-for-regression-7b1bb22f5f71">List of deep learning losses for regression</a> was originally published in <a href="https://medium.com/deeplearningmadeeasy">Deep Learning made easy</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 losses for classification & probabilities]]></title>
            <link>https://medium.com/deeplearningmadeeasy/deep-learning-losses-for-classification-probabilities-154f6d98fe61?source=rss----50ba1a5b3417---4</link>
            <guid isPermaLink="false">https://medium.com/p/154f6d98fe61</guid>
            <category><![CDATA[pytorch]]></category>
            <category><![CDATA[deep-learning]]></category>
            <category><![CDATA[classification]]></category>
            <category><![CDATA[loss-function]]></category>
            <category><![CDATA[probability]]></category>
            <dc:creator><![CDATA[Alvaro Durán Tovar]]></dc:creator>
            <pubDate>Tue, 01 Dec 2020 20:36:25 GMT</pubDate>
            <atom:updated>2020-12-01T20:36:04.503Z</atom:updated>
            <content:encoded><![CDATA[<p>An unified view</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*hcKZe4hkZyfRbDcQlEgogw.jpeg" /><figcaption>Photo by <a href="https://unsplash.com/@jankolar?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Jan Antonin Kolar</a> on <a href="https://unsplash.com/s/photos/sorting?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure><h3>Classification &amp; Probability</h3><p>Classification &amp; Probability? Why mix both? Well, because classification indeed can be thought as fitting a probability distribution, bear with me. I’ll comment a bit about how to fit distributions and then relate it to classification.</p><h4>Probability</h4><p>The loss used for fitting a probability distribution is the <em>negative log likelihood</em>, I explain it with more detail <a href="https://medium.com/deeplearningmadeeasy/negative-log-likelihood-6bd79b55d8b6">here</a>. What it does is given a distribution defined by some parameters (obtained from the output of a NN in this case), what is the probability of observing, (the target / label) Y? And then update the parameters through backpropagation in the direction where we maximize the probability of observing Y with a different set of parameters.</p><p>The observation Y won’t change obviously, as we want something that can fit as best as possible the generation of those observed Y (for future inference), we will change the parameters towards increasing the likelihood of obtaining those observations if sampling from the probability distribution.</p><p>One last time, we want a probability distribution parameterized from past data to predict some future data Y given some input X.</p><p>Each probability distribution have a different maximum likelihood estimation function, so I’m not going to enter into more detail here but we can reduce the general case to the following, where “p” is the maximum likelihood estimation function (I’m omitting the parameters of the distribution) (some examples <a href="http://jrmeyer.github.io/machinelearning/2017/08/18/mle.html">gaussian</a>, <a href="https://math.stackexchange.com/questions/2725539/maximum-likelihood-estimator-of-categorical-distribution">categorical</a>, <a href="https://www.statlect.com/fundamentals-of-statistics/Poisson-distribution-maximum-likelihood">poisson</a>…):</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/498/1*Q2Q7TuORw9si1_d1lxxyJA.png" /></figure><p>And we are lucky because deep learning frameworks already provides them!</p><h4>Classification</h4><p>Classification can be seen as using probability distributions, for the binary case we have the bernoulli distribution, for multi-class we have the categorical distribution, and you can think on the binary case as a special case of the multi-class classification.</p><p>If we have a probability distribution we know we can fit it with the negative log likelihood as mentioned above.</p><p>Also you probably already know we also have cross entropy and binary cross entropy. More weirds terms! Why?! :’(… Don’t worry, <strong>although cross entropy and NLL isn’t the same, for our case it’s the same </strong>(very well explained <a href="https://machinelearningmastery.com/cross-entropy-for-machine-learning/">here</a>), or better say the math formulas at the end simplify to the exact same thing, therefore cross entropy = binary cross entropy = NLL. They just exposes different apis, but they are the same at the end. Don’t you believe me? Take a look on the following code:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/a0fb78219c769450e83e08d83553c220/href">https://medium.com/media/a0fb78219c769450e83e08d83553c220/href</a></iframe><p>Why so many options for doing the same thing? Depending on the use case you want to use one or the other. Binary? Multi class? Logits? Normalized? …</p><p>Why negative on the “negative log likelihood”? Because the frameworks usually only implements miniziation, so we maximize the likelihood by minimizing the negative value.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=154f6d98fe61" width="1" height="1" alt=""><hr><p><a href="https://medium.com/deeplearningmadeeasy/deep-learning-losses-for-classification-probabilities-154f6d98fe61">Deep learning losses for classification &amp; probabilities</a> was originally published in <a href="https://medium.com/deeplearningmadeeasy">Deep Learning made easy</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[DeepFactors for forecasting, architecture review]]></title>
            <link>https://medium.com/deeplearningmadeeasy/deepfactors-for-forecasting-architecture-review-e8b4c72b887c?source=rss----50ba1a5b3417---4</link>
            <guid isPermaLink="false">https://medium.com/p/e8b4c72b887c</guid>
            <category><![CDATA[forecasting]]></category>
            <category><![CDATA[timeseries]]></category>
            <category><![CDATA[deep-learning]]></category>
            <category><![CDATA[mxnet]]></category>
            <category><![CDATA[data-science]]></category>
            <dc:creator><![CDATA[Alvaro Durán Tovar]]></dc:creator>
            <pubDate>Fri, 13 Nov 2020 20:58:23 GMT</pubDate>
            <atom:updated>2020-12-01T20:40:47.721Z</atom:updated>
            <content:encoded><![CDATA[<p>Today I’m going to be reviewing a deep learning model architecture for forecasting.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*DBOBgY6vgOIRgNz5OtUt-A.jpeg" /><figcaption>Photo by <a href="https://unsplash.com/@jplenio?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Johannes Plenio</a> on <a href="https://unsplash.com/s/photos/storm?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure><p>Until M4 competition everyone thought that traditional statistic models were superior for forecasting, as happened with many other fields I would say. Today it seems deep learning is the best solution almost always… at least having enough data. Traditional forecasting techniques like ARIMA, etc seems to be doing better for small datasets still.</p><p>What about huge datasets where we have many different time series? Like amazon for example, or any retail business. Would be amazing to be able to throw all of that into a model and make predictions for each product/user/… individually.</p><p>And would even better to be able to use exchangeable time series. Like we have the history for a given author, probably another book of the same author of the same topic will have similar evolution, or a book from another author but same topic.</p><p>And even better if we can solve the cold start problem for fresh new products for which we have similar data.</p><p>Too good to be true… well actually that’s what DeepFactors does!</p><p>Paper <strong>Deep Factors for Forecasting</strong>: <a href="https://arxiv.org/abs/1905.12417">https://arxiv.org/abs/1905.12417</a><br>Older paper about the same architecture: <a href="https://arxiv.org/abs/1812.00098">https://arxiv.org/abs/1812.00098</a></p><p>I have to recognize I struggled to understand it (well that happens to me with all papers...), so to make it easier for you here you have a comprehensive list of terms, but first some excerpt from the paper:</p><blockquote>Our new method is data-driven and scalable via a latent, global, deep component. It also handles uncertainty through a local classical model. We provide both theoretical and empirical evidence for the soundness of our approach through a necessary and sufficient decomposition of exchangeable time series into a global and a local part. Our experiments demonstrate the advantages of our model both in term of data efficiency, accuracy and computational complexity.<br>[…]<br>In this paper, we propose a novel global-local method, Deep Factor Models with Random Effects. It is based on a global DNN backbone and local probabilistic graphical models for computational efficiency. The global-local structure extracts complex non-linear patterns globally while capturing individual random effects for each time series locally.</blockquote><p>Fixed? Random? Global? Local? What’s that?</p><ul><li><strong>Fixed effect model</strong>: This just means that the model is deterministic, the output is always the same for the same input.</li><li><strong>Random effect model</strong>: The output is random, based on some probability distribution, ie. non deterministic.</li><li><strong>Global model</strong>: In this case refers to a model that learns some information shared across many time series.</li><li><strong>Local model</strong>: One model per time serie. Traditional statistical methods such as ARIMA are of this type.</li><li><strong>Global-local</strong>: Some sort of combination of shared high level information between time series and specific information for each specific time serie. First the global information is calculated and used to predict the local, specific, time serie.</li></ul><h3>Architecture</h3><p>In the following graph we have the theoretical architecture of the model. Note about “g” and “r”.</p><p>g: global effect, common for all (no i subindex).<br>r: random effect, specific for each one.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/416/1*vl5Y6NLosq6A-hQzNixWpQ.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/644/1*7-fyUZWOEv1gmwR1yPwXew.png" /></figure><p>Ok, not much to say about it, you have all you need to understand it on the paper. Let take a look on the implementation on gluon-ts.</p><h3>DeepFactors gluon-ts architecture</h3><p>The following schemas is based on gluon-ts <a href="https://github.com/awslabs/gluon-ts/tree/6287a4a38b549340ed9b49546e2e25c605c83e82/src/gluonts/model/deep_factor">repo code</a>. I always find useful to see how to implement the esotherical maths from the papers.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*OxzcJWaaJ-3ppIBnZRu8FQ.png" /></figure><p>Global model: The global model only receives the time features, that is, the time series past data plus some other useful features like hour of the day, day of the week, etc.</p><p>Deep Factors: The global deep factors comes from applying a matrix multiplication to the output of the LSTM, that’s almost the same as saying that we project that output into a different dimensional space, on the paper they use 10 as the rank of this new space.</p><p>Fixed effects: Now given those global factors we want to use them differently per category, therefore an attention block with the categories as input is used. The use of the category through an embedding layer should help to focus on different parts of the factors for each exchangeable time serie.</p><p>And with all of this we have the deterministic part of the model, the average without any kind of uncertainty associated. The output is 1 number per batch item.</p><p>Random effects: This is calculated from a combination of input features concatenated with the embedding of the category. The output is 1 number per batch item.</p><p>And now we have 2 numbers we can use as parameters of a gaussian distribution (code based on the gaussian process alternative).</p><h3>Improvements</h3><p>I’m far from being smarter than the people that coded this beautiful thing, but there are somethings I would like to try to see if it helps:</p><ul><li>QRNNs: <a href="https://arxiv.org/abs/1611.01576">https://arxiv.org/abs/1611.01576</a> Improved training speed.</li><li>Activations: There are no activation layers in any part if I understood the code correctly.</li><li>Different embedding objects for the fixed effects module and the random effects module. It’s shared on gluon-ts.</li><li>Forcing the standard deviation, the output of the random effects module, to be higher than 0 always (using mx.nd.clip for example). On gluon-ts they use this neat trick:</li></ul><blockquote>log(exp(x) + 1)</blockquote><p>That function have an asymptote on 0, should never be 0. But it can be so close to 0 that for a computer it’s indeed 0, causing NaNs.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=e8b4c72b887c" width="1" height="1" alt=""><hr><p><a href="https://medium.com/deeplearningmadeeasy/deepfactors-for-forecasting-architecture-review-e8b4c72b887c">DeepFactors for forecasting, architecture review</a> was originally published in <a href="https://medium.com/deeplearningmadeeasy">Deep Learning made easy</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[The difference between the mean and the median.]]></title>
            <link>https://medium.com/deeplearningmadeeasy/the-difference-between-the-mean-and-the-median-aa39c42f8e4a?source=rss----50ba1a5b3417---4</link>
            <guid isPermaLink="false">https://medium.com/p/aa39c42f8e4a</guid>
            <category><![CDATA[median]]></category>
            <category><![CDATA[deep-learning]]></category>
            <category><![CDATA[mean]]></category>
            <category><![CDATA[machine-learning]]></category>
            <category><![CDATA[statistics]]></category>
            <dc:creator><![CDATA[Alvaro Durán Tovar]]></dc:creator>
            <pubDate>Mon, 12 Oct 2020 20:14:43 GMT</pubDate>
            <atom:updated>2020-10-12T20:13:04.109Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*-htvtgU_w3oFgoJp-g2VUg.jpeg" /><figcaption>Photo by <a href="https://unsplash.com/@chrisliverani?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Chris Liverani</a> on <a href="https://unsplash.com/?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure><p>Both aims to represent the “center” of some data. A proper way to define them might be that they define the location of a distribution, defining location as the middle point of it, or the position at which most of the data is located.</p><h3>What’s the mean?</h3><p>First thing to say is that there are multiple kinds of means, the most common is called the <em>arithmetic mean</em>, but there are others called <em>geometric mean</em>, <em>weighted mean</em>, <em>harmonic mean</em> or even the <em>root mean square</em>… all trying to summarize some sense os “middle” of the data considering the whole data, in different ways.</p><p>And that’s the key difference with the median. All previous kinds of means mentioned above are calculated considering the whole data you have available:</p><ul><li>Sum everything and divide by it’s cardinality…</li><li>Multiply everything…</li><li>square everything, sum it and then apply root square…</li></ul><p>Doing some calculation over each data point and reducing it into 1 number. For the arithmetic mean, the “standard” we typically use, the formula is as:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/576/1*KbzrzPi88aRJIzs4YA5s4A.png" /></figure><h3>What’s the median?</h3><p>The median give us another way to get the center of the data, and it’s literally the center. The median is calculated by ordering all numbers and finding the value at the middle. Some examples:</p><ul><li>The median of [0,1,2,3,4] is 2.</li><li>The median of [100, 1000, 10000, 100000, 1000000] is 10000.</li><li>The median of [-100, -5, -4.3, 1.2, 1.8] is -4.3.</li></ul><p>That was simple because we have an odd number of numbers (take the one in the middle), but what if we have an even number of numbers? Then we take the two that falls on the center and calculate the arithmetic mean:</p><ul><li>The median of [0, 1, 2, 3] is 1.5.</li><li>The median of [100, 1000, 10000, 100000] is 5500.</li><li>The median of [-100, -5, -4.3, 1.2] is -4.65.</li></ul><h3>Normal distribution</h3><p>A normal distribution is parameterized by the mean and the standard deviation, sometimes called location and scale. For this distribution the mean and the median falls in the same place, why? Because it’s symmetrical:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/940/1*2__r1FDt7jsdryydVr4q3w.png" /></figure><h3>Other distributions</h3><p>For other distributions we can see the mean is shifted towards the tail.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*i3IstXnQVuWGa_b39I66rw.png" /></figure><p>And here you can start to have an idea of why this is important. If we have extreme values the mean will move, while the median not. Classic example:</p><blockquote>There are 4 guys on a pub drinking a pint of beer. To keep it simple say all of them have a monthly income of 1,000€. The mean is 1,000€ and the median is 1,000€.</blockquote><blockquote>Then Bill Gates enters the pub, say he have a monthly income of 1,000,000€ (who knows!).</blockquote><blockquote>Now the mean is 200,800€, while the median is still 1,000€.</blockquote><p>In cases like this where you have big outliers you should be using the median most likely to have a sense of where is the “middle”.</p><h3>When to use each</h3><p>Having outliers isn’t bad per se and something to avoid at all cost. For example on my job we have done a small change recently that might increase delivery times (it’s a logistic company) in some circumstances by a bit, should I be monitoring the median or the mean? Actually you want to monitor both:</p><ul><li>If the mean goes up means we have extreme values more often or extreme values have gone more extreme if possible.</li><li>If the median goes up means the whole data pattern has changed, everything seems to be affected.</li></ul><p>Monitoring the mean is useful to have a sense of how is the data distributed.</p><p>Monitoring the median is useful to have a sense of where is the exact midpoint of your data, if it changes something is changing your whole dataset rather than just affecting a subset of it. At the same time, if you don’t want to consider outliers typically the median is the better option.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=aa39c42f8e4a" width="1" height="1" alt=""><hr><p><a href="https://medium.com/deeplearningmadeeasy/the-difference-between-the-mean-and-the-median-aa39c42f8e4a">The difference between the mean and the median.</a> was originally published in <a href="https://medium.com/deeplearningmadeeasy">Deep Learning made easy</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[The reparameterization trick with code example]]></title>
            <link>https://medium.com/deeplearningmadeeasy/the-reparameterization-trick-with-code-example-abe5915c753d?source=rss----50ba1a5b3417---4</link>
            <guid isPermaLink="false">https://medium.com/p/abe5915c753d</guid>
            <category><![CDATA[deep-learning]]></category>
            <category><![CDATA[machine-learning]]></category>
            <category><![CDATA[variational-autoencoder]]></category>
            <category><![CDATA[reparameterization-trick]]></category>
            <category><![CDATA[example]]></category>
            <dc:creator><![CDATA[Alvaro Durán Tovar]]></dc:creator>
            <pubDate>Mon, 08 Jun 2020 20:16:51 GMT</pubDate>
            <atom:updated>2020-06-08T20:16:32.935Z</atom:updated>
            <content:encoded><![CDATA[<p>First time I hear about this (well, actually first time it was readen…) I didn’t have any idea about what was it, but hey! it sounds pretty cool!</p><p>Very likely if you are reading this you already have some idea about this topic: <strong>it’s a way to use backpropagation when using random sampling.</strong></p><p>That’s the thing, you can’t backpropagate when you pick up random numbers. Randomness on a computer usually means reading the voltage of some component, using the internal clock… some interaction with the world. There is no way to calculate the derivative of that.</p><p>This happens if we use variational auto-encoders for example, and maybe with bayesian networks? Things like that. This happens when:</p><ul><li>We obtain a probability distribution. Another non typical example: <a href="https://openai.com/blog/better-exploration-with-parameter-noise/">noise layers for DQN</a>.</li><li>We sample from the distribution.</li><li>We use the sampled value as the input for another layer.</li></ul><p>Then at some point we want to backpropagate, how do we propagate through a random number? ¯\_(ツ)_/¯</p><h4>De-Standarization of the distribution</h4><p>Say we have a normal distribution as N(10, 5), that means mean 10, standard deviation 5 (I prefer to read as location 10 and scale 5). It’s the same as doing:</p><p>N(0, 1) *5 + 10</p><p>Don’t you believe me? Here you have an example with numpy:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/bfb12548840db07f702fc774e29c6c4e/href">https://medium.com/media/bfb12548840db07f702fc774e29c6c4e/href</a></iframe><p>We just de-standarized the data. <strong>Instead of making it 0 mean 1 std, we did the opposite</strong>, we moved and scaled somewhere else. Do you know who is very good at discovering where is that somewhere else? Neural networks, among others.</p><p>So trick is as follows (for a normal distribution):</p><ul><li>Obtain new mean.</li><li>Obtain new std.</li><li>Apply those to a batch of random numbers from a N(0, 1) distribution.</li></ul><p>The network will decide how shift and scale the distribution on it’s own. Then you can propagate the gradient of the number acting as the mean and the number acting as the std. Of course this have several implications that I’m not smart enough to even try to explain it, so I’m not going to do it.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*tlVW3IaQ6zDIlunE1IOw0A.png" /><figcaption>Examples of how reparameterization works on standard normal distribution.</figcaption></figure><h4>Code example</h4><p>An example might look like this:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/cc56df18c96710c56b3fcf3b06934af1/href">https://medium.com/media/cc56df18c96710c56b3fcf3b06934af1/href</a></iframe><p>As you can see from a linear layer we obtain the scale and location and apply those a batch of random samples from a N(0, 1) distribution.</p><h4>Working example</h4><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/e5e6034d9930a133229580c4fad471dc/href">https://medium.com/media/e5e6034d9930a133229580c4fad471dc/href</a></iframe><p>You should try without BatchNorm as I think it might be able to predict sin function on it’s own because of its internal affine transformation matrix.</p><p>NOTE: I had to scale the input to make it 0–1, I couldn’t make it work without it.</p><h4>Does this work for other distributions?</h4><p>In theory yes according to <a href="https://stats.stackexchange.com/a/368199">this stack overflow answer</a> although doesn’t look straightfoward at all.</p><p>Variational autoencoders paper: <a href="https://arxiv.org/abs/1312.6114">https://arxiv.org/abs/1312.6114</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=abe5915c753d" width="1" height="1" alt=""><hr><p><a href="https://medium.com/deeplearningmadeeasy/the-reparameterization-trick-with-code-example-abe5915c753d">The reparameterization trick with code example</a> was originally published in <a href="https://medium.com/deeplearningmadeeasy">Deep Learning made easy</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>