<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

 <title>moto's blog</title>
 <link href="https://mthrok.github.io/ml-blog/atom.xml" rel="self"/>
 <link href="https://mthrok.github.io/ml-blog/"/>
 <updated>2018-04-07T22:23:57+00:00</updated>
 <id>https://mthrok.github.io</id>
 <author>
   <name>moto</name>
   <email>mthrok@gmail.com</email>
 </author>

 
 <entry>
   <title>What Dense Layer is Capable of Pt. 2</title>
   <link href="https://mthrok.github.io/ml-blog/deep_learning/dense/2018/04/08/what-dense-layer-is-capable-of-pt2/"/>
   <updated>2018-04-08T00:00:00+00:00</updated>
   <id>https://mthrok.github.io/deep_learning/dense/2018/04/08/what-dense-layer-is-capable-of-pt2</id>
   <content type="html">&lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js?config=TeX-AMS-MML_HTMLorMML&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt;

&lt;p&gt;
  In &lt;a href=&quot;/ml-blog/deep_learning/dense/2018/04/01/what-dense-layer-is-capable-of/&quot;&gt;the previous post&lt;/a&gt;, we built a simple linear regression model that maps one-hot vector to its label value. In this post, we build a model that reverse this operation.
&lt;/p&gt;

&lt;h2&gt;Problem&lt;/h2&gt;

&lt;p&gt;
  Let's build a unit vector from scalar value.
&lt;/p&gt;

$$
\begin{bmatrix}
1\\
2\\
3
\end{bmatrix}
\rightarrow
\begin{bmatrix} 
[1 &amp; 0 &amp; 0] \\
[0 &amp; 1 &amp; 0] \\
[0 &amp; 0 &amp; 1]
\end{bmatrix}
$$

&lt;!--more--&gt;

&lt;p&gt;
  This is not linearly solvable. We need to introduce non-linearity that surpress output in parts of regions.
&lt;/p&gt;

$$
\begin{align}
\mathbf{h} &amp; = \sigma (
  x \cdot \mathbf{v} + \mathbf{b}_1
) \\
\mathbf{y} &amp; = \mathbf{h} W + \mathbf{b}_2
\end{align}
$$

&lt;p&gt;
  Which can be implemented in Tensorflow as follow.
&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;n&quot;&gt;intermediate_variable&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tf&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;layers&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dense&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;input_variable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;units&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n_intermediate_dim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;use_bias&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;activation&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;activation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;output_variable&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tf&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;layers&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dense&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;intermediate_variable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;units&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n_output_dim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;use_bias&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;
  You can find the code for the experiment &lt;a href=&quot;https://github.com/mthrok/ml-blog&quot;&gt;here&lt;/a&gt;.
&lt;/p&gt;

&lt;p&gt;
  How does this model work? If we look at the each dimension of the output vector separately, we notice that they take non-zero value only when input scalar value is in certain region. This is not linear. To break the linear relationship, we pass this data point through an activation function. Then in the second dense layer activated values are combined to form the final input.
&lt;/p&gt;

&lt;h2&gt;Experiment&lt;/h2&gt;

&lt;p&gt;
  As I run some experiments, it turned out that each activation function has its preferred input value range where it can perform the task better. So in this experiment, linear scaling is added before the first dense layer. Loss type is L2. With L1, the model does not converges to global optima. Optimizer is Adam as Gradient Descent is very slow.
&lt;/p&gt;

&lt;center&gt;
  &lt;iframe
    width=&quot;630&quot; height=&quot;620&quot; align=&quot;middle&quot; frameborder=&quot;0&quot;
    src=&quot;/ml-blog/assets/2018-04-08/exp1_loss.html&quot;&gt;
  &lt;/iframe&gt;
  &lt;div style=&quot;padding-bottom: 1em;&quot;&gt;
    &lt;small&gt;
      Loss value over training. We see plateaus and sudden improves. Relu family (Relu, Relu6, Softplus, Leaky Relu) stays plateau and not sure if they can converge.&lt;br&gt;
      Sigmoid and Tanh can converge well. ELU converges as well but was not very robust and scaling has to be performed in a specific way.
    &lt;/small&gt;
  &lt;/div&gt;
&lt;/center&gt;

&lt;center&gt;
  &lt;iframe
    width=&quot;425&quot; height=&quot;560&quot; align=&quot;middle&quot; frameborder=&quot;0&quot;
    src=&quot;/ml-blog/assets/2018-04-08/exp1_output.html&quot;&gt;
  &lt;/iframe&gt;
  &lt;div style=&quot;padding-bottom: 1em;&quot;&gt;
    &lt;small&gt;
      Model output throught the training. In each image path, each row corresponds to one model output (one-hot encoded vector).
    &lt;/small&gt;
  &lt;/div&gt;
