<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.8.5">Jekyll</generator><link href="https://tonydeep.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://tonydeep.github.io/" rel="alternate" type="text/html" /><updated>2020-04-20T03:03:05+00:00</updated><id>https://tonydeep.github.io/feed.xml</id><title type="html">Tony Deep’s Blogs</title><subtitle>Science with a spirit of adventure</subtitle><author><name>TonyKhanh</name></author><entry><title type="html">Blogging with Jupyter Notebooks</title><link href="https://tonydeep.github.io/2020/04/12/blog_test.html" rel="alternate" type="text/html" title="Blogging with Jupyter Notebooks" /><published>2020-04-12T00:00:00+00:00</published><updated>2020-04-12T00:00:00+00:00</updated><id>https://tonydeep.github.io/2020/04/12/blog_test</id><content type="html" xml:base="https://tonydeep.github.io/2020/04/12/blog_test.html">&lt;blockquote&gt;
  &lt;p&gt;With Notebooks, we can easily share prose, code, tables, charts, and more!&lt;/p&gt;
&lt;/blockquote&gt;

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

&lt;ul class=&quot;table-of-content&quot; id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#writing-your-notebook&quot; id=&quot;markdown-toc-writing-your-notebook&quot;&gt;Writing your notebook&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#exporting-to-markdown&quot; id=&quot;markdown-toc-exporting-to-markdown&quot;&gt;Exporting to markdown&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Jupyter Notebooks is a great environment for creating blog posts. Or maybe you didn’t even plan to write a blog post, but you’ve done some interesting experiments and you realize afterwards that you have results worth sharing. Either way, you’ll want some way to get your Notebook onto your blog.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.fast.ai/2020/01/16/fast_template/&quot;&gt;fast_template&lt;/a&gt; and &lt;a href=&quot;http://nbdev.fast.ai/&quot;&gt;nbdev&lt;/a&gt; are set up to handle Jupyter Notebooks nicely, so there’s not much you have to do to get this working. I’ll walk you through the steps here. Note that Jupyter Notebooks and GitHub Pages already have some support for exporting notebooks to markdown; but I suggest you use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fast_template&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nbdev&lt;/code&gt;, with the process described in this post, because otherwise you won’t get useful features such as:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Support for pasting images directly into your notebook&lt;/li&gt;
  &lt;li&gt;Input and output cells clearly displayed with appropriate styles&lt;/li&gt;
  &lt;li&gt;The ability to hide some cells from the markdown output.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This whole post was created using this method. You can see the source notebook here:&lt;/p&gt;

&lt;h2 id=&quot;writing-your-notebook&quot;&gt;Writing your notebook&lt;/h2&gt;

&lt;p&gt;Your markdown cells, code cells, and all outputs will appear in your exported blog post. The only thing that won’t be shown is interactive outputs (e.g. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ipywidgets&lt;/code&gt;, bokeh plots, etc), or cells you explicitly hide using the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#hide&lt;/code&gt; marker discussed below.&lt;/p&gt;

&lt;p&gt;When you write your notebook, just write whatever you want your audience to see. Since most writing platforms make it much harder to include code and outputs, many of us are in a habit of including less real examples than we should. So try to get into a new habit of including lots of examples as you write.&lt;/p&gt;

&lt;p&gt;Often you’ll want to hide boilerplate such as import statements. Add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#hide&lt;/code&gt; to the top of any cell to make it not show up in output.&lt;/p&gt;

&lt;p&gt;Jupyter displays the result of the last line of a cell, so there’s no need to include &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;print()&lt;/code&gt;. (And including extra code that isn’t needed means there’s more cognitive overhead for the reader; so don’t include code that you don’t really need!)&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;2
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It works not just for text, but also for images:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;Image&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'../fast.ai/images/fast_template/image2.png'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;flip_lr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/blog_test_files/output_6_0.png&quot; alt=&quot;png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;…and plots:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;plot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/blog_test_files/output_8_0.png&quot; alt=&quot;png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;…and Pandas DataFrames, and much more!&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;pd&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;DataFrame&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'a'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'b'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div&gt;
&lt;style scoped=&quot;&quot;&gt;
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }

    .dataframe tbody tr th {
        vertical-align: top;
    }

    .dataframe thead th {
        text-align: right;
    }
&lt;/style&gt;
&lt;table border=&quot;1&quot; class=&quot;dataframe&quot;&gt;
  &lt;thead&gt;
    &lt;tr style=&quot;text-align: right;&quot;&gt;
      &lt;th&gt;&lt;/th&gt;
      &lt;th&gt;a&lt;/th&gt;
      &lt;th&gt;b&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;th&gt;0&lt;/th&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;3&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;1&lt;/th&gt;
      &lt;td&gt;2&lt;/td&gt;
      &lt;td&gt;4&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;

&lt;p&gt;You can also paste images, such as screenshots, directly into a markdown cell in Jupyter. This creates a file embedded in the notebook that Jupyter calls an “attachment”. Or you can use Markdown to refer to an image on the internet by its URL.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://upload.wikimedia.org/wikipedia/commons/1/1b/Creative-Tail-Animal-dog.svg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;exporting-to-markdown&quot;&gt;Exporting to markdown&lt;/h2&gt;

&lt;p&gt;Before you export to markdown, you first need to make sure your notebook is saved, so press &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;s&lt;/code&gt; or click &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;File&lt;/code&gt;➡&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Save&lt;/code&gt;. Then close the browser tab with the open notebook. This is important, because when we export to markdown any attachments will be exported to files, and the notebook will be updated to refer to those external files. Therefore, the notebook itself will change; if you leave it open, you may accidentally end up overwriting the updated notebook.&lt;/p&gt;

&lt;p&gt;You’ll need &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nbdev&lt;/code&gt; installed; if you haven’t already, then install it with:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;pip install nbdev
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then, in your terminal, cd to the folder containing your notebook, and type (assuming your notebook is called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;name.ipynb&lt;/code&gt;):&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;nbdev_nb2md name.ipynb
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You’ll see that a file &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;name.md&lt;/code&gt; and folder &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;name_files&lt;/code&gt; have been created (where “name” is replaced by your notebook file name). One problem is that the markdown exporter assumes your images will be in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;name_files&lt;/code&gt;, but on your blog they’ll be in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/images/name_files&lt;/code&gt;. So we need to do a search and replace to fix this in the markdown file. We can do this automatically with python. Create a file called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;upd_md.py&lt;/code&gt; with the following contents:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;fileinput&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;re&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fileinput&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;input&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;inplace&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;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;re&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sub&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;r'^(!.*]\()(\w+_files/)'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;r'\1/images/\2'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;''&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then, in the terminal, run (assuming that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;upd_md.py&lt;/code&gt; and your markdown doc are in the same folder):&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;python upd_md.py name.md
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This will modify your markdown doc inplace, so it will have the correct &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/images/&lt;/code&gt; prefix on each image reference.&lt;/p&gt;

&lt;p&gt;Finally, copy &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;name_files&lt;/code&gt; to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;images&lt;/code&gt; folder in your blog repo, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;name.md&lt;/code&gt; to your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_posts&lt;/code&gt; folder, and rename &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;name.md&lt;/code&gt; to have the required &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;YEAR-MONTH-DAY-name.md&lt;/code&gt; format. Commit and push this to GitHub, and you should see your post!&lt;/p&gt;</content><author><name>TonyKhanh</name></author><category term="blogs" /><summary type="html">With Notebooks, we can easily share prose, code, tables, charts, and more!</summary></entry><entry><title type="html">Hàm Scan trong Tensorflow</title><link href="https://tonydeep.github.io/2017/08/09/tensorflow-scan-function.html" rel="alternate" type="text/html" title="Hàm Scan trong Tensorflow" /><published>2017-08-09T00:00:00+00:00</published><updated>2017-08-09T00:00:00+00:00</updated><id>https://tonydeep.github.io/2017/08/09/tensorflow-scan-function</id><content type="html" xml:base="https://tonydeep.github.io/2017/08/09/tensorflow-scan-function.html">&lt;blockquote&gt;
  &lt;p&gt;Hàm scan là một một trong những hàm quan trọng trong Theano và giờ đây đã được Tensorflow sử dụng bởi sự tiện lợi và linh hoạt của nó.&lt;/p&gt;
&lt;/blockquote&gt;

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

&lt;ul class=&quot;table-of-content&quot; id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#overview&quot; id=&quot;markdown-toc-overview&quot;&gt;Overview&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#formular&quot; id=&quot;markdown-toc-formular&quot;&gt;Formular&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#example-1-hard-code&quot; id=&quot;markdown-toc-example-1-hard-code&quot;&gt;Example 1: Hard code&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#example-2-learning-to-predict-the-sum&quot; id=&quot;markdown-toc-example-2-learning-to-predict-the-sum&quot;&gt;Example 2: Learning to predict the &lt;strong&gt;Sum&lt;/strong&gt;&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#importing-libs&quot; id=&quot;markdown-toc-importing-libs&quot;&gt;Importing libs&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#generating-inputs-and-targets&quot; id=&quot;markdown-toc-generating-inputs-and-targets&quot;&gt;Generating Inputs and Targets&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#defining-the-rnn-model-from-scratch&quot; id=&quot;markdown-toc-defining-the-rnn-model-from-scratch&quot;&gt;Defining the RNN Model from Scratch&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#defining-an-optimizer&quot; id=&quot;markdown-toc-defining-an-optimizer&quot;&gt;Defining an Optimizer&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#training&quot; id=&quot;markdown-toc-training&quot;&gt;Training&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#testing-qualitatively&quot; id=&quot;markdown-toc-testing-qualitatively&quot;&gt;Testing Qualitatively&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#discussion&quot; id=&quot;markdown-toc-discussion&quot;&gt;Discussion&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#conclusion&quot; id=&quot;markdown-toc-conclusion&quot;&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;overview&quot;&gt;Overview&lt;/h2&gt;