&lt;/center&gt;

&lt;p&gt;
  What is happening inside? Why are Relu activations fail to converge? Let's take a look into the intermediate layer output.
&lt;/p&gt;

&lt;center&gt;
  &lt;iframe
    width=&quot;425&quot; height=&quot;430&quot; align=&quot;middle&quot; frameborder=&quot;0&quot;
    src=&quot;/ml-blog/assets/2018-04-08/exp1_intermediate.html&quot;&gt;
  &lt;/iframe&gt;
  &lt;div style=&quot;padding-bottom: 1em;&quot;&gt;
    &lt;small&gt;
      Output from the first dense layer (activation).
    &lt;/small&gt;
  &lt;/div&gt;
&lt;/center&gt;

&lt;p&gt;
  Each datapoint which is successfully converged, output has unique patterns. For the models which loss converged to zero, zero-crossing point of each intermediate feature's activation function can be found in the visualized range, but for the models which did not converge, some feature's zero-crossing point are outside of visualized range, meaning those features are not cotributing in the next layer.
&lt;/p&gt;
&lt;p&gt;
  In case of Tanh and Sigmoid activations, outputs from the intermediate layer take either 0 (-1 for Tanh) or 1. This means that what the model can output is bounded by the intermediate layer capacity.
&lt;/p&gt;

&lt;center&gt;
  &lt;iframe
    width=&quot;630&quot; height=&quot;620&quot; align=&quot;middle&quot; frameborder=&quot;0&quot;
    src=&quot;/ml-blog/assets/2018-04-08/exp2_loss.html&quot;&gt;
  &lt;/iframe&gt;
  &lt;div style=&quot;padding-bottom: 1em;&quot;&gt;
    &lt;small&gt;
      Loss for different number of intermediate features. Loss reaches 0 at 15, which is one smaller than the output dimension. 
    &lt;/small&gt;
  &lt;/div&gt;
&lt;/center&gt;
&lt;center&gt;
  &lt;iframe
    width=&quot;400&quot; height=&quot;620&quot; align=&quot;middle&quot; frameborder=&quot;0&quot;
    src=&quot;/ml-blog/assets/2018-04-08/exp2_output.html&quot;&gt;
  &lt;/iframe&gt;
&lt;/center&gt;

&lt;p&gt;
So activation functions over N intermediate features combined, the output space is devided into N + 1 regions as follow.
&lt;/p&gt;

&lt;center&gt;
  &lt;img src=&quot;/ml-blog/assets/2018-04-08/features.jpg&quot; alt=&quot;Combined features.&quot;&gt;
&lt;/center&gt;

&lt;h2&gt;Comments&lt;/h2&gt;
&lt;div class=&quot;blog-post-comments&quot;&gt;&lt;/div&gt;

&lt;script
  src=&quot;https://code.jquery.com/jquery-3.3.1.min.js&quot;
  integrity=&quot;sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=&quot;
  crossorigin=&quot;anonymous&quot;&gt;&lt;/script&gt;
&lt;script&gt;
const apiUrl = 'https://api.github.com/repos/mthrok/ml-blog/issues/3/comments'
$(function() { 
  $.ajax(apiUrl, {
    headers: {
        Accept: 'application/vnd.github.v3.html+json'
    },
    dataType: 'json',
    success: function(comments) {
      const $commentSection = $('.blog-post-comments')
      $commentSection.append(
      `
      &lt;a href=&quot;https://github.com/mthrok/ml-blog/issues/3#new_comment_field&quot;&gt;Visit GitHub to leave a comment.&lt;/a&gt;
      `
      )
      comments.forEach(function (comment) {
        $commentSection.append(
          `
          &lt;div class=&quot;comment&quot;&gt;
              ${comment.body_html}
              &lt;a class=&quot;commenter&quot; href=&quot;${comment.user.html_url}&quot; 
              target=&quot;_blank&quot;&gt;${comment.user.login}&lt;/a&gt;
              ${new Date(comment.created_at).toUTCString()}
          &lt;/div&gt;
          `
        )
      })
    }
  })
})	  
&lt;/script&gt;

</content>
 </entry>
 
 <entry>
   <title>What Dense Layer is Capable of</title>
   <link href="https://mthrok.github.io/ml-blog/deep_learning/dense/2018/04/01/what-dense-layer-is-capable-of/"/>
   <updated>2018-04-01T00:00:00+00:00</updated>
   <id>https://mthrok.github.io/deep_learning/dense/2018/04/01/what-dense-layer-is-capable-of</id>
   <content type="html">&lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js?config=TeX-AMS-MML_HTMLorMML&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt;

&lt;p&gt;
Building a new model in Deep Learning is not easy. Figuring out why a model is not acting as expected is difficult. It is important to know how what each component is capable of. Dense layer is one of the most fundamental component of Machine Learning. Here, we explore what it is capable of through series of simple and easy-to-interpret experiments.
&lt;/p&gt;

&lt;h2&gt;Problem&lt;/h2&gt;
&lt;p&gt;
Let's consider a model that maps one-hot vectors into indices.
&lt;/p&gt;

$$
\begin{bmatrix} 
[1 &amp; 0 &amp; 0] \\
[0 &amp; 1 &amp; 0] \\
[0 &amp; 0 &amp; 1]
\end{bmatrix}
\rightarrow
\begin{bmatrix}
1\\
2\\
3
\end{bmatrix}
$$

&lt;!--more--&gt;

&lt;p&gt;
This can be formulated as linear regression. It is easy to write this mapping in equation.
&lt;/p&gt;

$$
\mathbf{x}
\cdot
\begin{bmatrix}
1 \\
2 \\
3
\end{bmatrix}
\rightarrow
y
$$

&lt;p&gt;
And there are different ways to express the same mapping using bias term.
&lt;/p&gt;

$$
\mathbf{x}
\cdot
\begin{bmatrix}
-1 \\
0 \\
1
\end{bmatrix}
+
\begin{bmatrix}
2 \\
2 \\
2
\end{bmatrix}
\rightarrow
y
$$

&lt;h2&gt;Experiment&lt;/h2&gt;

&lt;p&gt;
This simple linear transformation is called Dense Layer or Fully-Connected Layer in Deep Learning, and in Tensorflow such model can be written as follow.
&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span class=&quot;n&quot;&gt;output_variable&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tf&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;layers&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dense&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;input_variablbe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;units&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n_dim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;activation&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;use_bias&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;use_bias&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;
You can find the code for the experiment &lt;a href=&quot;https://github.com/mthrok/ml-blog&quot;&gt;here&lt;/a&gt;.
&lt;/p&gt;

&lt;p&gt;
  Simple gradient descent is enough for finding the optima. The following figure shows training loss with different loss type and bias condition for 15 dimension case.
&lt;/p&gt;

&lt;center&gt;
  &lt;iframe
    width=&quot;630&quot; height=&quot;620&quot; align=&quot;middle&quot; frameborder=&quot;0&quot;
    src=&quot;/ml-blog/assets/2018-04-01/linear-regression-encoder-1d-loss-plot.html&quot;&gt;
  &lt;/iframe&gt;
  &lt;div style=&quot;padding-bottom: 1em;&quot;&gt;
    &lt;small&gt;
      Loss value over training. &lt;i&gt;Loss&lt;/i&gt; indicates the type of loss function; L1 or L2. &lt;i&gt;Bias&lt;/i&gt; indicates the initial bias value when used. &lt;i&gt;Shuffle&lt;/i&gt; indicates that input-to-output mapping was shuffled in deterministic way the training data. &lt;br&gt;You can click legend to hide/show the corresponding plot.
    &lt;/small&gt;
  &lt;/div&gt;
&lt;/center&gt;

&lt;p&gt;
  The following figure illustrates the model output through the training.
&lt;/p&gt;

&lt;center&gt;
  &lt;iframe
    width=&quot;630&quot; height=&quot;680&quot; align=&quot;middle&quot; frameborder=&quot;0&quot;
    src=&quot;/ml-blog/assets/2018-04-01/linear-regression-encoder-1d-plot.html&quot;&gt;
  &lt;/iframe&gt;
&lt;/center&gt;

&lt;p&gt;&lt;center&gt;&lt;small&gt;
      How a simple linear regression learns over the time. &lt;br&gt;
&lt;/small&gt;&lt;/center&gt;&lt;/p&gt;

&lt;h2&gt;Observation&lt;/h2&gt;

There are couple of interesting this we can observe.