&lt;p&gt;Hàm &lt;strong&gt;Scan&lt;/strong&gt; cho phép bạn sử dụng vòng lặp trong &lt;em&gt;Đồ thị tính toán&lt;/em&gt; (&lt;a href=&quot;https://www.tensorflow.org/versions/r0.10/get_started/basic_usage.html#the-computation-graph&quot;&gt;computation graph&lt;/a&gt;) của Tensorflow, cho phép bạn sử dụng thuật toán &lt;em&gt;lan truyền ngược&lt;/em&gt; (&lt;a href=&quot;https://mattmazur.com/2015/03/17/a-step-by-step-backpropagation-example/&quot;&gt;backpropagation&lt;/a&gt;) và một số kỹ thuật khác trong Machine Learning. Trong Tensorflow bạn có thể định nghĩa k &lt;a href=&quot;https://www.tensorflow.org/versions/r0.10/how_tos/graph_viz/index.html#name-scoping-and-nodes&quot;&gt;nodes&lt;/a&gt; mới cho vòng lặp có &lt;em&gt;k steps&lt;/em&gt;. Tuy nhiên giá trị &lt;strong&gt;&lt;em&gt;k&lt;/em&gt;&lt;/strong&gt; sẽ cố định thay vì được tuỳ chỉnh mềm dẻo và việc này làm cho đồ thị tính toán của bạn trở nên &lt;a href=&quot;https://github.com/tensorflow/tensorflow/issues/511&quot;&gt;chậm chạp&lt;/a&gt; hơn rất nhiều.&lt;/p&gt;

&lt;h2 id=&quot;formular&quot;&gt;Formular&lt;/h2&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&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;scan&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;elems&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;initializer&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;parallel_iterations&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;back_prop&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;swap_memory&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Toán tử &lt;em&gt;Scan&lt;/em&gt; áp dụng lặp đi lặp lại hàm &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fn&lt;/code&gt; trên chuỗi các thành phần &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;elems&lt;/code&gt; từ trái sang phải. Các thành phần này được tạo nên từ các &lt;a href=&quot;https://www.tensorflow.org/versions/r0.10/get_started/basic_usage.html#tensors&quot;&gt;tensor&lt;/a&gt; được &lt;a href=&quot;https://www.tensorflow.org/versions/r0.10/api_docs/python/array_ops.html#unpack&quot;&gt;unpack&lt;/a&gt; từ &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;elems&lt;/code&gt; theo chiều (dimension) 0. Hàm khả gọi &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fn&lt;/code&gt; nhận vào 2 đối số là 2 tensor: Tensor thứ nhất là giá trị tích luỹ được tính từ lời gọi hàm &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fn&lt;/code&gt; tại bước ngay trước. Nếu &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;initializer&lt;/code&gt; =  None, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;elems&lt;/code&gt; phải chứa ít nhất 1 phần tử và phần tử đầu tiên sẽ được sử dụng như là phần tử khởi tạo &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;initializer&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Giả sử &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;elems&lt;/code&gt; được giải nén thành tensor &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;values&lt;/code&gt; là list của các tensor, hàm &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fn&lt;/code&gt; sẽ trả về tensor có định dạng &lt;strong&gt;&lt;em&gt;shape&lt;/em&gt;&lt;/strong&gt; = [len(values)] + fn(initializer, values[0]).shape&lt;/p&gt;

&lt;h4&gt; Tham số:&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;em&gt;fn&lt;/em&gt;: Hàm áp dụng.&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;elems&lt;/em&gt;: Tensor có thể unpack theo &lt;em&gt;chiều&lt;/em&gt; (dimension) &lt;strong&gt;0&lt;/strong&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;initializer&lt;/em&gt;: (optional) Giá trị khởi tạo.&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;parallel_iterations&lt;/em&gt;: (optional) Số bước lặp cho phép chạy song song.&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;back_prop&lt;/em&gt;: (optional) True cho phép &lt;em&gt;back propagation&lt;/em&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;swap_memory&lt;/em&gt;: (optional) True cho phép hoán đổi việc sử dụng GPU-CPU memory.&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;name&lt;/em&gt;: (optional) Name prefix for the returned tensors.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;Kết quả:&lt;/h4&gt;

&lt;p&gt;Một Tensor được nén các kết quả trung gian áp dụng hàm &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fn&lt;/code&gt; trên list các &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tensors&lt;/code&gt; giải nén từ &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;elems&lt;/code&gt;, theo thứ tự từ trái sang phải.&lt;/p&gt;

&lt;h4&gt;Ví dụ &lt;/h4&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;elems&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sum&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;scan&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;elems&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#=&amp;gt; sum == [1, 3, 6, 10, 15, 21]
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Nào hãy cùng phân tích 2 ví dụ đơn giản để hiểu rõ hơn cách sử dụng &lt;strong&gt;Scan&lt;/strong&gt; trong Tensorflow:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Ví dụ 1: Viết một chương trình tính tổng luỹ tích của một list sử dụng &lt;strong&gt;scan&lt;/strong&gt;.&lt;/p&gt;

    &lt;p&gt;Input : [1, 2, 2, 2]&lt;/p&gt;

    &lt;p&gt;Output: [1, 3, 5, 7]&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Ví dụ 2: Sử dụng RNN để giải quyết Ví dụ 1 bằng cách train RNN để dự đoán chuỗi output [1, 3, 5, 7] từ chuỗi input đã biết [1, 2, 2, 2].&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;example-1-hard-code&quot;&gt;Example 1: Hard code&lt;/h2&gt;

&lt;script src=&quot;https://gist.github.com/tonydeep/50e555ed026efb2f518d609d86df5ff7.js&quot;&gt;&lt;/script&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Output: [ 1.  3.  5.  7.]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Ví dụ trên là cách đơn giản để sử dụng &lt;em&gt;Scan&lt;/em&gt;. Vậy thực sự &lt;em&gt;Scan&lt;/em&gt; làm việc như thế nào trong Tensorflow:
	Scan duyệt qua lần lượt từng phần tử trong &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;elems&lt;/code&gt;, tại mỗi vị trí &lt;em&gt;k&lt;/em&gt; sẽ áp dụng hàm &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fn&lt;/code&gt; với &lt;em&gt;inputs&lt;/em&gt; là &lt;em&gt;output&lt;/em&gt; của bước trước đó &lt;em&gt;k-1&lt;/em&gt; và &lt;em&gt;input&lt;/em&gt; của bước hiện tại. Giá trị tại bước &lt;em&gt;k = 0&lt;/em&gt; được gán khởi tạo trong &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;initializer&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;Lặp 0: fn(0.0, 1.0) == 1.0&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Lặp 1: fn(1.0, 2.0) == 3.0&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Lặp 2: fn(3.0, 2.0) == 5.0&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Lặp 3: fn(5.0, 2.0) == 7.0&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Dòng 6&lt;/strong&gt;: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;elems = tf.identity(elems)&lt;/code&gt;: Sử dụng để fix &lt;a href=&quot;https://github.com/tensorflow/tensorflow/issues/1725&quot;&gt;lỗi ở đây&lt;/a&gt;.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Không sử dụng hàm &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tf.identity()&lt;/code&gt;:
&lt;script src=&quot;https://gist.github.com/tonydeep/3a08fd63cd778dfc23b21787aa27d86d.js&quot;&gt;&lt;/script&gt;
Trong ví dụ trên, ta muốn tính cộng thêm 1 và giá trị của biến &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x&lt;/code&gt; tại &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dòng 5&lt;/code&gt; sau mỗi lần &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;y&lt;/code&gt; được kiểm tra để in ra ở &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dòng 11&lt;/code&gt;. Tuy nhiên:&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Kết quả là: 0.0, 0.0, 0.0, 0.0, 0.0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Vấn đề được giải quyết bằng cách sử dụng &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tf.identity()&lt;/code&gt; như ở code dưới đây:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Sử dụng hàm &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tf.identity()&lt;/code&gt;:
&lt;script src=&quot;https://gist.github.com/tonydeep/ecbc055ee3931aa33728c0e3b49c3583.js&quot;&gt;&lt;/script&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Kết quả là: 1.0, 2.0, 3.0, 4.0, 5.0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;example-2-learning-to-predict-the-sum&quot;&gt;Example 2: Learning to predict the &lt;strong&gt;Sum&lt;/strong&gt;&lt;/h2&gt;

&lt;p&gt;Ở ví dụ này, chúng ta sẽ viết một chương trình sử dụng mô hình RNN (&lt;a href=&quot;https://en.wikipedia.org/wiki/Recurrent_neural_network&quot;&gt;Recurrent Neural Network&lt;/a&gt;) và huấn luyện (train) mô hình để dự đoán hàm &lt;strong&gt;sum&lt;/strong&gt; từ tập dữ liệu huấn luyện (training data).&lt;/p&gt;

&lt;h3 id=&quot;importing-libs&quot;&gt;Importing libs&lt;/h3&gt;

&lt;script src=&quot;https://gist.github.com/tonydeep/253856a4510727eb6ec04d5536c8f539.js&quot;&gt;&lt;/script&gt;

&lt;h3 id=&quot;generating-inputs-and-targets&quot;&gt;Generating Inputs and Targets&lt;/h3&gt;

&lt;p&gt;Trước hết chúng ta sẽ sinh &lt;em&gt;training data&lt;/em&gt; là các cặp chuỗi &lt;em&gt;input&lt;/em&gt; và chuỗi &lt;em&gt;target&lt;/em&gt; tương ứng (được dùng như là những vector cột &lt;em&gt;shape&lt;/em&gt;=[k, 1])&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/tonydeep/bdd13530625ea9ed6e149f45349c890b.js&quot;&gt;&lt;/script&gt;

&lt;h3 id=&quot;defining-the-rnn-model-from-scratch&quot;&gt;Defining the RNN Model from Scratch&lt;/h3&gt;

&lt;p&gt;Tiếp theo, định nghĩa RNN model. Code tuy có hơi dài nhưng cơ bản với những comment giải thích bên trong sẽ giúp bạn dễ dàng hiểu và thực hành hơn.&lt;/p&gt;

&lt;p&gt;Các thành phần chính của RNN như sau:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Trạng thái (state) của RNN được update bởi công thức:&lt;/li&gt;
&lt;/ul&gt;

&lt;script type=&quot;math/tex; mode=display&quot;&gt;h_{t}=tanh( W_{h}h_{t-1}+W_{x}x_{t}+b)&lt;/script&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;&lt;em&gt;_vanilla_rnn_step&lt;/em&gt;&lt;/strong&gt; là thành phần chính của mô hình RNN này: Nó áp dụng công thức trên bằng việc nhận đầu vào là trạng thái của bước trước cùng với input hiện tại và sinh ra trạng thái mới. Có một chút bối rối ở đây khi các bạn phải xử lý &lt;em&gt;shape&lt;/em&gt; của các tensor bằng cách chuyển vị (transpose) sao cho phù hợp với việc tính toán và yêu cầu của Tensorflow.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;&lt;em&gt;_compute_predictions&lt;/em&gt;&lt;/strong&gt; áp dụng &lt;em&gt;_vanilla_rnn_step&lt;/em&gt; cho mọi bước sử dụng &lt;strong&gt;&lt;em&gt;scan&lt;/em&gt;&lt;/strong&gt;, mỗi bước cho kết quả là một trạng thái mới, sau đó sử dụng một layer để biến shape của trạng thái thành shape của target và dự đoán kết quả.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;&lt;em&gt;_compute_loss&lt;/em&gt;&lt;/strong&gt; tính khoảng cách Euclid trung bình (&lt;a href=&quot;https://en.wikipedia.org/wiki/Euclidean_distance&quot;&gt;mean squared Euclidean distance&lt;/a&gt;) giữa target thực tế và kết quả dự đoán được.&lt;/li&gt;
&lt;/ul&gt;

&lt;script src=&quot;https://gist.github.com/tonydeep/0e9ed24badf2bbea9959967a489d7e67.js&quot;&gt;&lt;/script&gt;

&lt;h3 id=&quot;defining-an-optimizer&quot;&gt;Defining an Optimizer&lt;/h3&gt;

&lt;p&gt;Chúng ta tiếp tục định nghĩa lớp Tối ưu hoá (Optimizer). Trong lớp này chúng ta sẽ sử dụng thuật toán gradient descent để update mô hình, sử dụng kỹ thuật &lt;em&gt;cắt ngọn&lt;/em&gt; (&lt;a href=&quot;https://www.reddit.com/r/MachineLearning/comments/31b6x8/gradient_clipping_rnns/&quot;&gt;gradient clipping&lt;/a&gt;) để tránh việc &lt;em&gt;bùng nổ&lt;/em&gt; gradient (&lt;a href=&quot;http://neuralnetworksanddeeplearning.com/chap5.html&quot;&gt;exploding gradient&lt;/a&gt;), bằng cách sử dụng ngưỡng &lt;em&gt;max_global_norm&lt;/em&gt; - Khi đó tại mỗi bước tính toán gradient, mỗi khi global norm (tổng norm của tất cả gradients) vượt quá ngưỡng sẽ được chuẩn hoá thành &lt;em&gt;max_global_norm&lt;/em&gt;. 
&lt;script src=&quot;https://gist.github.com/tonydeep/f0a188ab988243ad18600117e476ca1b.js&quot;&gt;&lt;/script&gt;&lt;/p&gt;

&lt;h3 id=&quot;training&quot;&gt;Training&lt;/h3&gt;

&lt;p&gt;Mọi thứ đã sẵn sàng, chúng ta tiến hành định nghĩa và thực thi hàm &lt;em&gt;train&lt;/em&gt;, tại đây chúng ta sẽ thực hiện các bước tính toán và update tham số của mô hình, và ghi nhận lại thông tin của của mô hình để có thể quan sát một cách trực quan thông qua công cụ &lt;a href=&quot;https://www.tensorflow.org/versions/r0.10/how_tos/graph_viz/index.html#tensorboard-graph-visualization&quot;&gt;TensorBoard&lt;/a&gt; của Tensorflow.
&lt;script src=&quot;https://gist.github.com/tonydeep/c72fb6cd225f93643afb08b2eef09907.js&quot;&gt;&lt;/script&gt;
Mô hình đươc train như sau:
&lt;script src=&quot;https://gist.github.com/tonydeep/e0232059bc01f814433e2c3b1614d591.js&quot;&gt;&lt;/script&gt;
Sau khi train mô hình, chạy lệnh &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tensorboard --logdir ./logdir&lt;/code&gt;, vào địa chỉ &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http://localhost:6006&lt;/code&gt; để quan sát các thông số của mô hình: loss, biểu đồ train mô hình qua từng steps, mô hình trực quan, …&lt;/p&gt;

&lt;!-- ![alt text](https://tonydeep.github.io/img/scan_post/DL_loss_raw.png &quot;Raw Loss&quot;) --&gt;
&lt;p&gt;&lt;img src=&quot;/assets/images/scan_post/loss_raw.png&quot; alt=&quot;&quot; style=&quot;width:200px; height:200px;&quot; /&gt;&lt;/p&gt;

&lt;!-- ![alt text](https://tonydeep.github.io/img/scan_post/DL_loss_ema.png &quot;EMA Loss&quot;) --&gt;
&lt;p&gt;&lt;img src=&quot;/assets/images/scan_post/loss_ema.png&quot; alt=&quot;&quot; style=&quot;width:200px; height:200px;&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;testing-qualitatively&quot;&gt;Testing Qualitatively&lt;/h3&gt;

&lt;p&gt;Cuối cùng chúng ta tiến hành kiểm tra chất lượng của mô hình bằng cách vẽ chuỗi target và chuỗi dự đoán trên cùng một biểu đồ, nếu 2 chuỗi có xu hướng chồng lên nhau thì mô hình cơ bản là tốt, ngược lại nếu 2 chuỗi tách biệt nhau thì mô hình dự đoán yếu.
&lt;script src=&quot;https://gist.github.com/tonydeep/0d61bf5619d3b758234f526609f43031.js&quot;&gt;&lt;/script&gt;&lt;/p&gt;

&lt;p&gt;và chạy:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;test_qualitatively&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sess&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;generator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;figsize&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Kết quả như sau:&lt;/p&gt;

&lt;!-- ![alt text](https://tonydeep.github.io/img/scan_post/DL_predict_sum_summaries.png &quot;Test Quality&quot;) --&gt;
&lt;p&gt;&lt;img src=&quot;/assets/images/scan_post/predictions.png&quot; alt=&quot;&quot; style=&quot;width:500px; height:700px;&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;discussion&quot;&gt;Discussion&lt;/h2&gt;

&lt;p&gt;Vậy là các bạn đã hoàn thiện một chương trình RNN đơn giản để huấn luyện mô hình dự đoán chuỗi tổng luỹ tích từ chuỗi input cho trước. Một số phần các bạn có thể lưu ý để cải thiện mô hình tốt hơn:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Giá trị của &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hidden_layer_size&lt;/code&gt;, trong mô hình trên chúng ta gán &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hidden_layer_size = 256&lt;/code&gt;. Các bạn hãy thử với các giá trị nhỏ hơn (mỗi lần chia cho 2) và quan sát &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;loss&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Giá trị của &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;initial_learning_rate=1e-2&lt;/code&gt;. Hãy thử với các giá trị khác và quan sát &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;loss&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Giá trị cho &lt;em&gt;gradient clipping&lt;/em&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;max_global_norm=1.0&lt;/code&gt;. Hãy thử train mô hình mà không sử dụng &lt;em&gt;gradient clipping&lt;/em&gt;, cùng đó kết hợp với lựa chọn &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;initial_learning_rate&lt;/code&gt; phù hợp.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;Mô hình trên được huấn luyện tại mỗi bước cho sử dụng duy nhất 1 cặp chuỗi input và target. Việc này làm tăng thời gian huấn luyện mô hình. Cải thiện bằng cách có thể sử dụng input_size lên tuỳ thuộc vào cấu hình máy.&lt;/li&gt;
  &lt;li&gt;Mô hình trên sử dụng chỉ một layer, chúng ta có thể mở rộng thành &lt;em&gt;deep model&lt;/em&gt; bằng cách chồng thêm 1, 2, … các layer lên nhau: Thực hiện hàm &lt;strong&gt;scan&lt;/strong&gt; để lấy kết quả layer thứ nhất, chạy &lt;strong&gt;scan&lt;/strong&gt; lần thứ hai để lấy kết quả của layer thứ 2, cứ tiếp tục như vậy. Lưu ý: Output của layer &lt;em&gt;l&lt;/em&gt; sẽ là input của layer &lt;em&gt;l+1&lt;/em&gt;.&lt;/li&gt;
  &lt;li&gt;Mô hình RNN cơ bản này ít khi sử dụng gần đây do hai vấn đề của nó là triệt tiêu và bùng nổ gradient (&amp;lt;a href=”“https://en.wikipedia.org/wiki/Vanishing_gradient_problem&amp;gt;&lt;em&gt;vanishing và expoding gradient&lt;/em&gt;&amp;lt;/a&amp;gt;). Hai mô hình thay thế cho RNN hay được sử dụng là LSTM (&lt;a href=&quot;http://colah.github.io/posts/2015-08-Understanding-LSTMs/&quot;&gt;Long-Short Term Memory&lt;/a&gt;) và GRU (&lt;a href=&quot;http://www.wildml.com/2015/10/recurrent-neural-network-tutorial-part-4-implementing-a-grulstm-rnn-with-python-and-theano/&quot;&gt;Gated Recurrent Unit&lt;/a&gt;).&lt;/li&gt;
  &lt;li&gt;Chúng ta đang sử dụng thuật toán BPTT (&lt;a href=&quot;https://en.wikipedia.org/wiki/Backpropagation_through_time&quot;&gt;backpropagation through time&lt;/a&gt;) đầy đủ bằng cách thực hiện toàn bộ quá trình lan truyền xuôi, ngược cho mỗi lượt update gradietn. Việc này làm cho quá trình train mô hình của chúng ta trở nên chậm, tốn thời gian. Một kỹ thuật thay thế là sử dụng &lt;a href=&quot;http://www.wildml.com/2015/10/recurrent-neural-networks-tutorial-part-3-backpropagation-through-time-and-vanishing-gradients/&quot;&gt;truncated backpropagation through time&lt;/a&gt; bằng cách cập nhật thông tin của mô hình thông qua một khoảng thời gian gần hơn trong quá khứ tuy vậy vẫn đảm bảo giữ được thông tin xa hơn quá khứ vì chúng cũng được lưu lại trong các trạng thái.&lt;/li&gt;
&lt;/ul&gt;</content><author><name>TonyKhanh</name></author><category term="tensorflow" /><summary type="html">Hàm scan là một một trong những hàm quan trọng trong Theano và giờ đây đã được Tensorflow sử dụng bởi sự tiện lợi và linh hoạt của nó.</summary></entry><entry><title type="html">Cross-Entropy Loss là gì?</title><link href="https://tonydeep.github.io/tensorflow/2017/07/07/Cross-Entropy-Loss.html" rel="alternate" type="text/html" title="Cross-Entropy Loss là gì?" /><published>2017-07-07T00:00:00+00:00</published><updated>2017-07-07T00:00:00+00:00</updated><id>https://tonydeep.github.io/tensorflow/2017/07/07/Cross-Entropy-Loss</id><content type="html" xml:base="https://tonydeep.github.io/tensorflow/2017/07/07/Cross-Entropy-Loss.html">&lt;blockquote&gt;
  &lt;p&gt;This post reviews some extremely remarkable results in applying deep neural networks to natural language processing (NLP)&lt;/p&gt;
&lt;/blockquote&gt;

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

&lt;h2 id=&quot;contents&quot;&gt;Contents&lt;/h2&gt;

&lt;ul class=&quot;table-of-content&quot; id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#contents&quot; id=&quot;markdown-toc-contents&quot;&gt;Contents&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#introduction&quot; id=&quot;markdown-toc-introduction&quot;&gt;Introduction&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#entropy&quot; id=&quot;markdown-toc-entropy&quot;&gt;Entropy&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#code-codeword-encode-decode&quot; id=&quot;markdown-toc-code-codeword-encode-decode&quot;&gt;Code, Codeword, Encode-Decode&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#không-gian-codeword&quot; id=&quot;markdown-toc-không-gian-codeword&quot;&gt;Không gian codeword&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#optimal-encoding---mã-tối-ưu&quot; id=&quot;markdown-toc-optimal-encoding---mã-tối-ưu&quot;&gt;Optimal Encoding - Mã tối ưu&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#công-thức-tính-entropy&quot; id=&quot;markdown-toc-công-thức-tính-entropy&quot;&gt;Công thức tính Entropy&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#cross-entropy&quot; id=&quot;markdown-toc-cross-entropy&quot;&gt;Cross Entropy&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#tại-sao-cross-entropy-lại-quan-trọng-&quot; id=&quot;markdown-toc-tại-sao-cross-entropy-lại-quan-trọng-&quot;&gt;Tại sao cross-entropy lại quan trọng ???&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#kl-divergence---kl-phân-kỳ&quot; id=&quot;markdown-toc-kl-divergence---kl-phân-kỳ&quot;&gt;KL Divergence - KL phân kỳ&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#khả-năng-dự-đoán&quot; id=&quot;markdown-toc-khả-năng-dự-đoán&quot;&gt;Khả năng dự đoán&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#likelihood&quot; id=&quot;markdown-toc-likelihood&quot;&gt;Likelihood&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#thảo-luận&quot; id=&quot;markdown-toc-thảo-luận&quot;&gt;Thảo luận&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#nguồn-tham-khảo&quot; id=&quot;markdown-toc-nguồn-tham-khảo&quot;&gt;Nguồn tham khảo&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;/h2&gt;

&lt;div class=&quot;imgcap&quot; style=&quot;align-content:center;&quot;&gt;
	&lt;img src=&quot;/assets/images/ce_post/shanon-entropy.jpeg&quot; alt=&quot;&quot; style=&quot;width:350px; height:250px;&quot; /&gt;
	&lt;div class=&quot;thecap&quot; style=&quot;font-size: 15px;&quot;&gt;Giai thoại Neumann-Shannon (From &lt;a href=&quot;http://www.eoht.info/page/Neumann-Shannon+anecdote&quot;&gt;Hmopedia&lt;/a&gt;)&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;spaceafterimg&quot;&gt;&lt;/div&gt;

&lt;p&gt;Mục tiêu của bài toán phân lớp dựa trên tính toán xác suất (&lt;a href=&quot;https://en.wikipedia.org/wiki/Probabilistic_classification&quot;&gt;&lt;em&gt;Probabilistic classification&lt;/em&gt;&lt;/a&gt;) là gán (&lt;em&gt;map&lt;/em&gt;) dữ liệu đầu vào cho nhãn của lớp có xác suất cao nhất, và chúng ta thường &lt;em&gt;train&lt;/em&gt; mô hình bằng điều chỉnh tham số của mô hình sao cho xác suất dự đoán được càng sát với &lt;em&gt;ground-truth probabilities&lt;/em&gt; càng tốt.&lt;/p&gt;

&lt;p&gt;Chúng ta giả sử chỉ xét mô hình với nhãn các lớp là phân biệt. Ví dụ cho bài toán phân lớp ảnh số từ &lt;script type=&quot;math/tex&quot;&gt;0-9&lt;/script&gt; &lt;a href=&quot;https://en.wikipedia.org/wiki/MNIST_database&quot;&gt;MNIST database&lt;/a&gt; với &lt;em&gt;input&lt;/em&gt; là danh sách các ảnh và &lt;em&gt;output&lt;/em&gt; là &lt;script type=&quot;math/tex&quot;&gt;10&lt;/script&gt; số từ &lt;script type=&quot;math/tex&quot;&gt;0-9&lt;/script&gt;, mô hình sẽ dự đoán xác suất output (cho mỗi ảnh input tương ứng) là danh sách &lt;script type=&quot;math/tex&quot;&gt;10&lt;/script&gt; số mỗi số là xác suất mà ảnh đầu vào sẽ thuộc lớp tương ứng, và thoả mãn: &lt;script type=&quot;math/tex&quot;&gt;\sum_{k=0}^9\hat{y}_k = 1.0&lt;/script&gt;&lt;/p&gt;

&lt;p&gt;Trong quá trình &lt;em&gt;training&lt;/em&gt;, giả sử chúng ta có ảnh input là ảnh mang số &lt;script type=&quot;math/tex&quot;&gt;9&lt;/script&gt; và mô hình được kỳ vọng sẽ dự đoán xác suất đầu ra gần với &lt;em&gt;ground-truth class probability&lt;/em&gt; &lt;script type=&quot;math/tex&quot;&gt;y = (0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0)^T&lt;/script&gt;, nghĩa là xác suất tại vị trí số &lt;script type=&quot;math/tex&quot;&gt;9&lt;/script&gt; của output &lt;script type=&quot;math/tex&quot;&gt;y&lt;/script&gt; đạt &lt;script type=&quot;math/tex&quot;&gt;max&lt;/script&gt;. Giả sử mô hình dự đoán phân bố xác suất output khác biệt so với target &lt;script type=&quot;math/tex&quot;&gt;y&lt;/script&gt;, với &lt;script type=&quot;math/tex&quot;&gt;\hat{y} = (0.0, 0.0, 0.0, 0.0, 0.0, 0.1, 0.1, 0.4, 0.3, 0.1)&lt;/script&gt;, thì chúng ta sẽ phải &lt;em&gt;điều chỉnh&lt;/em&gt; tham số của mô hình sao cho &lt;script type=&quot;math/tex&quot;&gt;\hat{y}&lt;/script&gt; &lt;strong&gt;&lt;em&gt;tiến gần tới&lt;/em&gt;&lt;/strong&gt; &lt;script type=&quot;math/tex&quot;&gt;y&lt;/script&gt;.&lt;/p&gt;

&lt;p&gt;Vậy thế nào là &lt;em&gt;điều chỉnh&lt;/em&gt; tham số cho &lt;script type=&quot;math/tex&quot;&gt;\hat{y}&lt;/script&gt; &lt;strong&gt;&lt;em&gt;tiến gần tới&lt;/em&gt;&lt;/strong&gt; &lt;script type=&quot;math/tex&quot;&gt;y&lt;/script&gt;. Ở đây nghĩa là chúng ta sẽ tìm cách &lt;strong&gt;&lt;em&gt;đánh giá sự khác biệt&lt;/em&gt;&lt;/strong&gt; giữa &lt;script type=&quot;math/tex&quot;&gt;\hat{y}&lt;/script&gt; và &lt;script type=&quot;math/tex&quot;&gt;y&lt;/script&gt;.&lt;/p&gt;

&lt;p&gt;Có nhiều cách để đánh giá sự khác biệt này, ở post này chúng ta sẽ đi tìm hiểu một trong số những cách phổ biến nhất đó chính là &lt;strong&gt;&lt;em&gt;cross-entropy&lt;/em&gt;&lt;/strong&gt;, và đánh giá tại sao cross-entropy lại phù hợp cho bài toán phân lớp (classification).&lt;/p&gt;

&lt;p&gt;&lt;a id=&quot;entropy&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;entropy&quot;&gt;Entropy&lt;/h2&gt;

&lt;div class=&quot;imgcap&quot;&gt;
	&lt;img src=&quot;/assets/images/ce_post/without_claude_shannon_there_would_be_no_internet_wide_image.jpg&quot; alt=&quot;&quot; style=&quot;width:550px; height:200px;&quot; /&gt;
	&lt;div class=&quot;thecap&quot; style=&quot;font-size: 15px;&quot;&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Claude_Shannon&quot;&gt;Claude Shannon&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;spaceafterimg&quot;&gt;&lt;/div&gt;

&lt;h3 id=&quot;code-codeword-encode-decode&quot;&gt;Code, Codeword, Encode-Decode&lt;/h3&gt;

&lt;p&gt;Các bạn hẳn vẫn còn nhớ cô nàng Alice và anh chàng Bob trong những câu chuyện về an toàn bảo mật thông tin. Lần này câu chuyện của 2 bạn ấy như sau: Bob rất thích động vật, anh ấy có thể nói chuyện cả ngày với Alice về chủ đề động vật. Đặc biệt khi nói chuyện với Alice anh ấy luôn chỉ có nói 4 từ: “&lt;em&gt;dog&lt;/em&gt;”, “&lt;em&gt;cat&lt;/em&gt;”, “&lt;em&gt;fish&lt;/em&gt;” và “&lt;em&gt;bird&lt;/em&gt;”.&lt;/p&gt;

&lt;p&gt;Một lần Bob đi du lịch xa, Bob liên lạc với Alice qua tin nhắn và mã hoá tin nhắn chỉ gồm các ký tự nhị phân &lt;script type=&quot;math/tex&quot;&gt;0&lt;/script&gt; và &lt;script type=&quot;math/tex&quot;&gt;1&lt;/script&gt;. Tin nhắn của Bob như sau:&lt;/p&gt;

&lt;!-- ![Bobs massages](https://tonydeep.github.io/assets/images/ce_post/binary_bits.png) --&gt;
&lt;p&gt;&lt;img src=&quot;/assets/images/ce_post/binary_bits.png&quot; alt=&quot;&quot; style=&quot;width:140px; height:40px;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Để thuận tiện cho việc trao đổi, Bob và Alice cùng thống nhất với nhau về cách thức mã hoá tin nhắn bằng cách thay thế từng từ thành chuỗi nhị phân (&lt;em&gt;codeword&lt;/em&gt;) độ dài 2 bit tương ứng và ghép lại thành 1 chuỗi tin nhắn duy nhất. Cụ thể:&lt;/p&gt;

&lt;!-- ![code-2bit](https://tonydeep.github.io/assets/images/ce_post/code-2bit.png) --&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/ce_post/code-2bit.png&quot; alt=&quot;&quot; style=&quot;width:300px; height:210px;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;và giải mã thông tin như sau:&lt;/p&gt;

&lt;!-- ![encode-2bit](https://tonydeep.github.io/assets/images/ce_post/encode-2bit.png) --&gt;
&lt;p&gt;&lt;img src=&quot;/assets/images/ce_post/encode-2bit.png&quot; alt=&quot;&quot; style=&quot;width:350px; height:160px;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Mọi chuyện sẽ không đáng lo nếu như giá cước là &lt;script type=&quot;math/tex&quot;&gt;100&lt;/script&gt; đồng/&lt;em&gt;1 bit&lt;/em&gt;, nhưng nay đã tăng lên là &lt;script type=&quot;math/tex&quot;&gt;500&lt;/script&gt; đồng/&lt;em&gt;1 bit&lt;/em&gt;. Giá cả đắt đỏ chẳng nhẽ lại thôi không liên lạc nữa. Do vậy, Bob và Alice quyết tìm ra cách nào đó để tin nhắn ngắn hơn (để giảm cước phí) nhưng vẫn đảm bảo chuyển tải được đầy đủ thông tin.&lt;/p&gt;

&lt;p&gt;Cùng nhau xem xét lại lịch sử các tin nhắn, Alice thấy rằng Bob tần suất các từ trong tin nhắn của Bob không tương đương với nhau. Cụ thể là: Bob thực sự thích “&lt;em&gt;dog&lt;/em&gt;”, anh ấy chủ yếu nói về “&lt;em&gt;dog&lt;/em&gt;” trong mọi tin nhắn của mình, thỉnh thoảng Bob mới nhắc đến 3 con vật còn lại là “&lt;em&gt;cat&lt;/em&gt;”, “&lt;em&gt;fish&lt;/em&gt;” và “&lt;em&gt;bird&lt;/em&gt;”. Tần suất cụ thể như bảng thống kê dưới đây:&lt;/p&gt;

&lt;!-- ![DogWordFreq](https://tonydeep.github.io/assets/images/ce_post/DogWordFreq.png) --&gt;
&lt;p&gt;&lt;img src=&quot;/assets/images/ce_post/DogWordFreq.png&quot; alt=&quot;&quot; style=&quot;width:350px; height:160px;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Phân tích một cách chi tiết hơn về &lt;em&gt;codeword&lt;/em&gt; mà 2 bạn đã dùng bằng biểu đồ dưới đây, với: &lt;em&gt;Trục tung&lt;/em&gt; - Thể hiện xác suất xuất hiện &lt;script type=&quot;math/tex&quot;&gt;p(x)&lt;/script&gt; của 1 word; &lt;em&gt;Trục hoành&lt;/em&gt; - Độ dài &lt;script type=&quot;math/tex&quot;&gt;L(x)&lt;/script&gt; của codeword tương ứng; &lt;em&gt;Diện tích&lt;/em&gt; - &lt;em&gt;Expected codeword lenght&lt;/em&gt;: Độ dài kỳ vọng hay độ dài trung bình của một codeword được gửi đi, ở đây = &lt;em&gt;2 bit&lt;/em&gt;:&lt;/p&gt;

&lt;!-- ![oldcode](https://tonydeep.github.io/assets/images/ce_post/OldCode.png) --&gt;
&lt;p&gt;&lt;img src=&quot;/assets/images/ce_post/OldCode.png&quot; alt=&quot;&quot; style=&quot;width:550px; height:310px;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Như vậy, mục tiêu của 2 bạn là &lt;em&gt;cực tiểu&lt;/em&gt; độ dài của tin nhắn gửi đi. Ở đây là hoàn toàn có thể lựa chọn codeword có &lt;a href=&quot;https://en.wikipedia.org/wiki/Variable-length_code&quot;&gt;độ dài khác nhau&lt;/a&gt;. Theo thuật toán tham lam thì word nào xuất hiện nhiều (&lt;em&gt;word phổ biến&lt;/em&gt;, ví dụ như “&lt;em&gt;dog&lt;/em&gt;”) sẽ ưu tiên chọn độ dài codeword tương ứng ngắn hơn và ngược lại những word nào xuất hiện ít (&lt;em&gt;word hiếm&lt;/em&gt;, ví dụ như “&lt;em&gt;bird&lt;/em&gt;”) thì codeword sử dụng sẽ dài hơn. Cụ thể ta có được như sau:&lt;/p&gt;

&lt;!-- ![code](https://tonydeep.github.io/assets/images/ce_post/code.png) --&gt;
&lt;p&gt;&lt;img src=&quot;/assets/images/ce_post/code.png&quot; alt=&quot;&quot; style=&quot;width:350px; height:180px;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Biểu đồ phân tích cho bộ codeword mới như sau:&lt;/p&gt;

&lt;!-- ![newcode](https://tonydeep.github.io/assets/images/ce_post/NewCode.png) --&gt;
&lt;p&gt;&lt;img src=&quot;/assets/images/ce_post/NewCode.png&quot; alt=&quot;&quot; style=&quot;width:550px; height:310px;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Để ý rằng trong biểu đồ trên độ dài của codeword phổ biến ngắn hơn trong khi đó độ dài của codeword hiếm là dài hơn. Phần diện tích được tính toán cũng nhỏ hơn,và tương ứng với độ dài trung bình của codeword là &lt;script type=&quot;math/tex&quot;&gt;1.75&lt;/script&gt;. Như vậy bằng cách sử dụng codeword có độ dài khác nhau ta có thể làm cho độ dài trung bình của codeword nhỏ hơn.&lt;/p&gt;

&lt;p&gt;Bạn cũng có thể tự hỏi rằng tại sao ko dùng tất cả codeword độ dài bằng 1 cả. Với cách này thì bạn sẽ gặp phải vấn đề nhập nhằng (&lt;em&gt;ambiguity&lt;/em&gt;) trong quá trình giải mã (&lt;em&gt;decode&lt;/em&gt;)(sẽ giải thích cụ thể hơn ở phần tiếp).&lt;/p&gt;

&lt;p&gt;Với ví dụ trên cùng với phân bố xác suất &lt;script type=&quot;math/tex&quot;&gt;p(x) = (\frac{1}{2}, \frac{1}{4}, \frac{1}{8}, \frac{1}{8})&lt;/script&gt;, thì &lt;script type=&quot;math/tex&quot;&gt;1.75&lt;/script&gt; là giá trị tối ưu, nghĩa là chúng ta sẽ không tìm được bộ codeword nào phù hợp mà có giá trị trung bình nhỏ hơn &lt;script type=&quot;math/tex&quot;&gt;1.75&lt;/script&gt;.&lt;/p&gt;

&lt;p&gt;Như vậy, các bạn có thể thấy rằng với mỗi bộ phân bố xác suất &lt;script type=&quot;math/tex&quot;&gt;p(X)&lt;/script&gt; cho trước, ta hoàn toàn xác định được giá trị tối ưu của code, hay độ dài trung bình tối ưu của codeword. Và giá trị này được gọi là &lt;a href=&quot;https://en.wikipedia.org/wiki/Entropy_information_theory&quot;&gt;Entropy&lt;/a&gt;.&lt;/p&gt;

&lt;!-- ![EntropOptimalLengthExample](https://tonydeep.github.io/assets/images/ce_post/EntropOptimalLengthExample.png) --&gt;
&lt;p&gt;&lt;img src=&quot;/assets/images/ce_post/EntropOptimalLengthExample.png&quot; alt=&quot;&quot; style=&quot;width:550px; height:310px;&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;không-gian-codeword&quot;&gt;Không gian codeword&lt;/h3&gt;

&lt;p&gt;Chúng ta có 2 codeword độ dài 1 là: &lt;em&gt;0&lt;/em&gt; và &lt;em&gt;1&lt;/em&gt;; 4 codeword độ dài 2 là: &lt;em&gt;00&lt;/em&gt;, &lt;em&gt;01&lt;/em&gt;, &lt;em&gt;10&lt;/em&gt;, &lt;em&gt;11&lt;/em&gt;; và tổng quát là &lt;script type=&quot;math/tex&quot;&gt;2^n&lt;/script&gt; codeword độ dài n.&lt;/p&gt;

&lt;!-- ![codespace](https://tonydeep.github.io/assets/images/ce_post/CodeSpace.png) --&gt;
&lt;p&gt;&lt;img src=&quot;/assets/images/ce_post/CodeSpace.png&quot; alt=&quot;&quot; style=&quot;width:400px; height:200px;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Như trên đã nói, bạn hoàn toàn có thể tuỳ ý lựa chọn codeword có độ dài bất kỳ. Ví dụ như hình trên là 8 codeword độ dài 3, bạn có thể lựa chọn một cách tổ hợp các codeword có độ dài khác nhau như bạn chọn 2 codeword độ dài 2, 4 codeword độ dài 3 chẳng hạn.&lt;/p&gt;

&lt;p&gt;Vậy điều gì quyết định đến việc chọn lựa codeword với độ dài khác nhau.&lt;/p&gt;

&lt;p&gt;Ở hình dưới, Bob mã hoá tin nhắn bằng cách thay thế từng word bằng codeword tương ứng và ghép lại thành một chuỗi mã hoá nhị phân.&lt;/p&gt;

&lt;!-- ![encode](https://tonydeep.github.io/assets/images/ce_post/encode.png) --&gt;
&lt;p&gt;&lt;img src=&quot;/assets/images/ce_post/encode.png&quot; alt=&quot;&quot; style=&quot;width:350px; height:150px;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Có một điều bạn cần lưu ý ở đây là làm thế nào để từ chuỗi mã hoá bạn có thể giải mã ngược lại thành chuỗi các codeword. Nếu như chọn codeword có độ dài như nhau thì việc này khá đơn giản. Tuy nhiên bạn lựa chọn codeword độ dài khác nhau việc giải mã ngược lại được thành chuỗi codeword là việc hết sức quan trọng.&lt;/p&gt;

&lt;p&gt;Thực tế, bạn cần chọn bộ codeword sao cho việc giải mã là duy nhất. Bằng không bạn sẽ rơi vào tình trạng “&lt;em&gt;nhập nhằng&lt;/em&gt;”, nghĩa là từ một chuỗi mã hoá sẽ có nhiều chuỗi giải mã thoả mãn. Ví dụ, nếu bạn chọn cả &lt;script type=&quot;math/tex&quot;&gt;0&lt;/script&gt; và &lt;script type=&quot;math/tex&quot;&gt;01&lt;/script&gt; trong bộ codeword của bạn, thì với chuỗi mã hoá &lt;script type=&quot;math/tex&quot;&gt;01101&lt;/script&gt; bạn sẽ khó quyết định đâu là codeword phù hợp được dùng để giải mã cho 2 bit đầu. Do đó, bạn sẽ không chọn bộ codeword là &lt;em&gt;prefix code&lt;/em&gt; - nghĩa là không codeword nào là &lt;em&gt;prefix&lt;/em&gt; của codeword trong cùng một bộ.&lt;/p&gt;

&lt;p&gt;Để dễ dàng cho việc lựa chọn &lt;em&gt;prefix code&lt;/em&gt;, bạn sẽ sử dụng một phương pháp gọi là “&lt;em&gt;hi sinh&lt;/em&gt;”, nghĩa là khi bạn đã chọn một codeword, ví dụ như &lt;script type=&quot;math/tex&quot;&gt;01&lt;/script&gt;, thì toàn bộ không gian codeword bắt đầu bằng &lt;script type=&quot;math/tex&quot;&gt;01&lt;/script&gt; sẽ không được sử dụng, ví dụ bạn sẽ không được dùng các codeword như: &lt;script type=&quot;math/tex&quot;&gt;010&lt;/script&gt;, &lt;script type=&quot;math/tex&quot;&gt;0101&lt;/script&gt;, … bởi nó sẽ gây ra tình trạng “&lt;em&gt;nhập nhằng&lt;/em&gt;” cho quá trình giải mã.&lt;/p&gt;

&lt;!-- ![codespaceused](https://tonydeep.github.io/assets/images/ce_post/CodeSpaceUsed.png) --&gt;
&lt;p&gt;&lt;img src=&quot;/assets/images/ce_post/CodeSpaceUsed.png&quot; alt=&quot;&quot; style=&quot;width:550px; height:300px;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Với &lt;script type=&quot;math/tex&quot;&gt;\frac{1}{4}&lt;/script&gt; trong tổng số codeword bắt đầu bằng &lt;script type=&quot;math/tex&quot;&gt;01&lt;/script&gt;, như vậy nếu codeword &lt;script type=&quot;math/tex&quot;&gt;01&lt;/script&gt; được chọn, bạn sẽ phải “&lt;em&gt;hi sinh&lt;/em&gt;” &lt;script type=&quot;math/tex&quot;&gt;\frac{1}{4}&lt;/script&gt; tổng số codeword. Đây là “&lt;em&gt;chi phí&lt;/em&gt;” bạn phải trả để có được một codeword độ dài 2.&lt;/p&gt;

&lt;h3 id=&quot;optimal-encoding---mã-tối-ưu&quot;&gt;Optimal Encoding - Mã tối ưu&lt;/h3&gt;

&lt;p&gt;Ở đây, bạn coi việc này giống như bạn đang có một &lt;em&gt;ngân khố&lt;/em&gt; đầy đủ với tỷ lệ &lt;script type=&quot;math/tex&quot;&gt;\frac{1}{1}&lt;/script&gt;, mỗi khi bạn chọn một codeword độ dài L thì theo thuyết “&lt;em&gt;hi sinh&lt;/em&gt;” ở trên bạn phải “&lt;em&gt;hi sinh&lt;/em&gt;” một “&lt;em&gt;chi phí&lt;/em&gt;” với tỷ lệ codeword là &lt;script type=&quot;math/tex&quot;&gt;\frac{1}{2^L}&lt;/script&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Chi phí&lt;/em&gt; cho codeword có độ dài &lt;script type=&quot;math/tex&quot;&gt;0&lt;/script&gt; là &lt;script type=&quot;math/tex&quot;&gt;1&lt;/script&gt; - tức toàn bộ codeword - nghĩa là nếu bạn chọn codeword có độ dài 0 thì bạn sẽ không được chọn bất kỳ codeword nào khác nữa; &lt;em&gt;Chi phí&lt;/em&gt; cho codeword độ dài 1, ví dụ như codeword &lt;script type=&quot;math/tex&quot;&gt;0&lt;/script&gt;, là &lt;script type=&quot;math/tex&quot;&gt;\frac{1}{2}&lt;/script&gt; vì có &lt;script type=&quot;math/tex&quot;&gt;\frac{1}{2}&lt;/script&gt; số lượng codeword bắt đầu bằng &lt;script type=&quot;math/tex&quot;&gt;0&lt;/script&gt;; &lt;em&gt;Chi phí&lt;/em&gt; cho codeword độ dài 2, ví dụ “&lt;script type=&quot;math/tex&quot;&gt;10&lt;/script&gt;”, là &lt;script type=&quot;math/tex&quot;&gt;\frac{1}{4}&lt;/script&gt; vì có &lt;script type=&quot;math/tex&quot;&gt;\frac{1}{4}&lt;/script&gt; số lượng codewprd bắt đầu bằng “10”. Tổng quát, &lt;em&gt;Chi phí&lt;/em&gt; cho codeword giảm theo hàm luỹ mũ của độ dài codeword.&lt;/p&gt;

&lt;!-- ![code-costonly](https://tonydeep.github.io/assets/images/ce_post/code-costonly.png) --&gt;
&lt;p&gt;&lt;img src=&quot;/assets/images/ce_post/code-costonly.png&quot; alt=&quot;&quot; style=&quot;width:700px; height:250px;&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;công-thức-tính-entropy&quot;&gt;Công thức tính Entropy&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;Chi phí&lt;/em&gt; cho codeword độ dài L là &lt;script type=&quot;math/tex&quot;&gt;cost = \frac{1}{2^L}&lt;/script&gt;, hay ngược lại nếu ta biết &lt;script type=&quot;math/tex&quot;&gt;cost&lt;/script&gt; của 1 codeword thì ta có thể tính được độ dài của codeword như sau: &lt;script type=&quot;math/tex&quot;&gt;l = \log_{2}(\frac{1}{cost})&lt;/script&gt;. Nếu bạn “&lt;em&gt;tiêu&lt;/em&gt;” một chi phí &lt;script type=&quot;math/tex&quot;&gt;p(x)&lt;/script&gt; cho codeword &lt;script type=&quot;math/tex&quot;&gt;x&lt;/script&gt;, độ dài của codeword x sẽ là &lt;script type=&quot;math/tex&quot;&gt;\log_{2}(\frac{1}{p(x)})&lt;/script&gt;.&lt;/p&gt;

&lt;!-- ![entropy-def-notitle](https://tonydeep.github.io/assets/images/ce_post/entropy-def-notitle.png)  --&gt;
&lt;p&gt;&lt;img src=&quot;/assets/images/ce_post/entropy-def-notitle.png&quot; alt=&quot;&quot; style=&quot;width:550px; height:300px;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Với một phân bố xác suất cụ thể &lt;script type=&quot;math/tex&quot;&gt;p&lt;/script&gt;, ta xác định được độ dài trung bình ngắn nhất của bộ codeword - được gọi là “&lt;em&gt;entropy&lt;/em&gt;” của &lt;script type=&quot;math/tex&quot;&gt;p&lt;/script&gt;, kí hiệu là &lt;script type=&quot;math/tex&quot;&gt;H(p)&lt;/script&gt;. Ta có:&lt;/p&gt;

&lt;script type=&quot;math/tex; mode=display&quot;&gt;\begin{equation}
H(p) = \sum_{x} p(x) \log_{2}(\frac{1}{p(x)}) = -\sum_{x} p(x) \log_{2}(p(x))
\end{equation}&lt;/script&gt;

&lt;p&gt;Nói một cách khác, nếu x là một sự kiện ngẫu nhiên rời rạc (có thể nhận các giá trị là 1..n), &lt;script type=&quot;math/tex&quot;&gt;p(x)&lt;/script&gt; là xác suất xảy ra của giá trị x, thì Entropy chính là giá trị kỳ vọng &lt;em&gt;số bits&lt;/em&gt; được mã hoá tối ưu. Như vậy, trung bình mỗi khi cần nhắn tin, Bob và Alice cần sử dụng ít nhất &lt;script type=&quot;math/tex&quot;&gt;H(p)&lt;/script&gt; bit.&lt;/p&gt;

&lt;p&gt;Entropy mô tả độ “&lt;strong&gt;&lt;em&gt;không chắc chắn&lt;/em&gt;&lt;/strong&gt;” của thông tin và là một cách để bạn định lượng được thông tin này. Giả sử nếu bạn biết chắc chắn có 2 sự kiện xảy ra với xác suất 50/50, bạn chắc chắn chỉ cần dùng 1 bit để nhắn tin. Hoặc nếu bạn biết có 16 sự kiện xảy ra với xác suất như nhau và &lt;script type=&quot;math/tex&quot;&gt;= \frac{1}{16}&lt;/script&gt; thì bạn chắc chắn chỉ cần 4 bit để nhắn tin.&lt;/p&gt;

&lt;p&gt;&lt;a id=&quot;minimizing-cross-entropy&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;cross-entropy&quot;&gt;Cross Entropy&lt;/h2&gt;

&lt;!-- ![Tools](https://tonydeep.github.io/assets/images/ce_post/tools.jpg) --&gt;
&lt;p&gt;&lt;img src=&quot;/assets/images/ce_post/tools.jpg&quot; alt=&quot;&quot; style=&quot;width:350px; height:250px;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Trở lại với câu chuyện của Bob và Alice, lúc trước 2 bạn chỉ nói tới sự quan tâm của Bob về 4 loại động vật: &lt;script type=&quot;math/tex&quot;&gt;dog&lt;/script&gt;, &lt;script type=&quot;math/tex&quot;&gt;cat&lt;/script&gt;, &lt;script type=&quot;math/tex&quot;&gt;fish&lt;/script&gt; và &lt;script type=&quot;math/tex&quot;&gt;bird&lt;/script&gt;, đặc biệt sở thích của Bob về &lt;script type=&quot;math/tex&quot;&gt;dog&lt;/script&gt;. Có chút thay đổi trong hoàn cảnh này là với Alice, cô cũng thích cả 4 loại động vật trên như Bob, nhưng cô thích nói về &lt;script type=&quot;math/tex&quot;&gt;cat&lt;/script&gt; hơn cả. Như vậy, 2 người có cùng “&lt;script type=&quot;math/tex&quot;&gt;vocabulary size&lt;/script&gt;” nhưng khác nhau về tần suất cho từng loại. Bob có thể nói cả ngày về chủ đề &lt;script type=&quot;math/tex&quot;&gt;dog&lt;/script&gt;, trong khi đó Alice lại cũng có thể nói cả ngày với chủ đề &lt;script type=&quot;math/tex&quot;&gt;cat&lt;/script&gt;.&lt;/p&gt;

&lt;p&gt;Cụ thể như hình dưới đây:&lt;/p&gt;

&lt;!-- ![DogCatWordFreq](https://tonydeep.github.io/assets/images/ce_post/DogCatWordFreq.png)  --&gt;
&lt;p&gt;&lt;img src=&quot;/assets/images/ce_post/DogCatWordFreq.png&quot; alt=&quot;&quot; style=&quot;width:450px; height:250px;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Ban đầu, Alice gửi tin cho Bob cùng sử dụng bộ code của Bob. Tuy nhiên tin nhắn của Alice lại có vẻ dài hơn so với mong đợi của 2 bạn. Bộ code của Bob đã được tối ưu dựa trên phân bố xác suất của Bob. Alice đã sử dụng bộ code được tối ưu (&lt;strong&gt;&lt;em&gt;suboptimal&lt;/em&gt;&lt;/strong&gt;) dựa trên phân bố xác suất của riêng mình. Do đó trong khi độ dài trung bình codeword của Bob là sử dụng bộ code của Bob là &lt;script type=&quot;math/tex&quot;&gt;1.75&lt;/script&gt; bit, thì độ dài trung bình codeword của Alice sử dụng bộ code của Bob lại dài hơn là &lt;script type=&quot;math/tex&quot;&gt;2.25&lt;/script&gt; bit.&lt;/p&gt;

&lt;p&gt;Vậy làm sao để đánh giá 2 codeword này??&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Cross_entropy&quot;&gt;Cross-Entropy&lt;/a&gt; là độ đo đánh giá độ dài trung bình số lượng bit cần thiết để mã hoá thông điệp với phân bố xác suất là &lt;script type=&quot;math/tex&quot;&gt;q(x)&lt;/script&gt;, sử dụng bộ codeword tối ưu (có phân bố xác suất là &lt;script type=&quot;math/tex&quot;&gt;p(x)&lt;/script&gt;).&lt;/p&gt;

&lt;p&gt;Nếu bạn nghĩ phân bố xác suất là một &lt;strong&gt;&lt;em&gt;tool&lt;/em&gt;&lt;/strong&gt; để mã hoá thông tin, thì &lt;strong&gt;entropy&lt;/strong&gt; là độ đo để đánh giá số lượng bit bạn cần để sử dụng &lt;strong&gt;&lt;em&gt;tool chuẩn&lt;/em&gt;&lt;/strong&gt; &lt;script type=&quot;math/tex&quot;&gt;p(x)&lt;/script&gt; - đây là tool đã được tối ưu vì bạn không thể mã hoá sử dụng số bit trung bình ít hơn.&lt;/p&gt;

&lt;p&gt;Ngược lại, &lt;strong&gt;cross-entropy&lt;/strong&gt; là số lượng bit bạn cần để nếu bạn mã hoá thông tin của &lt;strong&gt;&lt;em&gt;tool chuẩn&lt;/em&gt;&lt;/strong&gt; &lt;script type=&quot;math/tex&quot;&gt;p(x)&lt;/script&gt; sử dụng &lt;strong&gt;&lt;em&gt;tool sai&lt;/em&gt;&lt;/strong&gt; &lt;script type=&quot;math/tex&quot;&gt;q(x)&lt;/script&gt;. Nghĩa là khi mã hoá thông điệp cho sự kiện &lt;script type=&quot;math/tex&quot;&gt;i^{th}&lt;/script&gt; thay vì sử dụng &lt;script type=&quot;math/tex&quot;&gt;\log_{2} \frac{1}{p(x_{i})}&lt;/script&gt; bit bạn lại dùng  &lt;script type=&quot;math/tex&quot;&gt;log_{2} \frac{1}{q(x_{i})}&lt;/script&gt; bit.&lt;/p&gt;

&lt;p&gt;Ta có:
&lt;script type=&quot;math/tex&quot;&gt;H(p, q) = H_{q}(p) = \sum_{x} p(x) \log(\frac{1}{q(x)}) = - \sum_{x} p(x) \log(q(x))&lt;/script&gt;&lt;/p&gt;

&lt;p&gt;Ví dụ ta có:&lt;/p&gt;

&lt;!-- ![CrossEntropyDef](https://tonydeep.github.io/assets/images/ce_post/CrossEntropyDef.png) --&gt;
&lt;p&gt;&lt;img src=&quot;/assets/images/ce_post/CrossEntropyDef.png&quot; alt=&quot;&quot; style=&quot;width:500px; height:200px;&quot; /&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Cross-entroy luôn luôn lớn hơn Entropy; Việc mã hoá sử dụng &lt;em&gt;tool sai&lt;/em&gt; &lt;script type=&quot;math/tex&quot;&gt;q(x)&lt;/script&gt; sẽ luôn phải sử dụng nhiều bit hơn.&lt;/li&gt;
  &lt;li&gt;Cross-entropy không có tính chất đối xứng, nghĩa là &lt;script type=&quot;math/tex&quot;&gt;H(p, q) \neq H(q, p)&lt;/script&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ta có thể có một vài kịch bản sau:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Bob sử dụng Bob code: &lt;script type=&quot;math/tex&quot;&gt;H(p) = H_{p}(p) = 1.75&lt;/script&gt; bit&lt;/li&gt;
  &lt;li&gt;Alice sử dụng Bob code: &lt;script type=&quot;math/tex&quot;&gt;H_{p}(q) = 2.25&lt;/script&gt; bit&lt;/li&gt;
  &lt;li&gt;Alice sử dụng Alice code: &lt;script type=&quot;math/tex&quot;&gt;H(p) = H_{q}(q) = 1.75&lt;/script&gt; bit&lt;/li&gt;
  &lt;li&gt;Bod sử dụng Alice code: &lt;script type=&quot;math/tex&quot;&gt;H_{q}(p) = 2.375&lt;/script&gt; bit&lt;/li&gt;
&lt;/ul&gt;

&lt;!-- ![CrossEntropyCompare](https://tonydeep.github.io/assets/images/ce_post/CrossEntropyCompare.png) --&gt;
&lt;p&gt;&lt;img src=&quot;/assets/images/ce_post/CrossEntropyCompare.png&quot; alt=&quot;&quot; style=&quot;width:800px; height:400px;&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;tại-sao-cross-entropy-lại-quan-trọng-&quot;&gt;Tại sao cross-entropy lại quan trọng ???&lt;/h3&gt;
&lt;p&gt;Cross-entropy cho biết sự mức độ khác biệt giữa 2 phân bố xác suất. Sự khác biệt giữa phân bố &lt;script type=&quot;math/tex&quot;&gt;p&lt;/script&gt; và &lt;script type=&quot;math/tex&quot;&gt;q&lt;/script&gt; càng lớn, thì cross-entropy của p đối với q sẽ càng lớn hơn entropy của p.&lt;/p&gt;

&lt;!-- ![CrossEntropyPQ](https://tonydeep.github.io/assets/images/ce_post/CrossEntropyPQ.png) --&gt;
&lt;p&gt;&lt;img src=&quot;/assets/images/ce_post/CrossEntropyPQ.png&quot; alt=&quot;&quot; style=&quot;width:250px; height:100px;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Tương tự, sự khác biệt giữa phân bố &lt;script type=&quot;math/tex&quot;&gt;p&lt;/script&gt; và &lt;script type=&quot;math/tex&quot;&gt;q&lt;/script&gt; càng lớn, thì cross-entropy của q đối với p sẽ càng lớn hơn entropy của q.&lt;/p&gt;

&lt;!-- ![CrossEntropyQP](https://tonydeep.github.io/assets/images/ce_post/CrossEntropyQP.png) --&gt;
&lt;p&gt;&lt;img src=&quot;/assets/images/ce_post/CrossEntropyQP.png&quot; alt=&quot;&quot; style=&quot;width:250px; height:100px;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;a id=&quot;kl-divergence&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;kl-divergence---kl-phân-kỳ&quot;&gt;KL Divergence - KL phân kỳ&lt;/h2&gt;

&lt;!-- ![Taxes](https://tonydeep.github.io/assets/images/ce_post/taxes.jpg) --&gt;
&lt;p&gt;&lt;img src=&quot;/assets/images/ce_post/KL-Gauss-Example.png&quot; alt=&quot;&quot; style=&quot;width:550px; height:450px;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Điều thực sự thú vị ở đây chính là sự khác biệt giữa entropy và cross-entropy. Có thể nói nó là sự khác biệt hay &lt;em&gt;khoảng cách&lt;/em&gt; giữa 2 phân bố xác suất &lt;script type=&quot;math/tex&quot;&gt;p(x)&lt;/script&gt; và &lt;script type=&quot;math/tex&quot;&gt;q(x)&lt;/script&gt;. Nếu 2 phân bố xác suất này giống nhau thì khoảng cách là &lt;script type=&quot;math/tex&quot;&gt;0&lt;/script&gt; và ngược lại sự khác biệt càng lớn thì giá trị này càng lớn.&lt;/p&gt;

&lt;p&gt;Và nó được gọi là &lt;a href=&quot;https://en.wikipedia.org/wiki/Kullback%E2%80%93Leibler_divergence&quot;&gt;KL divergence&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;\begin{equation}
D( p | q) = \sum_x p_x \log \frac{1}{q_x} - \sum_x p_x \log \frac{1}{p_x}
= \sum_x p_x \log \frac{p_x}{q_x} 
= H(P, Q) - H(P) 
\end{equation}&lt;/p&gt;

&lt;p&gt;với &lt;script type=&quot;math/tex&quot;&gt;H(P, Q)&lt;/script&gt; là cross-entropy; &lt;script type=&quot;math/tex&quot;&gt;H(P)&lt;/script&gt; là entropy của P.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Lưu ý&lt;/em&gt;&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Việc cực tiểu hoá cross entroypy tương đương với việc cực tiểu hoá KL phân kỳ.&lt;/li&gt;
  &lt;li&gt;Cross entropy và KL phân kỳ được sử dụng phổ biến trong &lt;em&gt;Machine Learning&lt;/em&gt;. Chúng ta thường muốn một phân bố xác suất nào đó tiến gần với một phân bố khác. Ví dụ như chúng ta muốn phân bố của dự đoán tiến gần với phân bố cơ sở. KL phân kỳ cho ta một cái nhìn tự nhiên về vấn đề trên, tuy nhiên có vẻ như cross entropy lại được biết đến và sử dụng  rộng rãi hơn.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a id=&quot;predictive-power&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;khả-năng-dự-đoán&quot;&gt;Khả năng dự đoán&lt;/h2&gt;

&lt;!-- ![Fortune Teller](https://tonydeep.github.io/assets/images/ce_post/predict.jpg) --&gt;
&lt;p&gt;&lt;img src=&quot;/assets/images/ce_post/golden-wheel.jpg&quot; alt=&quot;&quot; style=&quot;width:350px; height:250px;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Ở đây chúng ta sử dụng cross-entropy để đánh giá sự khác biệt giữa 2 phân bố xác suất &lt;script type=&quot;math/tex&quot;&gt;y&lt;/script&gt; và &lt;script type=&quot;math/tex&quot;&gt;\hat{y}&lt;/script&gt; và tính lỗi (&lt;em&gt;loss&lt;/em&gt;) dựa trên tổng cross entropy của toàn bộ dữ liệu training.&lt;/p&gt;

&lt;p&gt;Cụ thể ta có hàm mục tiêu như sau:&lt;/p&gt;

&lt;p&gt;\begin{equation} 
H({y^{(n)}}, {\hat{y}^{(n)}}) = \sum_n H(y^{(n)}, \hat{y}^{(n)}) 
\end{equation}&lt;/p&gt;

&lt;p&gt;Một cách tiếp cận phổ biến khác là chúng ta tiến hành điều chỉnh tham số mô hình sao cho &lt;em&gt;likelihood&lt;/em&gt; của mô hình với dữ liệu đầu vào đạt &lt;em&gt;max&lt;/em&gt;. Với bài toán phân lớp chúng ta thường hay sử dụng mô hình phân biệt (&lt;a href=&quot;https://en.wikipedia.org/wiki/Discriminative_model&quot;&gt;discriminative model&lt;/a&gt;) ở đó dữ liệu training thường bao gồm cả dữ liệu và nhãn cần dự đoán. Nói cách khác chúng ta thường sẽ dự đoán &lt;em&gt;ground-truth labels&lt;/em&gt; với dữ liệu cho trước.&lt;/p&gt;

&lt;p&gt;Với giả sử dữ liệu của bài toán là độc lập và phân bố đồng nhất (&lt;a href=&quot;http://math.stackexchange.com/questions/466927/independent-identically-distributed-iid-random-variables&quot;&gt;independent and identically distributed&lt;/a&gt;), &lt;em&gt;likelihood&lt;/em&gt; sẽ được tính như sau:&lt;/p&gt;

&lt;script type=&quot;math/tex; mode=display&quot;&gt;L(\{y^{(n)}\}, \{\hat{y}^{(n)}\}) = \prod_n L(y^{(n)}, \hat{y}^{(n)})&lt;/script&gt;

&lt;p&gt;Vậy thế nào là &lt;strong&gt;&lt;em&gt;likelihood&lt;/em&gt;&lt;/strong&gt;? Đó chính là phần tử cụ thể của &lt;script type=&quot;math/tex&quot;&gt;\hat{y}^{(n)}&lt;/script&gt; tương ứng với &lt;em&gt;ground-truth label&lt;/em&gt; của &lt;script type=&quot;math/tex&quot;&gt;y^{(n)}&lt;/script&gt;.&lt;/p&gt;

&lt;p&gt;Ví dụ trong bài toán phân loại ảnh số MNIST: Với ảnh training thứ nhất có nhãn là &lt;script type=&quot;math/tex&quot;&gt;y^{(1)} = (0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)^T&lt;/script&gt;, thì &lt;strong&gt;&lt;em&gt;likelihood&lt;/em&gt;&lt;/strong&gt; &lt;script type=&quot;math/tex&quot;&gt;L(y^{(1)}, \hat{y}^{(1)})&lt;/script&gt; sẽ là phần tử thứ &lt;em&gt;3-th&lt;/em&gt; của kết quả dự đoán &lt;script type=&quot;math/tex&quot;&gt;\hat{y}^{(1)} = (0.0, 0.1, 0.1, 0.25, 0.0, 0.1, 0.1, 0.35, 0.0, 0.0)^T&lt;/script&gt;, hay &lt;script type=&quot;math/tex&quot;&gt;L(y^{(1)}, \hat{y}^{(1)}) = \hat{y}_{1}^{(1)} = 0.25&lt;/script&gt;.&lt;/p&gt;

&lt;p&gt;Tiếp tục giả sử chúng ta có tất cả 3 ảnh trong training data là các số 3, 5, 8 với các phân bố &lt;em&gt;ground-truth&lt;/em&gt; là:&lt;/p&gt;

&lt;p&gt;&lt;script type=&quot;math/tex&quot;&gt;y^{(1)} = (0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)^T&lt;/script&gt;,&lt;/p&gt;

&lt;p&gt;&lt;script type=&quot;math/tex&quot;&gt;y^{(2)} = (0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0)^T&lt;/script&gt;, và&lt;/p&gt;

&lt;p&gt;&lt;script type=&quot;math/tex&quot;&gt;y^{(3)} = (0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0)^T&lt;/script&gt;.&lt;/p&gt;

&lt;p&gt;Mô hình sẽ dự đoán 3 phân bố tương ứng là:&lt;/p&gt;

&lt;p&gt;&lt;script type=&quot;math/tex&quot;&gt;\hat{y}^{(1)} = (0.0, 0.1, 0.1, 0.25, 0.0, 0.1, 0.1, 0.35, 0.0, 0.0)^T&lt;/script&gt;,&lt;/p&gt;

&lt;p&gt;&lt;script type=&quot;math/tex&quot;&gt;\hat{y}^{(2)} = (0.0, 0.1, 0.1, 0.25, 0.0, 0.3, 0.1, 0.15, 0.0, 0.0)^T&lt;/script&gt;, và&lt;/p&gt;

&lt;p&gt;&lt;script type=&quot;math/tex&quot;&gt;\hat{y}^{(3)} = (0.0, 0.1, 0.1, 0.25, 0.0, 0.1, 0.1, 0.0, 0.35, 0.0)^T&lt;/script&gt;.&lt;/p&gt;

&lt;p&gt;Và &lt;em&gt;likelihood&lt;/em&gt; của cả training data sẽ là:&lt;/p&gt;

&lt;script type=&quot;math/tex; mode=display&quot;&gt;L(\{y^{(1)}, y^{(2)}, y^{(3)}\}, \{\hat{y}^{(1)}, \hat{y}^{(2)}, \hat{y}^{(3)}\}) = \hat{y}^{(1)}_3 \, \hat{y}^{(2)}_5 \, \hat{y}^{(3)}_8 \&lt;/script&gt;

&lt;p&gt;Vậy nhiệm vụ của chúng ta là điều chỉnh tham số mô hình sao cho &lt;em&gt;likelihood&lt;/em&gt; &lt;script type=&quot;math/tex&quot;&gt;L(\{y^{(n)}\}, \{\hat{y}^{(n)}\})&lt;/script&gt; đạt &lt;strong&gt;&lt;em&gt;max&lt;/em&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a id=&quot;unified-loss&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;likelihood&quot;&gt;Likelihood&lt;/h2&gt;

&lt;!-- ![Tape Measure](https://tonydeep.github.io/assets/images/ce_post/tape_measure.jpg) --&gt;
&lt;p&gt;&lt;img src=&quot;/assets/images/ce_post/tape_measure.jpg&quot; alt=&quot;&quot; style=&quot;width:350px; height:250px;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Cùng phân tích cụ thể hơn về công thức tính &lt;em&gt;likelihood&lt;/em&gt; trên:&lt;/p&gt;

&lt;p&gt;Thứ nhất, hàm logarit là hàm đơn điệu, do vậy việc &lt;em&gt;cực đại hoá likelihood&lt;/em&gt; sẽ tương đương với việc &lt;em&gt;cực đại hoá log likelihood&lt;/em&gt;, hay ngược lại là tương đương với việc &lt;em&gt;cực tiểu hoá &lt;strong&gt;negative log likelihood&lt;/strong&gt;&lt;/em&gt;.&lt;/p&gt;

&lt;script type=&quot;math/tex; mode=display&quot;&gt;-\log L(\{y^{(n)}\}, \{\hat{y}^{(n)}\}) = -\log \prod_n L(y^{(n)}, \hat{y}^{(n)}) = -\sum_n \log L(y^{(n)}, \hat{y}^{(n)})&lt;/script&gt;

&lt;p&gt;Thứ hai, như chúng ta phân tích ở phần trên, &lt;em&gt;log likelihood&lt;/em&gt; của &lt;script type=&quot;math/tex&quot;&gt;y^{(n)}&lt;/script&gt; được tính khá đơn giản chính là log của phần tử tương ứng trong &lt;script type=&quot;math/tex&quot;&gt;\hat{y}^{(n)}&lt;/script&gt;, cụ thể hơn là phần tử thứ &lt;script type=&quot;math/tex&quot;&gt;i&lt;/script&gt; thoả mãn &lt;script type=&quot;math/tex&quot;&gt;y^{(n)}_i = 1.0&lt;/script&gt;.&lt;/p&gt;

&lt;p&gt;Do đó chúng ta có thể viết lại công thức tính log likelihood cho mẫu training data thứ &lt;script type=&quot;math/tex&quot;&gt;n&lt;/script&gt; đơn giản hơn như sau:&lt;/p&gt;

&lt;script type=&quot;math/tex; mode=display&quot;&gt;\log L(y^{(n)}, \hat{y}^{(n)}) = \sum_i y^{(n)}_i \log \hat{y}^{(n)}_i&lt;/script&gt;

&lt;p&gt;và negative log likelihood cũng được viết lại như sau:&lt;/p&gt;

&lt;script type=&quot;math/tex; mode=display&quot;&gt;- \log L(\{y^{(n)}\}, \{\hat{y}^{(n)}\}) = -\sum_n \sum_i y^{(n)}_i \log \hat{y}^{(n)}_i&lt;/script&gt;

&lt;p&gt;Và đây chính là công thức tính tổng tất cả &lt;strong&gt;&lt;em&gt;cross-entropy&lt;/em&gt;&lt;/strong&gt; trên toàn bộ training data:&lt;/p&gt;

&lt;script type=&quot;math/tex; mode=display&quot;&gt;-\log L(\{y^{(n)}\}, \{\hat{y}^{(n)}\}) = \sum_n \big[-\sum_i y_i \log \hat{y}^{(n)}_i\big] = \sum_n H(y^{(n)}, \hat{y}^{(n)})&lt;/script&gt;

&lt;p&gt;&lt;a id=&quot;conclusions&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;thảo-luận&quot;&gt;Thảo luận&lt;/h2&gt;
&lt;!-- ![Stairs](https://tonydeep.github.io/assets/images/ce_post/stairs.jpg) --&gt;
&lt;p&gt;&lt;img src=&quot;/assets/images/ce_post/politic_discussion_121113_163116.jpg&quot; alt=&quot;&quot; style=&quot;width:350px; height:250px;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Khi xây dựng mô hình xác suất cho bài toán phân lớp có các lớp phân biệt lẫn nhau, chúng ta cần đánh giá sự khác biệt giữa xác suất dự đoán &lt;script type=&quot;math/tex&quot;&gt;\hat{y}&lt;/script&gt; và xác suất &lt;em&gt;ground-truth&lt;/em&gt; &lt;script type=&quot;math/tex&quot;&gt;y&lt;/script&gt; và trong quá trình &lt;strong&gt;&lt;em&gt;training&lt;/em&gt;&lt;/strong&gt; chúng ta sẽ điều chỉnh tham số sao cho sự khác biệt là nhỏ nhất.&lt;/p&gt;

&lt;p&gt;Và các bạn có thể nhận thấy rằng, &lt;strong&gt;&lt;em&gt;cross-entropy&lt;/em&gt;&lt;/strong&gt; là một lựa chọn phù hợp cho bài toán phân lớp trên.&lt;/p&gt;

&lt;p&gt;Có 2 khía cạnh đánh giá việc tiếp cận này:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Thứ nhất, việc cực tiểu hoá cross-entropy cho phép chúng ta tìm được &lt;script type=&quot;math/tex&quot;&gt;\hat{y}&lt;/script&gt; thoả mãn đáp ứng số bits tối thiểu cần thiết để &lt;em&gt;mã hoá&lt;/em&gt; thông tin từ &lt;script type=&quot;math/tex&quot;&gt;y&lt;/script&gt; sử dụng &lt;script type=&quot;math/tex&quot;&gt;\hat{y}&lt;/script&gt;&lt;/li&gt;
  &lt;li&gt;Thứ hai, việc cực tiểu hoá cross-entropy tương đương với việc cực tiểu hoá &lt;strong&gt;&lt;em&gt;negative log likelihood&lt;/em&gt;&lt;/strong&gt; hay chính là việc đánh giá trực tiếp khả năng dự đoán của mô hình.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a id=&quot;resources&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;nguồn-tham-khảo&quot;&gt;Nguồn tham khảo&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://colah.github.io/posts/2015-09-Visual-Information/&quot;&gt;Visual Information Theory&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><author><name>TonyKhanh</name></author><category term="representations" /><category term="nlp" /><category term="recursive-neural-networks" /><category term="rnn" /><summary type="html">This post reviews some extremely remarkable results in applying deep neural networks to natural language processing (NLP)</summary></entry></feed>