&lt;ul&gt;
  &lt;li&gt;&lt;b&gt;Bias learns faster than kernel.&lt;/b&gt;&lt;/li&gt;
  &lt;p&gt;
    Bias terms converge to optima before kernel terms do.&lt;br&gt;
    You can disable plots other than &lt;i&gt;Loss: L2, Bias: [0.]&lt;/i&gt; to see this.
  &lt;/p&gt;
  &lt;li&gt;&lt;b&gt;Existence of bias does not affect the speed kernel fits.&lt;/b&gt;&lt;/li&gt;
  &lt;p&gt;
    Comparing the same loss type with/without bias term, the step model converges to the optima is same. &lt;br&gt;
    In fact the loss curve of &lt;i&gt;Bias: [0,]&lt;/i&gt; starts at the same loss as &lt;i&gt;Bias: None&lt;/i&gt; but quickly merges to &lt;i&gt;Bias: [6.]&lt;/i&gt;. For L2 loss types, all the training cases converge around 1000 trainings.
  &lt;/p&gt;
  &lt;li&gt;&lt;b&gt;Model cannot truely converge to optima when L1 loss is used.&lt;/b&gt;&lt;/li&gt;
  &lt;p&gt;
    With L1 loss, derivetive value is always constant and when that value is larger than the actual error, parameters keep crossing the optimal value and fructuates.
  &lt;/p&gt;
  &lt;li&gt;&lt;b&gt;Shuffling the output axis in arbitrary order does not affect model training.&lt;/b&gt;&lt;/li&gt;
  &lt;p&gt;
    When label values are shuffled in arbibtrary order, model training is not affected.
  &lt;/p&gt;
&lt;/ul&gt;

&lt;h2&gt;Extention&lt;/h2&gt;

&lt;p&gt;
Extending this to multi dimension, we get the same property on each axis independently.
&lt;/p&gt;

$$
\begin{bmatrix} 
\begin{bmatrix} 
1 &amp; 0 &amp; 0 \\
0 &amp; 1 &amp; 0 
\end{bmatrix} \\
\begin{bmatrix} 
1 &amp; 0 &amp; 0 \\
0 &amp; 0 &amp; 1
\end{bmatrix} \\
\begin{bmatrix} 
0 &amp; 0 &amp; 1 \\
1 &amp; 0 &amp; 0
\end{bmatrix}
\end{bmatrix}
\rightarrow
\begin{bmatrix}
[1 &amp; 2]\\
[1 &amp; 3]\\
[3 &amp; 1]
\end{bmatrix}
$$

&lt;center&gt;
  &lt;iframe
    width=&quot;630&quot; height=&quot;680&quot; align=&quot;middle&quot; frameborder=&quot;0&quot;
    src=&quot;/ml-blog/assets/2018-04-01/linear-regression-encoder-2d-loss-plot.html&quot;&gt;
  &lt;/iframe&gt;
&lt;/center&gt;

&lt;center&gt;
  &lt;iframe
    width=&quot;630&quot; height=&quot;680&quot; align=&quot;middle&quot; frameborder=&quot;0&quot;
    src=&quot;/ml-blog/assets/2018-04-01/linear-regression-encoder-2d-plot.html&quot;&gt;
  &lt;/iframe&gt;
&lt;/center&gt;

&lt;h2&gt;Next&lt;/h2&gt;

In the next blog entry, we will explore the revese operation of linear regression, using Dense layer.

&lt;h2&gt;Comments&lt;/h2&gt;
&lt;div class=&quot;blog-post-comments&quot;&gt;&lt;/div&gt;

&lt;script
  src=&quot;https://code.jquery.com/jquery-3.3.1.min.js&quot;
  integrity=&quot;sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=&quot;
  crossorigin=&quot;anonymous&quot;&gt;&lt;/script&gt;
&lt;script&gt;
const apiUrl = 'https://api.github.com/repos/mthrok/ml-blog/issues/2/comments'
$(function() { 
  $.ajax(apiUrl, {
    headers: {
        Accept: 'application/vnd.github.v3.html+json'
    },
    dataType: 'json',
    success: function(comments) {
      const $commentSection = $('.blog-post-comments')
      $commentSection.append(
      `
      &lt;a href=&quot;https://github.com/mthrok/ml-blog/issues/2#new_comment_field&quot;&gt;Visit GitHub to leave a comment.&lt;/a&gt;
      `
      )
      comments.forEach(function (comment) {
        $commentSection.append(
          `
          &lt;div class=&quot;comment&quot;&gt;
              ${comment.body_html}
              &lt;a class=&quot;commenter&quot; href=&quot;${comment.user.html_url}&quot; 
              target=&quot;_blank&quot;&gt;${comment.user.login}&lt;/a&gt;
              ${new Date(comment.created_at).toUTCString()}
          &lt;/div&gt;
          `
        )
      })
    }
  })
})	  
&lt;/script&gt;

</content>
 </entry>
 

</feed>
