<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Ldy&#39;s Blog</title>
  
  <link href="/atom.xml" rel="self"/>
  
  <link href="http://buptldy.github.io/"/>
  <updated>2016-11-29T09:10:57.292Z</updated>
  <id>http://buptldy.github.io/</id>
  
  <author>
    <name>Ldy</name>
    
  </author>
  
  <generator uri="http://hexo.io/">Hexo</generator>
  
  <entry>
    <title>Generative Adversarial Networks</title>
    <link href="http://buptldy.github.io/2016/11/27/2016-11-27-gans/"/>
    <id>http://buptldy.github.io/2016/11/27/2016-11-27-gans/</id>
    <published>2016-11-27T02:00:00.000Z</published>
    <updated>2016-11-29T09:10:57.292Z</updated>
    
    <content type="html">&lt;p&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/public/16-11-27/13513902.jpg&quot; alt=&quot;&quot;&gt;&lt;br&gt;&lt;a id=&quot;more&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;人工智能目前的核心目标应该是赋予机器自主理解我们所在世界的能力。对于人类来说，我们对这个世界所了解的知识可能很快就会忘记，比如我们所处的三维环境中，物体能够交互，移动，碰撞；什么动物会飞，什么动物吃草等等。这些巨大的并且不断扩大的信息现在是很容易被机器获取的，问题的关键是怎么设计模型和算法让机器更好的去分析和理解这些数据中所蕴含的宝藏。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Generative models&lt;/code&gt;(生成模型)现在被认为是能够实现这一目标的最有前景的方法之一。&lt;code&gt;Generative models&lt;/code&gt;通过输入一大堆特定领域的数据进行训练（比如图像，句子，声音等）来使得模型能够产生和输入数据相似的输出。这一直觉的背后可以由下面名言阐述。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“What I cannot create, I do not understand.”  —Richard Feynman&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;生成模型由一个参数数量比训练数据少的多神经网络构成，所以生成模型为了能够产生和训练数据相似的输出就会迫使自己去发现数据中内在的本质内容。训练&lt;code&gt;Generative models&lt;/code&gt;的方法有几种，在这里我们主要阐述其中的&lt;code&gt;Adversarial Training&lt;/code&gt;（对抗训练）方法。&lt;/p&gt;
&lt;h2 id=&quot;Adversarial-Training&quot;&gt;&lt;a href=&quot;#Adversarial-Training&quot; class=&quot;headerlink&quot; title=&quot;Adversarial Training&quot;&gt;&lt;/a&gt;Adversarial Training&lt;/h2&gt;&lt;p&gt;上文说过Adversarial Training是训练生成模型的一种方法。为了训练生成模型，Adversarial Training提出一种&lt;code&gt;Discriminative Model&lt;/code&gt;(判别模型)来和生成模型产生对抗，下面来说说&lt;code&gt;Generative models&lt;/code&gt; $G(z)$ 和 &lt;code&gt;Discriminative Model&lt;/code&gt; $D(x)$ 是如何相互作用的。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;生成模型的目标是模仿输入训练数据, 通过输入一个随机噪声来产生和训练数据相似的样本；&lt;/li&gt;
&lt;li&gt;判别模型的目标就是判断生成模型产生的样本和真实的输入样本之间的相似性。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;其中生成模型和判别模型合起来的框架被称为&lt;code&gt;GAN&lt;/code&gt;网络。通过下图我们来理清判别模型和生成模型之间的输入输出关系：生成模型通过输入随机噪声 $z(z \sim p_z)$ 产生合成样本；而判别模型通过分别输入真实的训练数据和生成模型的训练数据来判断输入的数据是否真实。&lt;/p&gt;
&lt;center&gt;&lt;br&gt;&lt;img src=&quot;https://culurciello.github.io/assets/unsup/gan_simple.svg&quot; alt=&quot;&quot;&gt;&lt;br&gt;&lt;/center&gt;

&lt;p&gt;描述了&lt;code&gt;GAN&lt;/code&gt;的网络结构，但它的优化目标是什么？怎么就可以通过训练使得生成模型能够产生和真实数据相似的输出？优化的目标其实很简单，简单来说就是：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;判别模型努力的想把真实的数据预测为&lt;code&gt;1&lt;/code&gt;，把生成的数据预测为&lt;code&gt;0&lt;/code&gt;；&lt;/li&gt;
&lt;li&gt;而生成模型的奋斗目标则为‘我’要尽力的让判别模型对‘我’生成的数据预测为&lt;code&gt;1&lt;/code&gt;，让判别模型分不清‘我’产生的数据和真实数据之间的区别，从而达到‘以假乱真’的效果。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;下面用形式化说明下如果训练GAN网络, 先定义一些参数：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&quot;text-align:center&quot;&gt;参数&lt;/th&gt;
&lt;th style=&quot;text-align:center&quot;&gt;含义&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:center&quot;&gt;$p_z$&lt;/td&gt;
&lt;td style=&quot;text-align:center&quot;&gt;输入随机噪声 $z$ 的分布&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:center&quot;&gt;$p_{data}$&lt;/td&gt;
&lt;td style=&quot;text-align:center&quot;&gt;未知的输入样本的数据分布&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align:center&quot;&gt;$p_g$&lt;/td&gt;
&lt;td style=&quot;text-align:center&quot;&gt;生成模型的输出样本的数据分布，GAN的目标就是要$p_g=p_{data}$&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;训练判别模型 $D(x)$ 的目标：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;对每一个输入数据 $x \sim p_{data}$ 要使得 $D(x)$ 最大；&lt;/li&gt;
&lt;li&gt;对每一个输入数据 $x \nsim p_{data}$ 要使得 $D(x)$ 最小。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;训练生成模型 $G(z)$ 的目标是来产生样本来欺骗判别模型 $D$, 因此目标为最大化 $D(G(z))$，也就是把生成模型的输出输入到判别模型，然后要让判别模型预测其为真实数据。同时，最大化 $D(G(z))$ 等同于最小化 $1-D(G(z))$，因为 $D$ 的输出是介于0到1之间的，真实数据努力预测为1，否则为0。&lt;/p&gt;
&lt;p&gt;所以把生成模型和判别模型的训练目标结合起来，就得到了&lt;code&gt;GAN&lt;/code&gt;的优化目标：&lt;/p&gt;
&lt;p&gt;$$\min_G \max_D {\mathbb E}_{x\sim p_{\rm data}} \log D(x)+{\mathbb E}_{z\sim p_z}[\log (1-D(G(z)))] $$&lt;/p&gt;
&lt;p&gt;总结一下上面的内容，GAN启发自博弈论中的二人零和博弈，在二人零和博弈中，两位博弈方的利益之和为零或一个常数，即一方有所得，另一方必有所失。GAN模型中的两位博弈方分别由生成模型和判别模型充当。生成模型G捕捉样本数据的分布，判别模型是一个二分类器，估计一个样本来自于训练数据（而非生成数据）的概率。G和D一般都是非线性映射函数，例如多层感知机、卷积神经网络等。生成模型的输入是一些服从某一简单分布（例如高斯分布）的随机噪声z，输出是与训练图像相同尺寸的生成图像。向判别模型D输入生成样本，对于D来说期望输出低概率（判断为生成样本），对于生成模型G来说要尽量欺骗D，使判别模型输出高概率（误判为真实样本），从而形成竞争与对抗。&lt;/p&gt;
&lt;h2 id=&quot;GAN实现&quot;&gt;&lt;a href=&quot;#GAN实现&quot; class=&quot;headerlink&quot; title=&quot;GAN实现&quot;&gt;&lt;/a&gt;GAN实现&lt;/h2&gt;&lt;p&gt;一个简单的一维数据GAN网络的tensorflow实现:&lt;a href=&quot;https://github.com/ericjang/genadv_tutorial&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;genadv_tutorial&lt;/a&gt;&lt;br&gt;其一维训练数据分布如下所示，是一个均值-1， $\sigma =1$ 的正态分布。&lt;/p&gt;
&lt;center&gt;&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/public/16-11-24/4360345.jpg&quot; alt=&quot;&quot;&gt;&lt;br&gt;&lt;/center&gt;

&lt;p&gt;我们结合代码和上面的理论内容来分析下GAN的具体实现，判别模型的优化目标为最大化下式，其中 $D_1(x)$ 表示判别真实数据, $D_2(G(z))$ 表示对生成的数据进行判别， 其中 $D_1$ 和 $D_2$ 是共享参数的， 也就是说是同一个判别模型。&lt;/p&gt;
&lt;p&gt;$$\log(D_1(x))+\log(1-D_2(G(z)))$$&lt;/p&gt;
&lt;p&gt;对应的python代码如下：&lt;br&gt;&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;batch=tf.Variable(&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;obj_d=tf.reduce_mean(tf.log(D1)+tf.log(&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;-D2))&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;opt_d=tf.train.GradientDescentOptimizer(&lt;span class=&quot;number&quot;&gt;0.01&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;              .minimize(&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;-obj_d,global_step=batch,var_list=theta_d)&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;为了优化 $G$, 我们想要最大化 $D_2(x’)$(成功欺骗 $D$ )，因此 $G$ 的优化函数为：&lt;/p&gt;
&lt;p&gt;$$\log(D_2(G(z)))$$&lt;/p&gt;
&lt;p&gt;对应的python代码：&lt;/p&gt;
&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;batch=tf.Variable(&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;obj_g=tf.reduce_mean(tf.log(D2))&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;opt_g=tf.train.GradientDescentOptimizer(&lt;span class=&quot;number&quot;&gt;0.01&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;              .minimize(&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;-obj_g,global_step=batch,var_list=theta_g)&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;定义好优化目标后，下面就是训练的主要代码了：&lt;br&gt;&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;# Algorithm 1, GoodFellow et al. 2014&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; i &lt;span class=&quot;keyword&quot;&gt;in&lt;/span&gt; range(TRAIN_ITERS):&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    x= np.random.normal(mu,sigma,M) &lt;span class=&quot;comment&quot;&gt;# sample minibatch from p_data&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    z= np.random.random(M)  &lt;span class=&quot;comment&quot;&gt;# sample minibatch from noise prior&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    sess.run(opt_d, &amp;#123;x_node: x, z_node: z&amp;#125;) &lt;span class=&quot;comment&quot;&gt;# update discriminator D&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    z= np.random.random(M) &lt;span class=&quot;comment&quot;&gt;# sample noise prior&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    sess.run(opt_g, &amp;#123;z_node: z&amp;#125;) &lt;span class=&quot;comment&quot;&gt;# update generator G&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;下面是实验的结果，左图是训练之间的数据，可以看到生成数据的分布和训练数据相差甚远；右图是训练后的数据分析，生成数据和训练数据的分布接近了很多，且此时判别模型的输出分布在0.5左右，说明生成模型顺利的欺骗到判别模型。&lt;/p&gt;
&lt;figure&gt;&lt;br&gt;    &lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/public/16-11-29/64984825.jpg&quot;&gt;&lt;br&gt;&lt;br&gt;&lt;/figure&gt;

&lt;h2 id=&quot;DCGAN&quot;&gt;&lt;a href=&quot;#DCGAN&quot; class=&quot;headerlink&quot; title=&quot;DCGAN&quot;&gt;&lt;/a&gt;DCGAN&lt;/h2&gt;&lt;p&gt;GAN的一个改进模型就是DCGAN。这个网络的生成模型的输入为一个100个符合均匀分布的随机数（通常被称为&lt;code&gt;code&lt;/code&gt;），然后产生输出为64x64x3的输出图像(下图中 $G(z)$ ), 当&lt;code&gt;code&lt;/code&gt;逐渐递增时，生成模型输出的图像也逐渐变化。下图中的生产模型主要由&lt;a href=&quot;http://buptldy.github.io/2016/10/29/2016-10-29-deconv/&quot;&gt;反卷积层&lt;/a&gt;构成, 判别模型就由简单的卷积层组成，最后输出一个判断输入图片是否为真实数据的概率 $P(x)$ 。&lt;/p&gt;
&lt;center&gt;&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/public/16-11-27/33141448.jpg&quot;&gt;&lt;br&gt;&lt;/center&gt;

&lt;p&gt;下图为随着迭代次数，DCGAN产生图像的变化过程。&lt;/p&gt;
&lt;center&gt;&lt;br&gt;&lt;img src=&quot;https://openai.com/assets/research/generative-models/learning-gan-ffc4c09e6079283f334b2485ae663a6587d937a45ebc1d8aeac23a67889a3cf5.gif&quot;&gt;&lt;br&gt;&lt;/center&gt;

&lt;p&gt;训练好网络之后，其中的生成模型和判别模型都有其他的作用。一个训练好的判别模型能够用来对数据提取特征然后进行分类任务。通过输入随机向量生成模型可以产生一些非常有意思的的图片，如下图所示，当输入空间平滑变化时，输出的图片也在平滑转变。&lt;/p&gt;
&lt;center&gt;&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/public/16-11-25/42718244.jpg&quot;&gt;&lt;br&gt;&lt;/center&gt;

&lt;p&gt;还有一个非常有意思的属性就是如果对生产模型的输入向量做一些简单的数学运算，那么学习的特征输出也有同样的性质，如下图所示。&lt;/p&gt;
&lt;center&gt;&lt;br&gt;&lt;img src=&quot;https://fb-s-a-a.akamaihd.net/h-ak-xfp1/t39.2365-6/13438466_275356996149902_2140145659_n.jpg&quot;&gt;&lt;br&gt;&lt;/center&gt;

&lt;h2 id=&quot;GAN的训练及其改进&quot;&gt;&lt;a href=&quot;#GAN的训练及其改进&quot; class=&quot;headerlink&quot; title=&quot;GAN的训练及其改进&quot;&gt;&lt;/a&gt;GAN的训练及其改进&lt;/h2&gt;&lt;p&gt;上面使用GAN产生的图像虽然效果不错，但其实GAN网络的训练过程是非常不稳定的。&lt;br&gt;通常在实际训练GAN中所碰到的一个问题就是判别模型的收敛速度要比生成模型的收敛速度要快很多，通常的做法就是让生成模型多训练几次来赶上生成模型，但是存在的一个问题就是通常生成模型和判别模型的训练是相辅相成的，理想的状态是让生成模型和判别模型在每次的训练过程中同时变得更好。判别模型理想的minimum loss应该为0.5，这样才说明判别模型分不出是真实数据还是生成模型产生的数据。&lt;/p&gt;
&lt;h3 id=&quot;Improved-GANs&quot;&gt;&lt;a href=&quot;#Improved-GANs&quot; class=&quot;headerlink&quot; title=&quot;Improved GANs&quot;&gt;&lt;/a&gt;Improved GANs&lt;/h3&gt;&lt;p&gt;&lt;a href=&quot;https://arxiv.org/pdf/1606.03498v1.pdf&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;Improved techniques for training GANs&lt;/a&gt;这篇文章提出了很多改进GANs训练的方法，其中提出一个想法叫&lt;code&gt;Feature matching&lt;/code&gt;，之前判别模型只判别输入数据是来自真实数据还是生成模型。现在为判别模型提出了一个新的目标函数来判别生成模型产生图像的统计信息是否和真实数据的相似。让 $f(x)$ 表示判别模型中间层的输出， 新的目标函数被定义为 $|| \mathbb{E}_{x \sim p_{data}}f(x)  -  \mathbb{E}_{z \sim p_z}f(G(z))||^2_2$, 其实就是要求真实图像和合成图像在判别模型中间层的距离要最小。这样可以防止生成模型在当前判别模型上过拟合。&lt;/p&gt;
&lt;h3 id=&quot;InfoGAN&quot;&gt;&lt;a href=&quot;#InfoGAN&quot; class=&quot;headerlink&quot; title=&quot;InfoGAN&quot;&gt;&lt;/a&gt;InfoGAN&lt;/h3&gt;&lt;p&gt;到这可能有些同学会想到，我要是想通过GAN产生我想要的特定属性的图片改怎么办？普通的GAN输入的是随机的噪声，输出也是与之对应的随机图片，我们并不能控制输出噪声和输出图片的对应关系。这样在训练的过程中也会倒置生成模型倾向于产生更容易欺骗判别模型的某一类特定图片，而不是更好的去学习训练数据的分布，这样对模型的训练肯定是不好的。InfoGAN的提出就是为了解决这一问题，通过对输入噪声添加一些类别信息以及控制图像特征(如mnist数字的角度和厚度)的隐含变量来使得生成模型的输入不在是随机噪声。虽然现在输入不再是随机噪声，但是生成模型可能会忽略这些输入的额外信息还是把输入当成和输出无关的噪声，所以需要定义一个生成模型输入输出的互信息，互信息越高，说明输入输出的关联越大。&lt;/p&gt;
&lt;p&gt;下面三张图片展示了通过分别控制输入噪声的类别信息，数字角度信息，数字笔画厚度信息产生指定输出的图片，可以看出InfoGAN产生图片的效果还是很好的。&lt;/p&gt;
&lt;center&gt;&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/public/16-11-29/839516.jpg&quot;&gt;&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/public/16-11-29/10937636.jpg&quot;&gt;&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/public/16-11-29/2995738.jpg&quot;&gt;&lt;br&gt;&lt;/center&gt;

&lt;h3 id=&quot;其他应用&quot;&gt;&lt;a href=&quot;#其他应用&quot; class=&quot;headerlink&quot; title=&quot;其他应用&quot;&gt;&lt;/a&gt;其他应用&lt;/h3&gt;&lt;p&gt;GAN网络还有很多其他的有趣应用，比如下图所示的根据&lt;code&gt;一句话来产生对应的图片&lt;/code&gt;，可能大家都有了解karpathy大神的&lt;a href=&quot;https://github.com/karpathy/neuraltalk2&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;&lt;code&gt;看图说话&lt;/code&gt;&lt;/a&gt;, 但是GAN有能力把这个过程给反过来。&lt;/p&gt;
&lt;center&gt;&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/public/16-11-29/51572272.jpg&quot;&gt;&lt;br&gt;&lt;/center&gt;

&lt;p&gt;还有下面这个“&lt;a href=&quot;https://github.com/bamos/dcgan-completion.tensorflow&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;图像补全&lt;/a&gt;”, 根据图像剩余的信息来匹配最佳的补全内容。&lt;/p&gt;
&lt;center&gt;&lt;br&gt;&lt;img src=&quot;https://github.com/bamos/dcgan-completion.tensorflow/raw/master/completion.compressed.gif&quot;&gt;&lt;br&gt;&lt;/center&gt;

&lt;p&gt;还有下面这个&lt;a href=&quot;https://swarbrickjones.wordpress.com/2016/01/13/enhancing-images-using-deep-convolutional-generative-adversarial-networks-dcgans/&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;图像增强&lt;/a&gt;的例子，有点去马赛克的意思，效果还是挺不错的:-D。&lt;/p&gt;
&lt;center&gt;&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/public/16-11-29/71438836.jpg
&quot;&gt;&lt;br&gt;&lt;/center&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;颜乐存说过，2016年深度学习领域最让他兴奋技术莫过于对抗学习。对抗学习确实是解决非监督学习的一个有效方法，而无监督学习一直都是人工智能领域研究者所孜孜追求的“终极目标”之一。&lt;/p&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://arxiv.org/abs/1406.2661&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;Generative Adversarial Networks&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://arxiv.org/abs/1511.06434&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;Unsupervised Representation Learning with Deep Convolutional Generative Adversarial Networks&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://arxiv.org/abs/1606.03498&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;Improved Techniques for Training GANs&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://arxiv.org/abs/1606.03657&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;InfoGAN: Interpretable Representation Learning by Information Maximizing Generative Adversarial Nets&lt;/a&gt;&lt;/p&gt;
</content>
    
    <summary type="html">
    
      &lt;p&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/public/16-11-27/13513902.jpg&quot; alt=&quot;&quot;&gt;&lt;br&gt;
    
    </summary>
    
    
      <category term="Deep Learning" scheme="http://buptldy.github.io/tags/Deep-Learning/"/>
    
      <category term="Unsupervised Learning" scheme="http://buptldy.github.io/tags/Unsupervised-Learning/"/>
    
  </entry>
  
  <entry>
    <title>Transposed Convolution, Fractionally Strided Convolution or Deconvolution</title>
    <link href="http://buptldy.github.io/2016/10/29/2016-10-29-deconv/"/>
    <id>http://buptldy.github.io/2016/10/29/2016-10-29-deconv/</id>
    <published>2016-10-29T02:00:00.000Z</published>
    <updated>2016-10-30T08:01:56.429Z</updated>
    
    <content type="html">&lt;center&gt;&lt;br&gt;&lt;img src=&quot;http://ww3.sinaimg.cn/large/8c2b2f6fjw1f9ac3snmk6j21130a7wj5.jpg&quot;&gt;&lt;br&gt;&lt;/center&gt;&lt;br&gt;&lt;a id=&quot;more&quot;&gt;&lt;/a&gt;&lt;br&gt;&lt;br&gt;反卷积（Deconvolution）的概念第一次出现是Zeiler在2010年发表的论文&lt;a href=&quot;http://www.matthewzeiler.com/pubs/cvpr2010/cvpr2010.pdf&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;Deconvolutional networks&lt;/a&gt;中，但是并没有指定反卷积这个名字，反卷积这个术语正式的使用是在其之后的工作中(&lt;a href=&quot;https://www.cs.nyu.edu/~gwtaylor/publications/zeilertaylorfergus_iccv2011.pdf&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;Adaptive deconvolutional networks for mid and high level feature learning&lt;/a&gt;)。随着反卷积在神经网络可视化上的成功应用，其被越来越多的工作所采纳比如：场景分割、生成模型等。其中反卷积（Deconvolution）也有很多其他的叫法，比如：Transposed Convolution，Fractional Strided Convolution等等。&lt;br&gt;&lt;br&gt;这篇文章的目的主要有两方面：&lt;br&gt;1. 解释卷积层和反卷积层之间的关系；&lt;br&gt;2. 弄清楚反卷积层输入特征大小和输出特征大小之间的关系。&lt;br&gt;&lt;br&gt;## 卷积层&lt;br&gt;&lt;br&gt;卷积层大家应该都很熟悉了,为了方便说明，定义如下：&lt;br&gt;- 二维的离散卷积（$N = 2$）&lt;br&gt;- 方形的特征输入（$i_1 = i_2 = i$）&lt;br&gt;- 方形的卷积核尺寸（$k_1 = k_2 = k$）&lt;br&gt;- 每个维度相同的步长（$s_1 = s_2 = s$）&lt;br&gt;- 每个维度相同的padding ($p_1 = p_2 = p$)&lt;br&gt;&lt;br&gt;下图表示参数为 $(i=5,k=3,s=2,p=1)$ 的卷积计算过程，从计算结果可以看出输出特征的尺寸为 $(o_1 = o_2 = o = 3)$。&lt;br&gt;&lt;center&gt;&lt;br&gt;    &lt;img src=&quot;http://ww2.sinaimg.cn/large/8c2b2f6fjw1f99h94gnlbg20az0aldi4.gif&quot; width=&quot;300&quot;&gt;&lt;br&gt;&lt;/center&gt;

&lt;p&gt;下图表示参数为 $(i=6,k=3,s=2,p=1)$ 的卷积计算过程，从计算结果可以看出输出特征的尺寸为 $(o_1 = o_2 = o = 3)$。&lt;/p&gt;
&lt;center&gt;&lt;br&gt;    &lt;img src=&quot;http://ww4.sinaimg.cn/large/8c2b2f6fjw1f99h9jeg5ig20cd0bf0v5.gif&quot; width=&quot;300&quot;&gt;&lt;br&gt;&lt;/center&gt;

&lt;p&gt;从上述两个例子我们可以总结出卷积层输入特征与输出特征尺寸和卷积核参数的关系为：&lt;br&gt;$$o = \left\lfloor \frac{i + 2p - k}{s} \right\rfloor + 1.$$&lt;br&gt;其中 $\lfloor x \rfloor$ 表示对 $x$ 向下取整。&lt;/p&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;/p&gt;
&lt;h3 id=&quot;卷积和矩阵相乘&quot;&gt;&lt;a href=&quot;#卷积和矩阵相乘&quot; class=&quot;headerlink&quot; title=&quot;卷积和矩阵相乘&quot;&gt;&lt;/a&gt;卷积和矩阵相乘&lt;/h3&gt;&lt;p&gt;考虑如下一个简单的卷积层运算，其参数为 $(i=4,k=3,s=1,p=0)$，输出 $o=2$。&lt;/p&gt;
&lt;center&gt;&lt;br&gt;&lt;img src=&quot;http://ww3.sinaimg.cn/large/8c2b2f6fjw1f99i1rv4jog206s0770t7.gif&quot; width=&quot;300&quot;&gt;&lt;br&gt;&lt;/center&gt;

&lt;p&gt;对于上述卷积运算，我们把上图所示的3×3卷积核展成一个如下所示的[4,16]的稀疏矩阵 $\mathbf{C}$， 其中非0元素 $w_{i,j}$ 表示卷积核的第 $i$ 行和第 $j$ 列。&lt;/p&gt;
&lt;p&gt;\begin{pmatrix}&lt;br&gt;    w_{0,0} &amp;amp; w_{0,1} &amp;amp; w_{0,2} &amp;amp; 0       &amp;amp; w_{1,0} &amp;amp; w_{1,1} &amp;amp; w_{1,2} &amp;amp; 0       &amp;amp;&lt;br&gt;    w_{2,0} &amp;amp; w_{2,1} &amp;amp; w_{2,2} &amp;amp; 0       &amp;amp; 0       &amp;amp; 0       &amp;amp; 0       &amp;amp; 0       \\&lt;br&gt;    0       &amp;amp; w_{0,0} &amp;amp; w_{0,1} &amp;amp; w_{0,2} &amp;amp; 0       &amp;amp; w_{1,0} &amp;amp; w_{1,1} &amp;amp; w_{1,2} &amp;amp;&lt;br&gt;    0       &amp;amp; w_{2,0} &amp;amp; w_{2,1} &amp;amp; w_{2,2} &amp;amp; 0       &amp;amp; 0       &amp;amp; 0       &amp;amp; 0       \\&lt;br&gt;    0       &amp;amp; 0       &amp;amp; 0       &amp;amp; 0       &amp;amp; w_{0,0} &amp;amp; w_{0,1} &amp;amp; w_{0,2} &amp;amp; 0       &amp;amp;&lt;br&gt;    w_{1,0} &amp;amp; w_{1,1} &amp;amp; w_{1,2} &amp;amp; 0       &amp;amp; w_{2,0} &amp;amp; w_{2,1} &amp;amp; w_{2,2} &amp;amp; 0       \\&lt;br&gt;    0       &amp;amp; 0       &amp;amp; 0       &amp;amp; 0       &amp;amp; 0       &amp;amp; w_{0,0} &amp;amp; w_{0,1} &amp;amp; w_{0,2} &amp;amp;&lt;br&gt;    0       &amp;amp; w_{1,0} &amp;amp; w_{1,1} &amp;amp; w_{1,2} &amp;amp; 0       &amp;amp; w_{2,0} &amp;amp; w_{2,1} &amp;amp; w_{2,2} \\&lt;br&gt;\end{pmatrix}&lt;/p&gt;
&lt;p&gt;我们再把4×4的输入特征展成[16,1]的矩阵 $\mathbf{X}$，那么 $\mathbf{Y = CX}$ 则是一个[4,1]的输出特征矩阵，把它重新排列2×2的输出特征就得到最终的结果，从上述分析可以看出卷积层的计算其实是可以转化成矩阵相乘的。值得注意的是，在一些深度学习网络的开源框架中并不是通过这种这个转换方法来计算卷积的，因为这个转换会存在很多无用的0乘操作，Caffe中具体实现卷积计算的方法可参考&lt;a href=&quot;http://buptldy.github.io/2016/10/01/2016-10-01-im2col/&quot;&gt;Implementing convolution as a matrix multiplication&lt;/a&gt;。&lt;/p&gt;
&lt;p&gt;通过上述的分析，我们已经知道卷积层的前向操作可以表示为和矩阵$\mathbf{C}$相乘，那么 &lt;strong&gt;我们很容易得到卷积层的反向传播就是和$\mathbf{C}$的转置相乘&lt;/strong&gt;。&lt;/p&gt;
&lt;h3 id=&quot;反卷积和卷积的关系&quot;&gt;&lt;a href=&quot;#反卷积和卷积的关系&quot; class=&quot;headerlink&quot; title=&quot;反卷积和卷积的关系&quot;&gt;&lt;/a&gt;反卷积和卷积的关系&lt;/h3&gt;&lt;p&gt;全面我们已经说过反卷积又被称为Transposed(转置) Convolution，我们可以看出其实卷积层的前向传播过程就是反卷积层的反向传播过程，卷积层的反向传播过程就是反卷积层的前向传播过程。因为卷积层的前向反向计算分别为乘 $\mathbf{C}$ 和 $\mathbf{C^T}$,而反卷积层的前向反向计算分别为乘 $\mathbf{C^T}$ 和 $\mathbf{(C^T)^T}$ ，所以它们的前向传播和反向传播刚好交换过来。&lt;/p&gt;
&lt;p&gt;下图表示一个和上图卷积计算对应的反卷积操作，其中他们的输入输出关系正好相反。如果不考虑通道以卷积运算的反向运算来计算反卷积运算的话，我们还可以通过离散卷积的方法来求反卷积（这里只是为了说明，实际工作中不会这么做）。&lt;/p&gt;
&lt;p&gt;同样为了说明，定义反卷积操作参数如下：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;二维的离散卷积（$N = 2$）&lt;/li&gt;
&lt;li&gt;方形的特征输入（$i’_1 = i’_2 = i’$）&lt;/li&gt;
&lt;li&gt;方形的卷积核尺寸（$k’_1 = k’_2 = k’$）&lt;/li&gt;
&lt;li&gt;每个维度相同的步长（$s’_1 = s’_2 = s’$）&lt;/li&gt;
&lt;li&gt;每个维度相同的padding ($p’_1 = p’_2 = p’$)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;下图表示的是参数为( $i’=2,k’=3,s’=1,p’=2$)的反卷积操作，其对应的卷积操作参数为 $(i=4,k=3,s=1,p=0)$。我们可以发现对应的卷积和非卷积操作其 $(k=k’,s=s’)$，但是反卷积却多了$p’=2$。通过对比我们可以发现卷积层中左上角的输入只对左上角的输出有贡献，所以反卷积层会出现 $p’=k-p-1=2$。通过示意图，我们可以发现，反卷积层的输入输出在 $s=s’=1$ 的情况下关系为：&lt;/p&gt;
&lt;p&gt;$$o’=i’-k’+2p’+1=i’+(k-1)-2p$$&lt;/p&gt;
&lt;center&gt;&lt;br&gt;&lt;img src=&quot;http://ww4.sinaimg.cn/large/8c2b2f6fjw1f99j2k89hlg209k0aq41i.gif&quot; width=&quot;300&quot;&gt;&lt;br&gt;&lt;/center&gt;

&lt;h3 id=&quot;Fractionally-Strided-Convolution&quot;&gt;&lt;a href=&quot;#Fractionally-Strided-Convolution&quot; class=&quot;headerlink&quot; title=&quot;Fractionally Strided Convolution&quot;&gt;&lt;/a&gt;Fractionally Strided Convolution&lt;/h3&gt;&lt;p&gt;上面也提到过反卷积有时候也被叫做Fractionally Strided Convolution，翻译过来大概意思就是小数步长的卷积。对于步长 $s&amp;gt;1$的卷积，我们可能会想到其对应的反卷积步长 $s’&amp;lt;1$。 如下图所示为一个参数为 $i = 5, k = 3, s = 2 , p = 1$的卷积操作(就是第一张图所演示的)所对应的反卷积操作。对于反卷积操作的小数步长我们可以理解为：在其输入特征单元之间插入 $s-1$ 个0，插入0后把其看出是新的特征输入，然后此时步长 $s’$ 不再是小数而是为1。因此，结合上面所得到的结论，我们可以得出Fractionally Strided Convolution的输入输出关系为：&lt;/p&gt;
&lt;p&gt;$$ o’ = s(i’ −1)+k −2p$$&lt;/p&gt;
&lt;center&gt;&lt;br&gt;&lt;img src=&quot;http://ww1.sinaimg.cn/large/8c2b2f6fjw1f9aba7bh2ig20az0chwjq.gif&quot; width=&quot;300&quot;&gt;&lt;br&gt;&lt;/center&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://github.com/vdumoulin/conv_arithmetic&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;conv_arithmetic&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://arxiv.org/abs/1609.07009&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;Is the deconvolution layer the same as a convolutional layer?&lt;/a&gt;&lt;/p&gt;
</content>
    
    <summary type="html">
    
      &lt;center&gt;&lt;br&gt;&lt;img src=&quot;http://ww3.sinaimg.cn/large/8c2b2f6fjw1f9ac3snmk6j21130a7wj5.jpg&quot;/&gt;&lt;br&gt;&lt;/center&gt;&lt;br&gt;
    
    </summary>
    
    
      <category term="Deep Learning" scheme="http://buptldy.github.io/tags/Deep-Learning/"/>
    
      <category term="Caffe" scheme="http://buptldy.github.io/tags/Caffe/"/>
    
  </entry>
  
  <entry>
    <title>Caffe Source Code Analysis</title>
    <link href="http://buptldy.github.io/2016/10/09/2016-10-09-Caffe_Code/"/>
    <id>http://buptldy.github.io/2016/10/09/2016-10-09-Caffe_Code/</id>
    <published>2016-10-09T02:00:00.000Z</published>
    <updated>2016-10-09T02:13:14.802Z</updated>
    
    <content type="html">&lt;p&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-10-9/83591184.jpg&quot; alt=&quot;&quot;&gt;&lt;br&gt;&lt;a id=&quot;more&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;Caffe简介&quot;&gt;&lt;a href=&quot;#Caffe简介&quot; class=&quot;headerlink&quot; title=&quot;Caffe简介&quot;&gt;&lt;/a&gt;Caffe简介&lt;/h2&gt;&lt;p&gt;&lt;a href=&quot;http://caffe.berkeleyvision.org/&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;Caffe&lt;/a&gt;作为一个优秀的深度学习框架网上已经有很多内容介绍了，这里就不在多说。作为一个C++新手，断断续续看Caffe源码一个月以来发现越看不懂的东西越多，因此在博客里记录和分享一下学习的过程。其中我把自己看源码的一些注释结合了网上一些同学的注释以及在学习源码过程中查到到的一些资源(包括怎么使用IDE单步调试以及一些Caffe中使用的第三方库的介绍)放在github上：&lt;a href=&quot;https://github.com/BUPTLdy/Caffe_Code_Analysis&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;Caffe_Code_Analysis&lt;/a&gt;，感兴趣的同学可以看一看，希望能对你有帮助。&lt;/p&gt;
&lt;p&gt;一般在介绍Caffe代码结构的时候，大家都会说Caffe主要由&lt;code&gt;Blob&lt;/code&gt; &lt;code&gt;Layer&lt;/code&gt; &lt;code&gt;Net&lt;/code&gt; 和 &lt;code&gt;Solver&lt;/code&gt;这几个部分组成。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Blob 主要用来表示网络中的数据，包括训练数据，网络各层自身的参数(包括权值、偏置以及它们的梯度)，网络之间传递的数据都是通过 Blob 来实现的，同时 Blob 数据也支持在 CPU 与 GPU 上存储，能够在两者之间做同步。&lt;/li&gt;
&lt;li&gt;Layer 是对神经网络中各种层的一个抽象，包括我们熟知的卷积层和下采样层，还有全连接层和各种激活函数层等等。同时每种 Layer 都实现了前向传播和反向传播，并通过 Blob 来传递数据。&lt;/li&gt;
&lt;li&gt;Net 是对整个网络的表示，由各种 Layer 前后连接组合而成，也是我们所构建的网络模型。&lt;/li&gt;
&lt;li&gt;Solver 定义了针对 Net 网络模型的求解方法，记录网络的训练过程，保存网络模型参数，中断并恢复网络的训练过程。自定义 Solver 能够实现不同的网络求解方式。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;不过在刚开始准备阅读Caffe代码的时候，就算知道了代码是由上面四部分组成还是感觉会无从下手，下面我们准备通过一个&lt;a href=&quot;http://caffe.berkeleyvision.org/gathered/examples/mnist.html&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;Caffe训练LeNet&lt;/a&gt;的实例并结合代码来解释Caffe是如何初始化网络，然后正向传播、反向传播开始训练，最终得到训练好的模型这一过程。&lt;/p&gt;
&lt;h2 id=&quot;训练LeNet&quot;&gt;&lt;a href=&quot;#训练LeNet&quot; class=&quot;headerlink&quot; title=&quot;训练LeNet&quot;&gt;&lt;/a&gt;训练LeNet&lt;/h2&gt;&lt;p&gt;在Caffe提供的例子里，训练LeNet网络的命令为：&lt;br&gt;&lt;figure class=&quot;highlight plain&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;cd $CAFFE_ROOT&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;./build/tools/caffe train --solver=examples/mnist/lenet_solver.prototxt&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;其中第一个参数&lt;code&gt;build/tools/caffe&lt;/code&gt;是Caffe框架的主要框架，由&lt;a href=&quot;https://github.com/BVLC/caffe/blob/master/tools/caffe.cpp&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;&lt;code&gt;tools/caffe.cpp&lt;/code&gt;&lt;/a&gt;文件编译而来，第二个参数&lt;code&gt;train&lt;/code&gt;表示是要训练网络，第三个参数是 &lt;a href=&quot;https://github.com/BVLC/caffe/blob/master/examples/mnist/lenet_solver.prototxt&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;solver的protobuf描述文件&lt;/a&gt;。在Caffe中，网络模型的描述及其求解都是通过 &lt;a href=&quot;https://developers.google.com/protocol-buffers/&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;protobuf&lt;/a&gt; 定义的，并不需要通过敲代码来实现。同时，模型的参数也是通过 protobuf 实现加载和存储，包括 CPU 与 GPU 之间的无缝切换，都是通过配置来实现的，不需要通过硬编码的方式实现，有关&lt;br&gt;protobuf的具体内容可参考这篇博文：&lt;a href=&quot;http://alanse7en.github.io/caffedai-ma-jie-xi-2/&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;http://alanse7en.github.io/caffedai-ma-jie-xi-2/&lt;/a&gt;。&lt;/p&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;code&gt;caffe.cpp&lt;/code&gt;的main函数入口开始观察Caffe是怎么一步一步训练网络的。在&lt;code&gt;caffe.cpp&lt;/code&gt;中main函数之外通过&lt;code&gt;RegisterBrewFunction&lt;/code&gt;这个宏在每一个实现主要功能的函数之后将这个函数的名字和其对应的函数指针添加到了&lt;code&gt;g_brew_map&lt;/code&gt;中,具体分别为train()，test()，device_query()，time()这四个函数。&lt;/p&gt;
&lt;p&gt;在运行的时候,根据传入的参数在main函数中，通过GetBrewFunction得到了我们需要调用的那个函数的函数指针，并完成了调用。&lt;br&gt;&lt;figure class=&quot;highlight c++&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;// caffe.cpp&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; GetBrewFunction(caffe::&lt;span class=&quot;built_in&quot;&gt;string&lt;/span&gt;(argv[&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;])) ();&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;在我们上面所说的训练LeNet的例子中，传入的第二个参数为&lt;code&gt;train&lt;/code&gt;，所以调用的函数为&lt;code&gt;caffe.cpp&lt;/code&gt;中的&lt;code&gt;int train()&lt;/code&gt;函数，接下来主要看这个函数的内容。在&lt;code&gt;train&lt;/code&gt;函数中有下面两行代码，下面的代码定义了一个指向Solver&lt;float&gt;的shared_ptr。其中主要是通过调用SolverRegistry这个类的静态成员函数CreateSolver得到一个指向Solver的指针来构造shared_ptr类型的solver。而且由于C++多态的特性，尽管solver是一个指向基类Solver类型的指针，通过solver这个智能指针来调用各个成员函数会调用到各个子类(SGDSolver等)的函数。&lt;br&gt;&lt;figure class=&quot;highlight c++&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;// caffe.cpp&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;// 其中输入参数solver_param就是上面所说的第三个参数：网络的模型及求解文件&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;built_in&quot;&gt;shared_ptr&lt;/span&gt;&amp;lt;caffe::Solver&amp;lt;&lt;span class=&quot;keyword&quot;&gt;float&lt;/span&gt;&amp;gt; &amp;gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    solver(caffe::SolverRegistry&amp;lt;&lt;span class=&quot;keyword&quot;&gt;float&lt;/span&gt;&amp;gt;::CreateSolver(solver_param);&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/float&gt;&lt;/p&gt;
&lt;p&gt;因为在&lt;code&gt;caffe.proto&lt;/code&gt;文件中默认的优化&lt;code&gt;type&lt;/code&gt;为&lt;code&gt;SGD&lt;/code&gt;,所以上面的代码会实例化一个&lt;code&gt;SGDSolver&lt;/code&gt;的对象，’SGDSolver’类继承于&lt;code&gt;Solver&lt;/code&gt;类，在新建&lt;code&gt;SGDSolver&lt;/code&gt;对象时会调用其构造函数如下所示：&lt;br&gt;&lt;figure class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;//sgd_solvers.hpp&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;explicit SGDSolver(const SolverParameter&amp;amp; param)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    : Solver&amp;lt;Dtype&amp;gt;(param) &amp;#123; PreSolve(); &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;从上面代码可以看出，会先调用父类&lt;code&gt;Solver&lt;/code&gt;的构造函数，如下所示。Solver类的构造函数通过&lt;code&gt;Init(param)&lt;/code&gt;函数来初始化网络。&lt;br&gt;&lt;figure class=&quot;highlight c++&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;//solver.cpp&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;template&lt;/span&gt; &amp;lt;&lt;span class=&quot;keyword&quot;&gt;typename&lt;/span&gt; Dtype&amp;gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;Solver&amp;lt;Dtype&amp;gt;::Solver(&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; SolverParameter&amp;amp; param, &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; Solver* root_solver)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    : net_(), callbacks_(), root_solver_(root_solver),requested_early_exit_(&lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  Init(param);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;而在&lt;code&gt;Init(paran)&lt;/code&gt;函数中，又主要是通过&lt;code&gt;InitTrainNet()&lt;/code&gt;和&lt;code&gt;InitTestNets()&lt;/code&gt;函数分别来搭建训练网络结构和测试网络结构。&lt;/p&gt;
&lt;p&gt;训练网络只能有一个,在&lt;code&gt;InitTrainNet()&lt;/code&gt;函数中首先会设置一些基本参数，包括设置网络的状态为&lt;code&gt;TRAIN&lt;/code&gt;，确定训练网络只有一个等，然会会通过下面这条语句新建了一个&lt;code&gt;Net&lt;/code&gt;对象。&lt;code&gt;InitTestNets()&lt;/code&gt;函数和&lt;code&gt;InitTrainNet()&lt;/code&gt;函数基本类似，不再赘述。&lt;br&gt;&lt;figure class=&quot;highlight c++&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;//solver.cpp&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;net_.reset(&lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; Net&amp;lt;Dtype&amp;gt;(net_param));&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;上面语句新建了&lt;code&gt;Net&lt;/code&gt;对象之后会调用&lt;code&gt;Net&lt;/code&gt;类的构造函数，如下所示。可以看出构造函数是通过&lt;code&gt;Init(param)&lt;/code&gt;函数来初始化网络结构的。&lt;br&gt;&lt;figure class=&quot;highlight c++&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;//net.cpp&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;template&lt;/span&gt; &amp;lt;&lt;span class=&quot;keyword&quot;&gt;typename&lt;/span&gt; Dtype&amp;gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;Net&amp;lt;Dtype&amp;gt;::Net(&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; NetParameter&amp;amp; param, &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; Net* root_net)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    : root_net_(root_net) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  Init(param);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;下面是net.cpp文件里&lt;code&gt;Init()&lt;/code&gt;函数的主要内容(忽略具体细节)，其中&lt;code&gt;LayerRegistry&amp;lt;Dtype&amp;gt;::CreateLayer(layer_param)&lt;/code&gt;主要是通过调用LayerRegistry这个类的静态成员函数CreateLayer得到一个指向Layer类的shared_ptr类型指针。并把每一层的指针存放在&lt;code&gt;vector&amp;lt;shared_ptr&amp;lt;Layer&amp;lt;Dtype&amp;gt; &amp;gt; &amp;gt; layers_&lt;/code&gt;这个指针容器里。这里相当于根据每层的参数&lt;code&gt;layer_param&lt;/code&gt;实例化了对应的各个子类层，比如&lt;code&gt;conv_layer&lt;/code&gt;(卷积层)和&lt;code&gt;pooling_layer&lt;/code&gt;(池化层)。实例化了各层就会调用每个层的构造函数，但每层的构造函数都没有做什么大的设置。&lt;/p&gt;
&lt;p&gt;接下来在Init()函数中主要由四部分组成：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;AppendBottom&lt;/code&gt;：设置每一层的输入数据&lt;/li&gt;
&lt;li&gt;&lt;code&gt;AppendTop&lt;/code&gt;：设置每一层的输出数据&lt;/li&gt;
&lt;li&gt;&lt;code&gt;layers_[layer_id]-&amp;gt;SetUp&lt;/code&gt;：对上面设置的输入输出数据计算分配空间，并设置每层的可学习参数(权值和偏置),下面会详细降到这个函数&lt;/li&gt;
&lt;li&gt;&lt;code&gt;AppendParam&lt;/code&gt;：对上面申请的可学习参数进行设置，主要包括学习率和正则率等。&lt;figure class=&quot;highlight c++&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;//net.cpp Init()&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; layer_id = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;; layer_id &amp;lt; param.layer_size(); ++layer_id) &amp;#123;&lt;span class=&quot;comment&quot;&gt;//param是网络参数，layer_size()返回网络拥有的层数&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; LayerParameter&amp;amp; layer_param = param.layer(layer_id);&lt;span class=&quot;comment&quot;&gt;//获取当前layer的参数&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    layers_.push_back(LayerRegistry&amp;lt;Dtype&amp;gt;::CreateLayer(layer_param));&lt;span class=&quot;comment&quot;&gt;//根据参数实例化layer&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;//下面的两个for循环将此layer的bottom blob的指针和top blob的指针放入bottom_vecs_和top_vecs_,bottom blob和top blob的实例全都存放在blobs_中。相邻的两层，前一层的top blob是后一层的bottom blob，所以blobs_的同一个blob既可能是bottom blob，也可能使top blob。&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; bottom_id = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;; bottom_id &amp;lt; layer_param.bottom_size();++bottom_id) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;       &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; blob_id=AppendBottom(param,layer_id,bottom_id,&amp;amp;available_blobs,&amp;amp;blob_name_to_idx);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; top_id = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;; top_id &amp;lt; num_top; ++top_id) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;       AppendTop(param, layer_id, top_id, &amp;amp;available_blobs, &amp;amp;blob_name_to_idx);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;// 调用layer类的Setup函数进行初始化，输入参数：每个layer的输入blobs以及输出blobs,为每个blob设置大小&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;layers_[layer_id]-&amp;gt;SetUp(bottom_vecs_[layer_id], top_vecs_[layer_id]);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;//接下来的工作是将每层的parameter的指针塞进params_，尤其是learnable_params_。&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;   &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; num_param_blobs = layers_[layer_id]-&amp;gt;blobs().size();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;   &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; param_id = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;; param_id &amp;lt; num_param_blobs; ++param_id) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;       AppendParam(param, layer_id, param_id);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;       &lt;span class=&quot;comment&quot;&gt;//AppendParam负责具体的dirtywork&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;经过上面的过程，&lt;code&gt;Net&lt;/code&gt;类的初始化工作基本就完成了，接着我们具体来看看上面所说的&lt;code&gt;layers_[layer_id]-&amp;gt;SetUp&lt;/code&gt;对每一具体的层结构进行设置，我们来看看&lt;code&gt;Layer&lt;/code&gt;类的&lt;code&gt;Setup()&lt;/code&gt;函数，对每一层的设置主要由下面三个函数组成：&lt;br&gt;&lt;code&gt;LayerSetUp(bottom, top)&lt;/code&gt;：由Layer类派生出的特定类都需要重写这个函数，主要功能是设置权值参数(包括偏置)的空间以及对权值参数经行随机初始化。&lt;br&gt;&lt;code&gt;Reshape(bottom, top)&lt;/code&gt;：根据输出blob和权值参数计算输出blob的维数，并申请空间。&lt;/p&gt;
&lt;figure class=&quot;highlight plain&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;//layer.hpp&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;// layer 初始化设置&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;void SetUp(const vector&amp;lt;Blob&amp;lt;Dtype&amp;gt;*&amp;gt;&amp;amp; bottom,   &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    const vector&amp;lt;Blob&amp;lt;Dtype&amp;gt;*&amp;gt;&amp;amp; top) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  InitMutex();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  CheckBlobCounts(bottom, top);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  LayerSetUp(bottom, top);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  Reshape(bottom, top);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  SetLossWeights(top);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;经过上述过程基本上就完成了初始化的工作，总体的流程大概就是新建一个&lt;code&gt;Solver&lt;/code&gt;对象，然后调用&lt;code&gt;Solver&lt;/code&gt;类的构造函数，然后在&lt;code&gt;Solver&lt;/code&gt;的构造函数中又会新建&lt;code&gt;Net&lt;/code&gt;类实例，在&lt;code&gt;Net&lt;/code&gt;类的构造函数中又会新建各个&lt;code&gt;Layer&lt;/code&gt;的实例,一直具体到设置每个&lt;code&gt;Blob&lt;/code&gt;,大概就介绍完了网络初始化的工作，当然里面还有很多具体的细节，但大概的流程就是这样。&lt;/p&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;code&gt;solver&lt;/code&gt;指针开始一步一步的调用&lt;code&gt;Solver&lt;/code&gt;，&lt;code&gt;Net&lt;/code&gt;,&lt;code&gt;Layer&lt;/code&gt;,&lt;code&gt;Blob&lt;/code&gt;类的构造函数，完成整个网络的初始化。&lt;br&gt;&lt;figure class=&quot;highlight plain&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;//caffe.cpp&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;shared_ptr&amp;lt;caffe::Solver&amp;lt;float&amp;gt; &amp;gt; //初始化&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     solver(caffe::SolverRegistry&amp;lt;float&amp;gt;::CreateSolver(solver_param));&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;完成初始化之后，就可以开始对网络经行训练了，开始训练的代码如下所示，指向&lt;code&gt;Solver&lt;/code&gt;类的指针&lt;code&gt;solver&lt;/code&gt;开始调用&lt;code&gt;Solver&lt;/code&gt;类的成员函数&lt;code&gt;Solve()&lt;/code&gt;，名称比较绕啊。&lt;br&gt;&lt;figure class=&quot;highlight c++&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;// 开始优化&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;solver-&amp;gt;Solve();&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;接下来我们来看看&lt;code&gt;Solver&lt;/code&gt;类的成员函数&lt;code&gt;Solve()&lt;/code&gt;,Solve函数其实主要就是调用了&lt;code&gt;Solver&lt;/code&gt;的另一个成员函数&lt;code&gt;Step（）&lt;/code&gt;来完成实际的迭代训练过程。&lt;br&gt;&lt;figure class=&quot;highlight plain&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;//solver.cpp&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;template &amp;lt;typename Dtype&amp;gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;void Solver&amp;lt;Dtype&amp;gt;::Solve(const char* resume_file) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  ...&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  int start_iter = iter_;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  ...&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  // 然后调用了&amp;apos;Step&amp;apos;函数，这个函数执行了实际的逐步的迭代过程&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  Step(param_.max_iter() - iter_);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  ...&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  LOG(INFO) &amp;lt;&amp;lt; &amp;quot;Optimization Done.&amp;quot;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;顺着来看看这个&lt;code&gt;Step()&lt;/code&gt;函数的主要代码,首先是一个大循环设置了总的迭代次数，在每次迭代中训练&lt;code&gt;iter_size&lt;/code&gt; x &lt;code&gt;batch_size&lt;/code&gt;个样本，这个设置是为了在GPU的显存不够的时候使用，比如我本来想把batch_size设置为128，iter_size是默认为1的，但是会out_of_memory，借助这个方法，可以设置batch_size=32，iter_size=4，那实际上每次迭代还是处理了128个数据。&lt;/p&gt;
&lt;figure class=&quot;highlight plain&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;//solver.cpp&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;template &amp;lt;typename Dtype&amp;gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;void Solver&amp;lt;Dtype&amp;gt;::Step(int iters) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  ...&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  //迭代&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  while (iter_ &amp;lt; stop_iter) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ...&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // iter_size也是在solver.prototxt里设置，实际上的batch_size=iter_size*网络定义里的batch_size，&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // 因此每一次迭代的loss是iter_size次迭代的和，再除以iter_size，这个loss是通过调用`Net::ForwardBackward`函数得到的&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // accumulate gradients over `iter_size` x `batch_size` instances&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    for (int i = 0; i &amp;lt; param_.iter_size(); ++i) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    /*&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     * 调用了Net中的代码，主要完成了前向后向的计算，&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     * 前向用于计算模型的最终输出和Loss，后向用于&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     * 计算每一层网络和参数的梯度。&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     */&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      loss += net_-&amp;gt;ForwardBackward();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ...&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    /*&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     * 这个函数主要做Loss的平滑。由于Caffe的训练方式是SGD，我们无法把所有的数据同时&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     * 放入模型进行训练，那么部分数据产生的Loss就可能会和全样本的平均Loss不同，在必要&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     * 时候将Loss和历史过程中更新的Loss求平均就可以减少Loss的震荡问题。&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     */&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    UpdateSmoothedLoss(loss, start_iter, average_loss);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ...&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // 执行梯度的更新，这个函数在基类`Solver`中没有实现，会调用每个子类自己的实现&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    //，后面具体分析`SGDSolver`的实现&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ApplyUpdate();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // 迭代次数加1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ++iter_;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ...&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;上面&lt;code&gt;Step()&lt;/code&gt;函数主要分为三部分：&lt;/p&gt;
&lt;h3 id=&quot;loss-net-gt-ForwardBackward&quot;&gt;&lt;a href=&quot;#loss-net-gt-ForwardBackward&quot; class=&quot;headerlink&quot; title=&quot;loss += net_-&amp;gt;ForwardBackward();&quot;&gt;&lt;/a&gt;&lt;code&gt;loss += net_-&amp;gt;ForwardBackward();&lt;/code&gt;&lt;/h3&gt;&lt;p&gt;这行代码通过&lt;code&gt;Net&lt;/code&gt;类的&lt;code&gt;net_&lt;/code&gt;指针调用其成员函数&lt;code&gt;ForwardBackward()&lt;/code&gt;，其代码如下所示,分别调用了成员函数&lt;code&gt;Forward(&amp;amp;loss)&lt;/code&gt;和成员函数&lt;code&gt;Backward()&lt;/code&gt;来进行前向传播和反向传播。&lt;br&gt;&lt;figure class=&quot;highlight plain&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;// net.hpp&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;// 进行一次正向传播，一次反向传播&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;Dtype ForwardBackward() &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  Dtype loss;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  Forward(&amp;amp;loss);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  Backward();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  return loss;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;前面的&lt;code&gt;Forward(&amp;amp;loss)&lt;/code&gt;函数最终会执行到下面一段代码,&lt;code&gt;Net&lt;/code&gt;类的&lt;code&gt;Forward()&lt;/code&gt;函数会对网络中的每一层执行&lt;code&gt;Layer&lt;/code&gt;类的成员函数&lt;code&gt;Forward()&lt;/code&gt;，而具体的每一层&lt;code&gt;Layer&lt;/code&gt;的派生类会重写&lt;code&gt;Forward()&lt;/code&gt;函数来实现不同层的前向计算功能。上面的&lt;code&gt;Backward()&lt;/code&gt;反向求导函数也和&lt;code&gt;Forward()&lt;/code&gt;类似，调用不同层的&lt;code&gt;Backward()&lt;/code&gt;函数来计算每层的梯度。&lt;br&gt;&lt;figure class=&quot;highlight plain&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;//net.cpp&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;for (int i = start; i &amp;lt;= end; ++i) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;// 对每一层进行前向计算，返回每层的loss，其实只有最后一层loss不为0&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  Dtype layer_loss = layers_[i]-&amp;gt;Forward(bottom_vecs_[i], top_vecs_[i]);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  loss += layer_loss;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  if (debug_info_) &amp;#123; ForwardDebugInfo(i); &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;h3 id=&quot;UpdateSmoothedLoss&quot;&gt;&lt;a href=&quot;#UpdateSmoothedLoss&quot; class=&quot;headerlink&quot; title=&quot;UpdateSmoothedLoss();&quot;&gt;&lt;/a&gt;&lt;code&gt;UpdateSmoothedLoss();&lt;/code&gt;&lt;/h3&gt;&lt;p&gt; 这个函数主要做Loss的平滑。由于Caffe的训练方式是SGD，我们无法把所有的数据同时放入模型进行训练，那么部分数据产生的Loss就可能会和全样本的平均Loss不同，在必要时候将Loss和历史过程中更新的Loss求平均就可以减少Loss的震荡问题&lt;/p&gt;
&lt;h3 id=&quot;ApplyUpdate&quot;&gt;&lt;a href=&quot;#ApplyUpdate&quot; class=&quot;headerlink&quot; title=&quot;ApplyUpdate();&quot;&gt;&lt;/a&gt;&lt;code&gt;ApplyUpdate();&lt;/code&gt;&lt;/h3&gt;&lt;p&gt;这个函数是&lt;code&gt;Solver&lt;/code&gt;类的纯虚函数，需要派生类来实现，比如&lt;code&gt;SGDSolver&lt;/code&gt;类实现的&lt;code&gt;ApplyUpdate();&lt;/code&gt;函数如下，主要内容包括：设置参数的学习率；对梯度进行Normalize；对反向求导得到的梯度添加正则项的梯度；最后根据SGD算法计算最终的梯度；最后的最后把计算得到的最终梯度对权值进行更新。&lt;br&gt;&lt;figure class=&quot;highlight plain&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;template &amp;lt;typename Dtype&amp;gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;void SGDSolver&amp;lt;Dtype&amp;gt;::ApplyUpdate() &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  CHECK(Caffe::root_solver());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  // GetLearningRate根据设置的lr_policy来计算当前迭代的learning rate的值&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  Dtype rate = GetLearningRate();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  // 判断是否需要输出当前的learning rate&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  if (this-&amp;gt;param_.display() &amp;amp;&amp;amp; this-&amp;gt;iter_ % this-&amp;gt;param_.display() == 0) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    LOG(INFO) &amp;lt;&amp;lt; &amp;quot;Iteration &amp;quot; &amp;lt;&amp;lt; this-&amp;gt;iter_ &amp;lt;&amp;lt; &amp;quot;, lr = &amp;quot; &amp;lt;&amp;lt; rate;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  // 避免梯度爆炸，如果梯度的二范数超过了某个数值则进行scale操作，将梯度减小&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  ClipGradients();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  // 对所有可更新的网络参数进行操作&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  for (int param_id = 0; param_id &amp;lt; this-&amp;gt;net_-&amp;gt;learnable_params().size();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;       ++param_id) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;	// 将第param_id个参数的梯度除以iter_size，&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;	// 这一步的作用是保证实际的batch_size=iter_size*设置的batch_size&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    Normalize(param_id);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // 将正则化部分的梯度降入到每个参数的梯度中&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    Regularize(param_id);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    // 计算SGD算法的梯度(momentum等)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ComputeUpdateValue(param_id, rate);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  // 调用`Net::Update`更新所有的参数&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  this-&amp;gt;net_-&amp;gt;Update();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;等进行了所有的循环，网络的训练也算是完成了。上面大概说了下使用Caffe进行网络训练时网络初始化以及前向传播、反向传播、梯度更新的过程，其中省略了大量的细节。上面还有很多东西都没提到，比如说Caffe中&lt;code&gt;Layer&lt;/code&gt;派生类的注册及各个具体层前向反向的实现、&lt;code&gt;Solver&lt;/code&gt;派生类的注册、网络结构的读取、模型的保存等等大量内容。&lt;/p&gt;
</content>
    
    <summary type="html">
    
      &lt;p&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-10-9/83591184.jpg&quot; alt=&quot;&quot;&gt;&lt;br&gt;
    
    </summary>
    
    
      <category term="Deep Learning" scheme="http://buptldy.github.io/tags/Deep-Learning/"/>
    
      <category term="Caffe" scheme="http://buptldy.github.io/tags/Caffe/"/>
    
      <category term="C++" scheme="http://buptldy.github.io/tags/C/"/>
    
  </entry>
  
  <entry>
    <title>Implementing convolution as a matrix multiplication</title>
    <link href="http://buptldy.github.io/2016/10/01/2016-10-01-im2col/"/>
    <id>http://buptldy.github.io/2016/10/01/2016-10-01-im2col/</id>
    <published>2016-10-01T02:00:00.000Z</published>
    <updated>2016-10-01T11:57:07.112Z</updated>
    
    <content type="html">&lt;center&gt;&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-10-1/61814949.jpg&quot; alt=&quot;&quot;&gt;&lt;br&gt;&lt;/center&gt;

&lt;a id=&quot;more&quot;&gt;&lt;/a&gt;
&lt;h2 id=&quot;CNN中的卷积操作&quot;&gt;&lt;a href=&quot;#CNN中的卷积操作&quot; class=&quot;headerlink&quot; title=&quot;CNN中的卷积操作&quot;&gt;&lt;/a&gt;CNN中的卷积操作&lt;/h2&gt;&lt;p&gt;卷积层是CNNs网络中可以说是最重要的层了，卷积层的主要作用是对输入图像求卷积运算。如下图所示，输入图片的维数为$[c_0,h_0,w_0]$ ；卷积核的维数为$[c_1,c_0,h_k,w_k]$，其中$c_0$在图中没有表示出来，一个卷积核可以看成由$c_1$个维数为$[c_0,h_k,w_k]$的三维滤波器组成；除了这些参数通常在计算卷积运算的时候还有一些超参数比如：stride（步长）：$S$,padding（填充）：$P$。&lt;/p&gt;
&lt;p&gt;根据上面所说的参数就可以求出输出特征的维数为$[c_1,h_1,w_1]$,其中$h_1 = (h_0-h_k+2P)/S+1$,$w_1 = (w_0-w_k+2P)/S+1$。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-10-1/28468053.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;卷积的计算过程其实很简单，但不是很容易说清楚，下面通过代码来说明。&lt;/p&gt;
&lt;p&gt;基本环境设置:&lt;/p&gt;
&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;%load_ext cython  &lt;span class=&quot;comment&quot;&gt;#代码运行在jupyter-notebook中&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;import&lt;/span&gt; matplotlib.pyplot &lt;span class=&quot;keyword&quot;&gt;as&lt;/span&gt; plt&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;import&lt;/span&gt; numpy &lt;span class=&quot;keyword&quot;&gt;as&lt;/span&gt; np&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;%matplotlib inline&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;plt.rcParams[&lt;span class=&quot;string&quot;&gt;&#39;figure.figsize&#39;&lt;/span&gt;] = (&lt;span class=&quot;number&quot;&gt;10.0&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;8.0&lt;/span&gt;) &lt;span class=&quot;comment&quot;&gt;# set default size of plots&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;plt.rcParams[&lt;span class=&quot;string&quot;&gt;&#39;image.interpolation&#39;&lt;/span&gt;] = &lt;span class=&quot;string&quot;&gt;&#39;nearest&#39;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;plt.rcParams[&lt;span class=&quot;string&quot;&gt;&#39;image.cmap&#39;&lt;/span&gt;] = &lt;span class=&quot;string&quot;&gt;&#39;gray&#39;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;卷积层计算的代码如下，想象一副图像尺寸为MxM，卷积核mxm。在计算时，卷积核与图像中每个mxm大小的图像块做element-wise相乘，然后得到的结果相加得到一个值，然后再移动一个stride，做同样的运算，直到整副输入图像遍历完，上述过程得到的值就组成了输出特征，具体运算过程还是看代码。&lt;/p&gt;
&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;conv_forward_naive&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(x, w, b, conv_param)&lt;/span&gt;:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  out = &lt;span class=&quot;keyword&quot;&gt;None&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  stride = conv_param[&lt;span class=&quot;string&quot;&gt;&#39;stride&#39;&lt;/span&gt;]&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  pad = conv_param[&lt;span class=&quot;string&quot;&gt;&#39;pad&#39;&lt;/span&gt;]&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  N, C, W, H = x.shape&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  F, C, HH, WW = w.shape&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  H_out = &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt; + (H + &lt;span class=&quot;number&quot;&gt;2&lt;/span&gt; * pad - HH) / stride&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  W_out = &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt; + (W + &lt;span class=&quot;number&quot;&gt;2&lt;/span&gt; * pad - WW) / stride&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  npad = ((&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;,&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;), (&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;,&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;), (pad,pad), (pad,pad))&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  x_pad = np.pad(x, pad_width=npad, mode=&lt;span class=&quot;string&quot;&gt;&#39;constant&#39;&lt;/span&gt;, constant_values=&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  out = np.zeros((N, F, H_out, W_out))&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; i &lt;span class=&quot;keyword&quot;&gt;in&lt;/span&gt; xrange(N):&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; j &lt;span class=&quot;keyword&quot;&gt;in&lt;/span&gt; xrange(F):&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;          &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; k &lt;span class=&quot;keyword&quot;&gt;in&lt;/span&gt; xrange(H_out):&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;              &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; z &lt;span class=&quot;keyword&quot;&gt;in&lt;/span&gt; xrange(W_out):&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                  out[i, j, k, z] = np.sum(x_pad[i, :, k*stride:k*stride+HH,  z*stride:z*stride+WW]*w[j, :, :, :])+b[j]            &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  cache = (x, w, b, conv_param)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; out, cache&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;下面来检测下上面的卷积计算代码，我们人为的设置两个卷积核（分别为求灰度特征，和边缘特征），然后对两幅输入图像求卷积，观察输出的结果：&lt;/p&gt;
&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;47&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;48&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;49&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;50&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;51&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;52&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;53&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;54&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;55&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;56&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;57&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;from&lt;/span&gt; scipy.misc &lt;span class=&quot;keyword&quot;&gt;import&lt;/span&gt; imread, imresize&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;kitten, puppy = imread(&lt;span class=&quot;string&quot;&gt;&#39;kitten.jpg&#39;&lt;/span&gt;), imread(&lt;span class=&quot;string&quot;&gt;&#39;puppy.jpg&#39;&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;d = kitten.shape[&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;] - kitten.shape[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;]&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;kitten_cropped = kitten[:, d/&lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;:-d/&lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;, :]&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;img_size = &lt;span class=&quot;number&quot;&gt;200&lt;/span&gt;   &lt;span class=&quot;comment&quot;&gt;# Make this smaller if it runs too slow&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;x = np.zeros((&lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;3&lt;/span&gt;, img_size, img_size))&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;x[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;, :, :, :] = imresize(puppy, (img_size, img_size)).transpose((&lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;))&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;x[&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;, :, :, :] = imresize(kitten_cropped, (img_size, img_size)).transpose((&lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;))&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;# Set up a convolutional weights holding 2 filters, each 3x3&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;w = np.zeros((&lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;3&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;3&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;3&lt;/span&gt;))&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;# The first filter converts the image to grayscale.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;# Set up the red, green, and blue channels of the filter.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;w[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;, :, :] = [[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;], [&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;0.3&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;], [&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;]]&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;w[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;, :, :] = [[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;], [&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;0.6&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;], [&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;]]&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;w[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;, :, :] = [[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;], [&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;0.1&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;], [&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;]]&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;# Second filter detects horizontal edges in the blue channel.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;w[&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;, :, :] = [[&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;], [&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;], [&lt;span class=&quot;number&quot;&gt;-1&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;-2&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;-1&lt;/span&gt;]]&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;# Vector of biases. We don&#39;t need any bias for the grayscale&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;# filter, but for the edge detection filter we want to add 128&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;# to each output so that nothing is negative.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;b = np.array([&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;128&lt;/span&gt;])&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;# Compute the result of convolving each input in x with each filter in w,&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;# offsetting by b, and storing the results in out.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;out, _ = conv_forward_naive(x, w, b, &amp;#123;&lt;span class=&quot;string&quot;&gt;&#39;stride&#39;&lt;/span&gt;: &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;string&quot;&gt;&#39;pad&#39;&lt;/span&gt;: &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;&amp;#125;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;imshow_noax&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(img, normalize=True)&lt;/span&gt;:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;string&quot;&gt;&quot;&quot;&quot; Tiny helper to show images as uint8 and remove axis labels &quot;&quot;&quot;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; normalize:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        img_max, img_min = np.max(img), np.min(img)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        img = &lt;span class=&quot;number&quot;&gt;255.0&lt;/span&gt; * (img - img_min) / (img_max - img_min)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    plt.imshow(img.astype(&lt;span class=&quot;string&quot;&gt;&#39;uint8&#39;&lt;/span&gt;))&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    plt.gca().axis(&lt;span class=&quot;string&quot;&gt;&#39;off&#39;&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;# Show the original images and the results of the conv operation&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;plt.subplot(&lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;3&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;imshow_noax(puppy, normalize=&lt;span class=&quot;keyword&quot;&gt;False&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;plt.title(&lt;span class=&quot;string&quot;&gt;&#39;Original image&#39;&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;plt.subplot(&lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;3&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;imshow_noax(out[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;])&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;plt.title(&lt;span class=&quot;string&quot;&gt;&#39;Grayscale&#39;&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;plt.subplot(&lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;3&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;3&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;imshow_noax(out[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;])&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;plt.title(&lt;span class=&quot;string&quot;&gt;&#39;Edges&#39;&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;plt.subplot(&lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;3&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;4&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;imshow_noax(kitten_cropped, normalize=&lt;span class=&quot;keyword&quot;&gt;False&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;plt.subplot(&lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;3&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;5&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;imshow_noax(out[&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;])&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;plt.subplot(&lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;3&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;6&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;imshow_noax(out[&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;])&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;plt.show()&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;图像经过卷积后，输入结果如下所示：&lt;/p&gt;
&lt;center&gt;:&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-10-1/81198578.jpg&quot; alt=&quot;&quot;&gt;&lt;br&gt;&lt;/center&gt;

&lt;h2 id=&quot;im2col&quot;&gt;&lt;a href=&quot;#im2col&quot; class=&quot;headerlink&quot; title=&quot;im2col&quot;&gt;&lt;/a&gt;im2col&lt;/h2&gt;&lt;p&gt;运行上面代码的时候，我们发现对这两张图片计算卷积还是比较慢的，而在CNN中是存在大量的卷积运算的，所以我们需要一个更加快速的计算卷积的方法。如下图所示为Caffe中计算卷积的示意图，通过上面普通卷积运算的实现我们可以发现，卷积操作实际上是在对输入特征的一定范围内和卷积核滤波器做点乘，如下图我们可以利用这一特性把卷积操作转换成两个大矩阵相乘。&lt;/p&gt;
&lt;p&gt;把输入图像要经行卷积操作的这一区域展成列向量的操作通常称为&lt;code&gt;im2col&lt;/code&gt;，具体过程如下图所示。&lt;/p&gt;
&lt;center&gt;&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-10-1/72204285.jpg&quot; alt=&quot;&quot;&gt;&lt;br&gt;&lt;/center&gt;

&lt;p&gt;下图为一个具体的例子，看懂下面这个图应该就会清楚上面的做法。&lt;/p&gt;
&lt;center&gt;&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-10-1/690672.jpg&quot; alt=&quot;&quot;&gt;&lt;br&gt;&lt;/center&gt;

&lt;p&gt;下面的&lt;code&gt;im2col_cython&lt;/code&gt;是使用Cython代码来实现&lt;code&gt;im2col&lt;/code&gt;功能，有关Cython在Python中的具体使用可参考：&lt;a href=&quot;http://buptldy.github.io/2016/06/15/2016-06-15-Python%E9%80%9F%E5%BA%A6%E4%BC%98%E5%8C%96-Cython%E4%B8%ADnumpy%E4%BB%A5%E5%8F%8A%E5%A4%9A%E7%BA%BF%E7%A8%8B%E7%9A%84%E4%BD%BF%E7%94%A8/&quot;&gt;Python速度优化-Cython中numpy以及多线程的使用&lt;/a&gt;。&lt;/p&gt;
&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;%%cython&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;import&lt;/span&gt; cython&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;cimport numpy &lt;span class=&quot;keyword&quot;&gt;as&lt;/span&gt; np&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;import&lt;/span&gt; numpy &lt;span class=&quot;keyword&quot;&gt;as&lt;/span&gt; np&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;ctypedef fused DTYPE_t:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    np.float32_t&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    np.float64_t&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;im2col_cython&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(np.ndarray[DTYPE_t, ndim=&lt;span class=&quot;number&quot;&gt;4&lt;/span&gt;] x, int field_height,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                  int field_width, int padding, int stride)&lt;/span&gt;:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    cdef int N = x.shape[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;]&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    cdef int C = x.shape[&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;]&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    cdef int H = x.shape[&lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;]&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    cdef int W = x.shape[&lt;span class=&quot;number&quot;&gt;3&lt;/span&gt;]&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    cdef int HH = (H + &lt;span class=&quot;number&quot;&gt;2&lt;/span&gt; * padding - field_height) / stride + &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    cdef int WW = (W + &lt;span class=&quot;number&quot;&gt;2&lt;/span&gt; * padding - field_width) / stride + &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    cdef int p = padding&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    cdef np.ndarray[DTYPE_t, ndim=&lt;span class=&quot;number&quot;&gt;4&lt;/span&gt;] x_padded = np.pad(x,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            ((&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;), (&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;), (p, p), (p, p)), mode=&lt;span class=&quot;string&quot;&gt;&#39;constant&#39;&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    cdef np.ndarray[DTYPE_t, ndim=&lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;] cols = np.zeros(&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            (C * field_height * field_width, N * HH * WW),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            dtype=x.dtype)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;# Moving the inner loop to a C function with no bounds checking works, but does&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;# not seem to help performance in any measurable way.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    cdef int c, ii, jj, row, yy, xx, i, col&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; c &lt;span class=&quot;keyword&quot;&gt;in&lt;/span&gt; range(C):&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; yy &lt;span class=&quot;keyword&quot;&gt;in&lt;/span&gt; range(HH):&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; xx &lt;span class=&quot;keyword&quot;&gt;in&lt;/span&gt; range(WW):&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; ii &lt;span class=&quot;keyword&quot;&gt;in&lt;/span&gt; range(field_height):&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; jj &lt;span class=&quot;keyword&quot;&gt;in&lt;/span&gt; range(field_width):&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        row = c * field_width * field_height + ii * field_height + jj&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; i &lt;span class=&quot;keyword&quot;&gt;in&lt;/span&gt; range(N):&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                            col = yy * WW * N + xx * N + i&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                            cols[row, col] = x_padded[i, c, stride * yy + ii, stride * xx + jj]&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; cols&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;调用上面的&lt;code&gt;im2col_cython&lt;/code&gt;函数来实现卷积操作：&lt;br&gt;&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;conv_forward_im2col&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(x, w, b, conv_param)&lt;/span&gt;:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;string&quot;&gt;&quot;&quot;&quot;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  A fast implementation of the forward pass for a convolutional layer&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  based on im2col and col2im.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &quot;&quot;&quot;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  N, C, H, W = x.shape&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  num_filters, _, filter_height, filter_width = w.shape&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  stride, pad = conv_param[&lt;span class=&quot;string&quot;&gt;&#39;stride&#39;&lt;/span&gt;], conv_param[&lt;span class=&quot;string&quot;&gt;&#39;pad&#39;&lt;/span&gt;]&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;comment&quot;&gt;# Check dimensions&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;keyword&quot;&gt;assert&lt;/span&gt; (W + &lt;span class=&quot;number&quot;&gt;2&lt;/span&gt; * pad - filter_width) % stride == &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;string&quot;&gt;&#39;width does not work&#39;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;keyword&quot;&gt;assert&lt;/span&gt; (H + &lt;span class=&quot;number&quot;&gt;2&lt;/span&gt; * pad - filter_height) % stride == &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;string&quot;&gt;&#39;height does not work&#39;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;comment&quot;&gt;# Create output&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  out_height = (H + &lt;span class=&quot;number&quot;&gt;2&lt;/span&gt; * pad - filter_height) / stride + &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  out_width = (W + &lt;span class=&quot;number&quot;&gt;2&lt;/span&gt; * pad - filter_width) / stride + &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  out = np.zeros((N, num_filters, out_height, out_width), dtype=x.dtype)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;comment&quot;&gt;# x_cols = im2col_indices(x, w.shape[2], w.shape[3], pad, stride)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  x_cols = im2col_cython(x, w.shape[&lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;], w.shape[&lt;span class=&quot;number&quot;&gt;3&lt;/span&gt;], pad, stride)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  res = w.reshape((w.shape[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;], &lt;span class=&quot;number&quot;&gt;-1&lt;/span&gt;)).dot(x_cols) + b.reshape(&lt;span class=&quot;number&quot;&gt;-1&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  out = res.reshape(w.shape[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;], out.shape[&lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;], out.shape[&lt;span class=&quot;number&quot;&gt;3&lt;/span&gt;], x.shape[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;])&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  out = out.transpose(&lt;span class=&quot;number&quot;&gt;3&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  cache = (x, w, b, conv_param, x_cols)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; out, cache&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;测试使用&lt;code&gt;im2col&lt;/code&gt;方法的卷积操作，从输出的图片可以看出和原始卷积方法一样。&lt;/p&gt;
&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;out, _ = conv_forward_im2col(x, w, b, &amp;#123;&lt;span class=&quot;string&quot;&gt;&#39;stride&#39;&lt;/span&gt;: &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;string&quot;&gt;&#39;pad&#39;&lt;/span&gt;: &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;&amp;#125;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;# Show the original images and the results of the conv operation&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;plt.subplot(&lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;3&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;imshow_noax(puppy, normalize=&lt;span class=&quot;keyword&quot;&gt;False&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;plt.title(&lt;span class=&quot;string&quot;&gt;&#39;Original image&#39;&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;plt.subplot(&lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;3&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;imshow_noax(out[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;])&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;plt.title(&lt;span class=&quot;string&quot;&gt;&#39;Grayscale&#39;&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;plt.subplot(&lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;3&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;3&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;imshow_noax(out[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;])&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;plt.title(&lt;span class=&quot;string&quot;&gt;&#39;Edges&#39;&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;plt.subplot(&lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;3&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;4&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;imshow_noax(kitten_cropped, normalize=&lt;span class=&quot;keyword&quot;&gt;False&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;plt.subplot(&lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;3&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;5&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;imshow_noax(out[&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;])&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;plt.subplot(&lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;3&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;6&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;imshow_noax(out[&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;])&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;plt.show()&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;center&gt;&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-10-1/81198578.jpg&quot; alt=&quot;&quot;&gt;&lt;br&gt;&lt;/center&gt;

&lt;p&gt;下面来测试一下使用两种方法的时间，使用原始的卷积操作每次循环需要2.19s，而使用&lt;code&gt;im2col&lt;/code&gt;方法则只需要28.3ms，时间大概缩短了77倍，当然这其中也包括了使用Cython所降低的时间，但总体上来说还是大大加快了卷积的计算速度。&lt;/p&gt;
&lt;p&gt;虽然使用&lt;code&gt;im2col&lt;/code&gt;方法加快了计算速度，但也会使用更多的内存，因为把输入图像转换为col的时候，会有很多重复的元素。&lt;/p&gt;
&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;%timeit conv_forward_naive(x, w, b, &amp;#123;&lt;span class=&quot;string&quot;&gt;&#39;stride&#39;&lt;/span&gt;: &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;string&quot;&gt;&#39;pad&#39;&lt;/span&gt;: &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;&amp;#125;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;%timeit conv_forward_im2col(x, w, b, &amp;#123;&lt;span class=&quot;string&quot;&gt;&#39;stride&#39;&lt;/span&gt;: &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;string&quot;&gt;&#39;pad&#39;&lt;/span&gt;: &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;&amp;#125;)&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;figure class=&quot;highlight plain&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1 loop, best of 3: 2.19 s per loop&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10 loops, best of 3: 28.3 ms per loop&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&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;http://cs231n.github.io/convolutional-networks/&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;Convolutional Neural Networks (CNNs / ConvNets)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.colinyan.com/%E6%B7%B1%E5%85%A5%E7%90%86%E8%A7%A3caffe%E6%BA%90%E7%A0%81%EF%BC%88%E5%8D%B7%E7%A7%AF%E5%AE%9E%E7%8E%B0%E8%AF%A6%E7%BB%86%E5%88%86%E6%9E%90%EF%BC%89/&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;深入理解Caffe源码（卷积实现详细分析&lt;/a&gt;&lt;/p&gt;
</content>
    
    <summary type="html">
    
      &lt;center&gt;&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-10-1/61814949.jpg&quot; alt=&quot;&quot;&gt;&lt;br&gt;&lt;/center&gt;
    
    </summary>
    
    
      <category term="Deep Learning" scheme="http://buptldy.github.io/tags/Deep-Learning/"/>
    
      <category term="CNN" scheme="http://buptldy.github.io/tags/CNN/"/>
    
  </entry>
  
  <entry>
    <title>Ways for Visualizing Convolutional Networks</title>
    <link href="http://buptldy.github.io/2016/09/25/2016-09-25-cnn_vis/"/>
    <id>http://buptldy.github.io/2016/09/25/2016-09-25-cnn_vis/</id>
    <published>2016-09-25T02:00:00.000Z</published>
    <updated>2016-09-25T14:53:05.980Z</updated>
    
    <content type="html">&lt;p&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/%E9%80%89%E5%8C%BA_005.jpg&quot; alt=&quot;&quot;&gt;&lt;br&gt;&lt;a id=&quot;more&quot;&gt;&lt;/a&gt;&lt;br&gt;近年来，卷积神经网络（CNN）在海量数据的物体分类、识别取得了巨大的成功，但是我们对CNN为什么能够取得这么好的效果以及其中间层所计算得到的特征的理解却是远远落后与CNN的应用。更多的时候CNN对于我们来说就像个黑盒子，输入数据和便签进行训练，然后就可以拟合出我们想要的结果。&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-9-18/80287570.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;如果不能弄明白CNN为什么能够工作的这么好，构建一个好的CNN模型就只能靠试错。为了对CNN有个直观的了解，近年来有许多工作围绕着CNN可视化来展开。&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-9-18/38360122.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;目前CNN的可视化方法主要分为两种：&lt;/p&gt;
&lt;p&gt;(1) 前向计算可视化&lt;/p&gt;
&lt;p&gt;通过前向计算直接可视化深度卷积网络每层的feature map，然后观察feature map的数值变化。一个训练成功的CNN网络，其feature map的值伴随网络深度的增加，会越来越稀疏。&lt;/p&gt;
&lt;p&gt;(2)反向计算可视化&lt;/p&gt;
&lt;p&gt;反向信号向后传播将低维的feature maps 还原到原图像空间，可视化该feature map被原图哪部分特征激活，从而理解该feature map从原图像学习了何种特征。&lt;/p&gt;
&lt;p&gt;本文后面的内容也主要围绕这两方面展开。&lt;/p&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;在介绍一些具体的可视化方法之前，我们先介绍一下我们使用的模型,我们使用的网络是经过CaffeNet微调，用来分类21类光学遥感图像的模型，具体内容可参考&lt;a href=&quot;http://buptldy.github.io/2016/06/12/2016-06-12-CNN%E5%9C%A8%E5%85%89%E5%AD%A6%E9%81%A5%E6%84%9F%E5%9B%BE%E5%83%8F%E4%B8%8A%E7%9A%84%E5%BA%94%E7%94%A8/&quot;&gt;CNN在光学遥感图像上的应用&lt;/a&gt;。&lt;/p&gt;
&lt;p&gt;CaffeNet其实就是AlexNet在Caffe上的实现，为了适应我们具体的分类任务，输出层改为21个节点。&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-5-23/18035393.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;其中要分类的21类光学遥感图像如下图所示：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-5-22/46888988.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&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;h3 id=&quot;特征可视化&quot;&gt;&lt;a href=&quot;#特征可视化&quot; class=&quot;headerlink&quot; title=&quot;特征可视化&quot;&gt;&lt;/a&gt;特征可视化&lt;/h3&gt;&lt;p&gt;通过可视化CNN计算得到的特征通常是大家都能想到的事情，通常第一层能提取到的特征能够和图像对应上，但是到了CNN的更高层，提取到的特征就变的更加抽象，不容易解释。&lt;/p&gt;
&lt;p&gt;如下图所示，Input为输入图像，Filter为CNN第一层卷积层所学&lt;br&gt;习到的参数，可视化后其实就是一个个抽取边缘的滤波器，然后Output为CNN第一层卷积层所提取到的特征，从图中可以看出来输入图像经过CNN第一层卷积层之后得到了边缘特征。&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-9-18/70836148.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;但是CNN高层滤波器对前面输入特征的组合，提取得到的高维特征就不怎么好解释了，如下图所示，顺着箭头方向依次为上述输入图片通过CNN高层卷积层所提取到的特征，可以发现特征随着网络的加深，会越来越抽象、越来越稀疏。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-9-18/23256006.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;t-SNE-visualization&quot;&gt;&lt;a href=&quot;#t-SNE-visualization&quot; class=&quot;headerlink&quot; title=&quot;t-SNE visualization&quot;&gt;&lt;/a&gt;t-SNE visualization&lt;/h3&gt;&lt;p&gt;有时为了体现CNN提取到特征的相关性，我们可以把提取到的特征经行t-SNE降维，然后在二维平面显示出来，如下图所示。从下图可以看出，视觉上看上去相似的图片，在降维后在平面上也很靠近。我们提取的是fc7层的特征（也称为CNN-Code）,t-SNE降维为2维向量显示如下。&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-9-18/89427613.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;遮挡实验&quot;&gt;&lt;a href=&quot;#遮挡实验&quot; class=&quot;headerlink&quot; title=&quot;遮挡实验&quot;&gt;&lt;/a&gt;遮挡实验&lt;/h3&gt;&lt;p&gt;如下图，左边的图为输入图像，注意上边的黑色遮挡区域，我们在输入图像上逐渐移动遮挡区域，然后记录对应输入图像所对应的正确类别的输出概率。很容易理解，当我们遮挡住输入图像的关键区域时，对应的正确输出概率会很低，从下图也可以看出来，当遮挡住飞机的关键部位时，CNN判别为飞机场的概率下降到0.2以下。说明CNN模型确实学习到了物体的关键部分，而不是只依靠一些上下文环境，遮挡实验的代码可参考：&lt;a href=&quot;https://github.com/BUPTLdy/occlusion_experiments&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;occlusion_experiments&lt;/a&gt;。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-9-19/45188603.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&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;前面介绍的几种前向计算可视化的方法都比较好理解，但是还是不能解释CNN深层提取到的特征究竟是什么，究竟对应了输入图像的哪一部分。&lt;/p&gt;
&lt;h3 id=&quot;反向求导可视化&quot;&gt;&lt;a href=&quot;#反向求导可视化&quot; class=&quot;headerlink&quot; title=&quot;反向求导可视化&quot;&gt;&lt;/a&gt;反向求导可视化&lt;/h3&gt;&lt;p&gt;在探讨对图像反向求导可视化之前，我们先看看那一个线性分类器，公式如下：&lt;/p&gt;
&lt;p&gt;$$f(x_i)=Wx_i+b$$&lt;/p&gt;
&lt;p&gt;$W$为线性分类器权值、$x_i$表示一幅输入图像，$b$为偏置。如下图所示，$W$为线性分类器的权值维度为&lt;code&gt;[3×4]&lt;/code&gt;，3表示要分类的数目，4表示为图片的每一个像素值打分;其中$x_i$为一幅图像展成的列向量，维度为&lt;code&gt;[4×1]&lt;/code&gt;;$b$的维度为&lt;code&gt;[3×1]&lt;/code&gt;,所以$Wx_i+b$得到一个&lt;code&gt;[3×1]&lt;/code&gt;的向量表示当前输入图像$x_i$在每个类别上的打分，其中最高分预判为输入图像的类别。通过上述分析&lt;br&gt;可知$W$值决定了图像中的对应像素的重要性，某一类中某个像素越重要，则其对应的权值越大。&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-9-21/40364595.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;对于CNN来说因为有很多层非线性函数，$f(x_i)$为一个高度非线性话的分类器，不过我们可以把它看做一个整体，近似的等于一个线性分类器：&lt;/p&gt;
&lt;p&gt;$$f(x_i) \approx Wx_i+b$$&lt;/p&gt;
&lt;p&gt;然后我们可以对某个输入图片$x_0$上对上式求导，得打权值$W$，也就得到了对应输入图片的重要性大小。&lt;/p&gt;
&lt;p&gt;$$W = \frac{\partial f(x_i)}{\partial I}\vert _{x_0}$$&lt;/p&gt;
&lt;p&gt;产生的图像如下图所示，不是很明显，仔细看能看出飞机的轮廓。&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-9-22/81010256.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;欺骗CNN网络&quot;&gt;&lt;a href=&quot;#欺骗CNN网络&quot; class=&quot;headerlink&quot; title=&quot;欺骗CNN网络&quot;&gt;&lt;/a&gt;欺骗CNN网络&lt;/h3&gt;&lt;p&gt;上面讨论了通过对图片求导来得到对应图片像素的重要性，我们可以利用上面求到的图像导数来欺骗CNN网络，如下图所示坐上图为输入图片类别为&lt;code&gt;airplane&lt;/code&gt;，然后给定一个目标类别&lt;code&gt;denseresidential&lt;/code&gt;,我们通过对输入图像求梯度上升来最大化目标类别的输出，求得的梯度累加到输入图像上，知道CNN判别为目标类别。下图中我们可以看出，上面的两个图人眼看起来都是&lt;code&gt;airplane&lt;/code&gt;类别，差别看起来也不大，但是CNN判别第二张图为&lt;code&gt;denseresidential&lt;/code&gt;类比，从某种意义上说我们欺骗了CNN。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-9-22/31659955.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;Class-Model-Visualisation&quot;&gt;&lt;a href=&quot;#Class-Model-Visualisation&quot; class=&quot;headerlink&quot; title=&quot;Class Model Visualisation&quot;&gt;&lt;/a&gt;Class Model Visualisation&lt;/h3&gt;&lt;p&gt;对于一个训练好的CNN模型，我们可以通过随机产生一张带噪声的图片然后在我们感兴趣的类别上通过梯度上升逐渐优化输入图片可以产生对应类别的图片。&lt;/p&gt;
&lt;p&gt;更一般的, 让$I$ 表示随机产生的噪声图片， $y$ 表示我们感兴趣的类别， $s_y(I)$ 表示CNN 对图片 $I$ 在类别 $y$上的打分。 我们希望能够产生的图片 $I^*$ 使得在类别 $y$ 上打分最高。&lt;/p&gt;
&lt;p&gt;$$&lt;br&gt;I^* = \arg\max_I s_y(I) - R(I)&lt;br&gt;$$&lt;/p&gt;
&lt;p&gt;其中 $R$ 为正则项， 我们可以通过梯度上升法来求解 。&lt;/p&gt;
&lt;p&gt;产生的图片如下所示，可以看出产生的图像对目标的分类又一定的旋转不变形和尺度不变性。&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-9-22/60627433.jpg&quot; alt=&quot;&quot;&gt;&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-9-22/72860217.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;Feature-Inversion&quot;&gt;&lt;a href=&quot;#Feature-Inversion&quot; class=&quot;headerlink&quot; title=&quot;Feature Inversion&quot;&gt;&lt;/a&gt;Feature Inversion&lt;/h3&gt;&lt;p&gt;为了CNN怎么去学习和理解特征，最近也有文章提出通过提取到的特征重建原图像的方法。我们在训练好的CNN模型的基础上，可以通过对图像的求导来实现。具体来说，给定图片&lt;br&gt;$I$, 让$\phi_\ell(I)$ 表示卷积神经$\phi$中 $\ell$ 层所提取到的特征。我们想要求得一张图片$I^*$ 在网络$\phi$中的$\ell$ 层和图片 $I$有相同的特征。&lt;/p&gt;
&lt;p&gt;$$&lt;br&gt;I^* = \arg\min_{I’} |\phi_\ell(I) - \phi_\ell(I’)|_2^2 + R(I’)&lt;br&gt;$$&lt;/p&gt;
&lt;p&gt;其中 $|\cdot|_2^2$ 为欧式距离，$R$ 表示正则项。&lt;/p&gt;
&lt;p&gt;下图展示了从不同层提取的特征重建原图的结果，可以看出层数越深，重建出的结果和原图差异越大，因为CNN在特取特征的过程中，还有一个压缩学习图片最本质特征的作用，所以越往后层，重建得到图片越是代表原图片的本质。&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-9-23/93123483.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;DeepDream&quot;&gt;&lt;a href=&quot;#DeepDream&quot; class=&quot;headerlink&quot; title=&quot;DeepDream&quot;&gt;&lt;/a&gt;DeepDream&lt;/h3&gt;&lt;p&gt;2015年夏天，google发布了一种从神经网络产生图片的新方法，原理其实很简单，就是从神经网络中的某一层提取特征，然后让这一层的反向梯度等于这一层提取到的特征，然后在反向传导回图像，通常会选择在卷积层进行操作，所以可以产生任意分辨率的图像。&lt;/p&gt;
&lt;p&gt;过程如下，我们先对CNN输入一张原图&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-9-23/40419664.jpg&quot; alt=&quot;&quot;&gt;&lt;br&gt;然后选择激活某一层的特征，如果选择的是高层特征，反向传递得到的结果如下，高层特征反向传递得到了一些复杂的模式；&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-9-23/18649599.jpg&quot; alt=&quot;&quot;&gt;&lt;br&gt;如果是低层的特征，则得到的是一些线条，纹理特征。&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-9-23/14566819.jpg&quot; alt=&quot;&quot;&gt;&lt;br&gt;如果我们把上述输出的结果当成输入再次传入，经过一定次数的循环，一些模式会得到增强，输出结果看起来有点惊悚:&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-9-23/11926968.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;反卷积可视化&quot;&gt;&lt;a href=&quot;#反卷积可视化&quot; class=&quot;headerlink&quot; title=&quot;反卷积可视化&quot;&gt;&lt;/a&gt;反卷积可视化&lt;/h3&gt;&lt;p&gt;反卷积顾名思义是和卷积相反的操作，使用反卷积进行特征的可视化，可以理解为把得到的特征映射回原图像的输入空间。反卷积网络如下图所示，其中下图左边为反卷积网络、右边为卷积网络。其中反卷积网络中的反卷积层和卷积网络中卷积层对应，Unpooling层和pooling层对应。卷积网络是输入图像提取特征，而反卷积网络是从特征映射到输入图像。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-9-19/64712899.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;流程如上图所示。&lt;/p&gt;
&lt;h4 id=&quot;正常卷积过程convnet：&quot;&gt;&lt;a href=&quot;#正常卷积过程convnet：&quot; class=&quot;headerlink&quot; title=&quot;正常卷积过程convnet：&quot;&gt;&lt;/a&gt;正常卷积过程convnet：&lt;/h4&gt;&lt;p&gt;如图右侧黑框流程图部分，上一层pooled的特征图，通过本层的filter卷积后，形成本层的卷积特征，然后经过ReLU函数进行非线性变换的到Recitifed特征图，再经过本层的max-pooling操作，完成本层的卷积池化操作；之后传入下一层。本层需要记录在执行max-pooling操作时，每个pooing局域内最大值的位置&lt;/p&gt;
&lt;p&gt;选择激活值：&lt;/p&gt;
&lt;p&gt;为了理解某一个给定的pooling特征激活值，先把特征中其他的激活值设置为0；然后利用deconvnet把这个给定的激活值映射到初始像素层。&lt;/p&gt;
&lt;h4 id=&quot;反卷积过程deconvnet：&quot;&gt;&lt;a href=&quot;#反卷积过程deconvnet：&quot; class=&quot;headerlink&quot; title=&quot;反卷积过程deconvnet：&quot;&gt;&lt;/a&gt;反卷积过程deconvnet：&lt;/h4&gt;&lt;p&gt;Unpooling&lt;/p&gt;
&lt;p&gt;顾名思义就是反pooling过程，由于pooling是不可逆的，所以unpooling只是正常pooling的一种近似；通过记录正常pooling时的位置，把传进来的特征按照记录的方式重新“摆放”，来近似pooling前的卷基层特征。如图中彩色部分&lt;/p&gt;
&lt;p&gt;Filtering&lt;/p&gt;
&lt;p&gt;利用卷积过程filter的转置（实际上就是水平和数值翻转filter）版本来计算卷积前的特征图；从而形成重构的特征。从一个单独的激活值获得的重构图片类似原始图片的一个部分。&lt;/p&gt;
&lt;p&gt;反卷积反池化过程如下所示：&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/%E9%80%89%E5%8C%BA_006.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&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;通过CNN可视化，我们可以看到底层卷积网络学习到的是一些边缘、颜色块等信息；高层网络通过对底层网络抽取到的特征经行组合，学习到了更加复杂以及具有不变性的特征。特征的可视化都是通过对图片方向求导来计算，通过设置不同的优化函数，梯度下降求导来达到可视化的目的。&lt;/p&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://arxiv.org/abs/1412.0035&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;Understanding deep image representations by inverting them.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://arxiv.org/abs/1412.1897&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;Deep neural networks are easily fooled: High confidence predictions for unrecognizable images.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://arxiv.org/abs/1312.6034&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;Deep inside convolutional networks: Visualising image classification models and saliency maps.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://arxiv.org/abs/1506.06579&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;Understanding neural networks through deep visualization.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://arxiv.org/abs/1311.2901&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;Visualizing and understanding convolutional networks.&lt;/a&gt;&lt;/p&gt;
</content>
    
    <summary type="html">
    
      &lt;p&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/%E9%80%89%E5%8C%BA_005.jpg&quot; alt=&quot;&quot;&gt;&lt;br&gt;
    
    </summary>
    
    
      <category term="Deep Learning" scheme="http://buptldy.github.io/tags/Deep-Learning/"/>
    
      <category term="CNN" scheme="http://buptldy.github.io/tags/CNN/"/>
    
  </entry>
  
  <entry>
    <title>Linux Deepin Note</title>
    <link href="http://buptldy.github.io/2016/08/30/2016-08-30-deepin/"/>
    <id>http://buptldy.github.io/2016/08/30/2016-08-30-deepin/</id>
    <published>2016-08-30T02:00:00.000Z</published>
    <updated>2016-10-04T06:18:38.788Z</updated>
    
    <content type="html">&lt;p&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-9-11/90739124.jpg&quot; alt=&quot;&quot;&gt;&lt;br&gt;&lt;a id=&quot;more&quot;&gt;&lt;/a&gt;&lt;/p&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;深度操作系统，是一个Linux发行版，由武汉深之度科技有限公司开发。Deepin系统不仅仅注重系统和桌面环境的开发，同时还注重配套的基础软件开发，目前Deepin系统已经拥有相当多深度特色应用并与许多第三方厂商合作推出热门应用的Linux版本。以上来自维基百科，总的来说Deepin界面很漂亮，对新手也很友好，但就是有点不稳定加上我又爱折腾，所以有时会崩溃，所以进行系统备份还是很有必要的。&lt;/p&gt;
&lt;p&gt;备份系统前我们先了解下Linux文件系统的目录结构，清楚哪些文件夹需要备份，哪些不需要。&lt;/p&gt;
&lt;p&gt;&lt;center&gt;&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-9-11/79598638.jpg&quot; alt=&quot;&quot;&gt;&lt;br&gt;&lt;/center&gt;&lt;/p&gt;
&lt;h3 id=&quot;备份过程&quot;&gt;&lt;a href=&quot;#备份过程&quot; class=&quot;headerlink&quot; title=&quot;备份过程&quot;&gt;&lt;/a&gt;备份过程&lt;/h3&gt;&lt;h4 id=&quot;切换到root&quot;&gt;&lt;a href=&quot;#切换到root&quot; class=&quot;headerlink&quot; title=&quot;切换到root&quot;&gt;&lt;/a&gt;切换到root&lt;/h4&gt;&lt;figure class=&quot;highlight plain&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;sudo su&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;h4 id=&quot;进入根目录&quot;&gt;&lt;a href=&quot;#进入根目录&quot; class=&quot;headerlink&quot; title=&quot;进入根目录&quot;&gt;&lt;/a&gt;进入根目录&lt;/h4&gt;&lt;figure class=&quot;highlight plain&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;cd /&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;h4 id=&quot;执行打包命令&quot;&gt;&lt;a href=&quot;#执行打包命令&quot; class=&quot;headerlink&quot; title=&quot;执行打包命令&quot;&gt;&lt;/a&gt;执行打包命令&lt;/h4&gt;&lt;figure class=&quot;highlight plain&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;tar -cvpzf /media/ldy/6482108A82/backup1.tgz --exclude=/proc --exclude=/lost+found --exclude=/tmp --exclude=/sys --exclude=/media --exclude=/home /&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;命令解释：&lt;/p&gt;
&lt;p&gt;tar：linux常用的打包程序&lt;br&gt;cvpzf：式tar的参数&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;c­创建新文档&lt;/li&gt;
&lt;li&gt;v­处理过程中输出相关信息&lt;/li&gt;
&lt;li&gt;p­表示保持相同的权限&lt;/li&gt;
&lt;li&gt;z­调用gzip来压缩归档文件，与­x联用时调用gzip完成解压缩&lt;/li&gt;
&lt;li&gt;f­对普通文件操作&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;/media/ldy/6482108A82/backup1.tgz：表示打包到你挂载的硬盘里并命名为backup1.tgz&lt;/p&gt;
&lt;p&gt;­­exclude=/proc：排除/proc目录，不打包这个目录，后面也同理，为什么排除参考上面的Linux文件系统的目录结构，为什么排除/home，因为我把/home新分了一区，在重装系统的时候选择不格式化/home分区即可保留数据&lt;/p&gt;
&lt;p&gt;/：表示打包linux根目录所有文件，当然了排除的文件不包含在内&lt;/p&gt;
&lt;h3 id=&quot;恢复过程-还未实践&quot;&gt;&lt;a href=&quot;#恢复过程-还未实践&quot; class=&quot;headerlink&quot; title=&quot;恢复过程(还未实践)&quot;&gt;&lt;/a&gt;恢复过程(还未实践)&lt;/h3&gt;&lt;h4 id=&quot;切换到root-1&quot;&gt;&lt;a href=&quot;#切换到root-1&quot; class=&quot;headerlink&quot; title=&quot;切换到root&quot;&gt;&lt;/a&gt;切换到root&lt;/h4&gt;&lt;figure class=&quot;highlight plain&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;sudo su&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;h4 id=&quot;进入根目录-1&quot;&gt;&lt;a href=&quot;#进入根目录-1&quot; class=&quot;headerlink&quot; title=&quot;进入根目录&quot;&gt;&lt;/a&gt;进入根目录&lt;/h4&gt;&lt;figure class=&quot;highlight plain&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;cd /&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;h4 id=&quot;解压恢复系统&quot;&gt;&lt;a href=&quot;#解压恢复系统&quot; class=&quot;headerlink&quot; title=&quot;解压恢复系统&quot;&gt;&lt;/a&gt;解压恢复系统&lt;/h4&gt;&lt;figure class=&quot;highlight plain&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;tar xvpfz linuxbackup.tgz -C /&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;等执行完后，别急着重启系统，要记得创建刚才在备份时候排除的目录，手动创建，例如上面我们排除，我们需创建&lt;br&gt;&lt;figure class=&quot;highlight plain&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;mkdir proc  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;mdkir lost+found  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;mkdir mnt   &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;mkdir sys  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;mkdir tmp&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;mkdir media&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;h2 id=&quot;fsck命令&quot;&gt;&lt;a href=&quot;#fsck命令&quot; class=&quot;headerlink&quot; title=&quot;fsck命令&quot;&gt;&lt;/a&gt;fsck命令&lt;/h2&gt;&lt;p&gt;前两天由于笔记本突然掉电，导致/home分区损坏，开机出现：&lt;br&gt;&lt;figure class=&quot;highlight plain&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;Cannot open access to console , the root account is locked.&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;h3 id=&quot;解决方法&quot;&gt;&lt;a href=&quot;#解决方法&quot; class=&quot;headerlink&quot; title=&quot;解决方法&quot;&gt;&lt;/a&gt;解决方法&lt;/h3&gt;&lt;p&gt;用deepin安装u盘启动，出现选择安装语言的界面时，按ctrl+alt+F1，进入tty，然后输入startx，进入live cd模式，挂载硬盘的根分区，然后修改/etc/fstab文件，把里面的/home分区里的启动项注释掉，如下所示。mount 命令在开始时会读取这个文件，确定设备和分区的挂载选项，注释掉后开机就不会挂载/home分区。&lt;br&gt;&lt;figure class=&quot;highlight plain&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;# /dev/sda2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;UUID=79813e75-eab0-42e4-b77c-daba9a9b7d01	/         	ext4      	rw,relatime,data=ordered	0 1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;# /dev/sda6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;#UUID=8b23af2a-2fd6-426e-8e63-f791378d8485	/home     	ext4      	rw,relatime,data=ordered	0 2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;# /dev/sda5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;UUID=730d40c7-946a-478e-bde9-9501ba156103	none      	swap      	defaults  	0 0&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;修改后退出liveCD模式进入原系统，因为没有挂载损坏的/home分区，所以能进入系统，但是是不能进入图形界面的，进入文字界面执行下述命令修护损坏的/home分区，其中/dev/sda6为/home分区所在的设备名，设备名可以通过&lt;code&gt;fdisk -l&lt;/code&gt;查看。&lt;br&gt;&lt;figure class=&quot;highlight plain&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;sudo fsck -y /dev/sda6&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;修复成功后，取消/etc/fstab的注释，重启即可。&lt;/p&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;前面已经介绍过/etc/fstab文件，要开机加载其他硬盘修改这个文件就可以。&lt;/p&gt;
&lt;h3 id=&quot;UUID&quot;&gt;&lt;a href=&quot;#UUID&quot; class=&quot;headerlink&quot; title=&quot;UUID&quot;&gt;&lt;/a&gt;UUID&lt;/h3&gt;&lt;p&gt;所有分区和设备都有唯一的 UUID。它们由文件系统生成工具 (mkfs.*) 在创建文件系统时生成。&lt;br&gt;&lt;code&gt;lsblk -f&lt;/code&gt;命令将显示所有设备的 UUID 值。/etc/fstab 中使用 UUID= 前缀:&lt;br&gt;&lt;figure class=&quot;highlight plain&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;/etc/fstab&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;# &amp;lt;file system&amp;gt;                           &amp;lt;dir&amp;gt;         &amp;lt;type&amp;gt;    &amp;lt;options&amp;gt;             &amp;lt;dump&amp;gt; &amp;lt;pass&amp;gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;tmpfs                                     /tmp          tmpfs     nodev,nosuid          0      0&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;UUID=24f28fc6-717e-4bcd-a5f7-32b959024e26 /     ext4              defaults,noatime      0      1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;UUID=03ec5dd3-45c0-4f95-a363-61ff321a09ff /home ext4              defaults,noatime      0      2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;UUID=4209c845-f495-4c43-8a03-5363dd433153 none  swap              defaults              0      0&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;h3 id=&quot;各段含义&quot;&gt;&lt;a href=&quot;#各段含义&quot; class=&quot;headerlink&quot; title=&quot;各段含义&quot;&gt;&lt;/a&gt;各段含义&lt;/h3&gt;&lt;p&gt;&lt;code&gt;&amp;lt;file systems&amp;gt;&lt;/code&gt; ：要挂载的分区或存储设备.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&amp;lt;dir&amp;gt;&lt;/code&gt; ： &lt;code&gt;&amp;lt;file systems&amp;gt;&lt;/code&gt;的挂载位置。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&amp;lt;type&amp;gt;&lt;/code&gt;  要挂载设备或是分区的文件系统类型，支持许多种不同的文件系统：ext2, ext3, ext4, reiserfs, xfs, jfs, smbfs, iso9660, vfat, ntfs, swap 及 auto。 设置成auto类型，mount 命令会猜测使用的文件系统类型，对 CDROM 和 DVD 等移动设备是非常有用的。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&amp;lt;options&amp;gt;&lt;/code&gt; 挂载时使用的参数，使用默认参数&lt;code&gt;defaults&lt;/code&gt;即可。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&amp;lt;dump&amp;gt;&lt;/code&gt;dump 工具通过它决定何时作备份. dump 会检查其内容，并用数字来决定是否对这个文件系统进行备份。 允许的数字是 0 和 1 。0 表示忽略， 1 则进行备份。大部分的用户是没有安装 dump 的 ，对他们而言 &lt;dump&gt; 应设为 0。&lt;/dump&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&amp;lt;pass&amp;gt;&lt;/code&gt; fsck 读取 &lt;pass&gt; 的数值来决定需要检查的文件系统的检查顺序。允许的数字是0, 1, 和2。 根目录应当获得最高的优先权 1, 其它所有需要被检查的设备设置为 2. 0 表示设备不会被 fsck 所检查。&lt;/pass&gt;&lt;/p&gt;
&lt;h3 id=&quot;实例&quot;&gt;&lt;a href=&quot;#实例&quot; class=&quot;headerlink&quot; title=&quot;实例&quot;&gt;&lt;/a&gt;实例&lt;/h3&gt;&lt;p&gt;比如我要开机自动挂载/dev/sdb5这个设备，在/etc/fstab后面加入下面内容即可。&lt;/p&gt;
&lt;figure class=&quot;highlight plain&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;# /dev/sdb5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;UUID=6482108A821062BA           /media/ldy/6482108A82   ntfs     	defaults  	0 0&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
</content>
    
    <summary type="html">
    
      &lt;p&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-9-11/90739124.jpg&quot; alt=&quot;&quot;&gt;&lt;br&gt;
    
    </summary>
    
    
      <category term="Linux" scheme="http://buptldy.github.io/tags/Linux/"/>
    
  </entry>
  
  <entry>
    <title>Implementation of Batch Normalization Layer</title>
    <link href="http://buptldy.github.io/2016/08/18/2016-08-18-Batch_Normalization/"/>
    <id>http://buptldy.github.io/2016/08/18/2016-08-18-Batch_Normalization/</id>
    <published>2016-08-18T02:00:00.000Z</published>
    <updated>2016-10-04T06:14:23.251Z</updated>
    
    <content type="html">&lt;p&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-8-5/21841995.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;a id=&quot;more&quot;&gt;&lt;/a&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;通常在神经网络训练开始前,都要对输入数据做一个归一化处理,那么具体为什么需要归一化呢?归一化后有什么好处呢?原因在于神经网络学习过程本质就是为了学习数据分布,一旦训练数据与测试数据的分布不同,那么网络的泛化能力也大大降低;另外一方面,一旦每批训练数据的分布各不相同(batch 梯度下降),那么网络就要在每次迭代都去学习适应不同的分布,这样将会大大降低网络的训练速度,这也正是为什么我们需要对数据都要做一个归一化预处理的原因。对于深度网络的训练是一个复杂的过程,只要网络的前面几层发生微小的改变,那么后面几层就会被累积放大下去。一旦网络某一层的输入数据的分布发生改变,那么这一层网络就需要去适应学习这个新的数据分布,所以如果训练过程中,训练数据的分布一直在发生变化,那么将会影响网络的训练速度。&lt;/p&gt;
&lt;center&gt;&lt;br&gt;&lt;img src=&quot;http://i2.buimg.com/567571/70c7efd885eb08f3.png&quot; alt=&quot;&quot;&gt;&lt;br&gt;&lt;/center&gt;

&lt;p&gt;举例说明进行数据预处理能够加速训练过程，上图中红点代表2维的数据点，由于图像数据的每一维一般都是0-255之间的数字，因此数据点只会落在第一象限，而且图像数据具有很强的相关性，比如第一个灰度值为30，比较黑，那它旁边的一个像素值一般不会超过100，否则给人的感觉就像噪声一样。由于强相关性，数据点仅会落在第一象限的很小的区域中，形成类似上图所示的狭长分布。&lt;/p&gt;
&lt;p&gt;而神经网络模型在初始化的时候，权重W是随机采样生成的，一个常见的神经元表示为：ReLU(Wx+b) = max(Wx+b,0)，即在Wx+b=0的两侧，对数据采用不同的操作方法。具体到ReLU就是一侧收缩，一侧保持不变。&lt;/p&gt;
&lt;p&gt;随机的Wx+b=0表现为上图中的随机虚线，注意到，两条绿色虚线实际上并没有什么意义，在使用梯度下降时，可能需要很多次迭代才会使这些虚线对数据点进行有效的分割，就像紫色虚线那样，这势必会带来求解速率变慢的问题。更何况，我们这只是个二维的演示，数据占据四个象限中的一个，如果是几百、几千、上万维呢？而且数据在第一象限中也只是占了很小的一部分区域而已，可想而知不对数据进行预处理带来了多少运算资源的浪费，而且大量的数据外分割面在迭代时很可能会在刚进入数据中时就遇到了一个局部最优，导致overfit的问题。&lt;/p&gt;
&lt;p&gt;这时，如果我们将数据减去其均值，数据点就不再只分布在第一象限，这时一个随机分界面落入数据分布的概率增加了多少呢？2^n倍！如果我们使用去除相关性的算法，例如PCA和ZCA白化，数据不再是一个狭长的分布，随机分界面有效的概率就又大大增加了。&lt;/p&gt;
&lt;p&gt;不过计算协方差矩阵的特征值太耗时也太耗空间，我们一般最多只用到z-score处理，即每一维度减去自身均值，再除以自身标准差，这样能使数据点在每维上具有相似的宽度，可以起到一定的增大数据分布范围，进而使更多随机分界面有意义的作用。&lt;/p&gt;
&lt;h2 id=&quot;batch-normalization-算法&quot;&gt;&lt;a href=&quot;#batch-normalization-算法&quot; class=&quot;headerlink&quot; title=&quot;batch normalization 算法&quot;&gt;&lt;/a&gt;batch normalization 算法&lt;/h2&gt;&lt;p&gt;算法基本流程：&lt;/p&gt;
&lt;center&gt;&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-8-5/92943869.jpg&quot; alt=&quot;&quot;&gt;&lt;br&gt;&lt;/center&gt;

&lt;p&gt;如果在ReLU=max(Wx+b,0)之后，对数据进行归一化。然而，文章中说这样做在训练初期，分界面还在剧烈变化时，计算出的参数不稳定，所以退而求其次，在Wx+b之后进行归一化。因为初始的W是从标准高斯分布中采样得到的，而W中元素的数量远大于x，Wx+b每维的均值本身就接近0、方差接近1，所以在Wx+b后使用Batch Normalization能得到更稳定的结果。&lt;/p&gt;
&lt;p&gt;文中使用了类似z-score的归一化方式：每一维度减去自身均值，再除以自身标准差，由于使用的是随机梯度下降法，这些均值和方差也只能在当前迭代的batch中计算，故作者给这个算法命名为Batch Normalization。&lt;/p&gt;
&lt;p&gt;在Normalization完成后，Google的研究员仍对数值稳定性不放心，又加入了两个参数gamma和beta，使得&lt;/p&gt;
&lt;p&gt;$$y_i=\gamma \hat{x}_i+ \beta$$&lt;/p&gt;
&lt;p&gt;注意到，如果我们令gamma等于之前求得的标准差，beta等于之前求得的均值，则这个变换就又将数据还原回去了。在他们的模型中，这两个参数与每层的W和b一样，是需要迭代求解的。为什么进行归一化之后又添加两个可学习的参数对数据进行变化：&lt;strong&gt;实际上BN可以看作是在原模型上加入的“新操作”，这个新操作很大可能会改变某层原来的输入。当然也可能不改变，不改变的时候就是“还原原来输入”。如此一来，既可以改变同时也可以保持原输入，那么模型的容纳能力（capacity）就提升了。&lt;/strong&gt;&lt;/p&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;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-8-5/21841995.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;根据链式求导法则，我们可以把复杂的运算分解成一步一步能够简单求导的运算，然后根据链式求导法则来求得最终的导数，参考&lt;a href=&quot;http://cs231n.github.io/optimization-2/&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;cs231n&lt;/a&gt;。&lt;/p&gt;
&lt;h3 id=&quot;前向传播&quot;&gt;&lt;a href=&quot;#前向传播&quot; class=&quot;headerlink&quot; title=&quot;前向传播&quot;&gt;&lt;/a&gt;前向传播&lt;/h3&gt;&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;batchnorm_forward&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(x, gamma, beta, eps)&lt;/span&gt;:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  N, D = x.shape&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;comment&quot;&gt;#step1: calculate mean&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  mu = &lt;span class=&quot;number&quot;&gt;1.&lt;/span&gt;/N * np.sum(x, axis = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;comment&quot;&gt;#step2: subtract mean vector of every trainings example&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  xmu = x - mu&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;comment&quot;&gt;#step3: following the lower branch - calculation denominator&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  sq = xmu ** &lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;comment&quot;&gt;#step4: calculate variance&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  var = &lt;span class=&quot;number&quot;&gt;1.&lt;/span&gt;/N * np.sum(sq, axis = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;comment&quot;&gt;#step5: add eps for numerical stability, then sqrt&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  sqrtvar = np.sqrt(var + eps)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;comment&quot;&gt;#step6: invert sqrtwar&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  ivar = &lt;span class=&quot;number&quot;&gt;1.&lt;/span&gt;/sqrtvar&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;comment&quot;&gt;#step7: execute normalization&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  xhat = xmu * ivar&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;comment&quot;&gt;#step8: Nor the two transformation steps&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  gammax = gamma * xhat&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;comment&quot;&gt;#step9&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  out = gammax + beta&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;comment&quot;&gt;#store intermediate&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  cache = (xhat,gamma,xmu,ivar,sqrtvar,var,eps)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; out, cache&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;h3 id=&quot;反向求导&quot;&gt;&lt;a href=&quot;#反向求导&quot; class=&quot;headerlink&quot; title=&quot;反向求导&quot;&gt;&lt;/a&gt;反向求导&lt;/h3&gt;&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;batchnorm_backward&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(dout, cache)&lt;/span&gt;:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;comment&quot;&gt;#unfold the variables stored in cache&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  xhat,gamma,xmu,ivar,sqrtvar,var,eps = cache&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;comment&quot;&gt;#get the dimensions of the input/output&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  N,D = dout.shape&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;comment&quot;&gt;#step9&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  dbeta = np.sum(dout, axis=&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  dgammax = dout &lt;span class=&quot;comment&quot;&gt;#not necessary, but more understandable&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;comment&quot;&gt;#step8&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  dgamma = np.sum(dgammax*xhat, axis=&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  dxhat = dgammax * gamma&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;comment&quot;&gt;#step7&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  divar = np.sum(dxhat*xmu, axis=&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  dxmu1 = dxhat * ivar&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;comment&quot;&gt;#step6&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  dsqrtvar = &lt;span class=&quot;number&quot;&gt;-1.&lt;/span&gt; /(sqrtvar**&lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;) * divar&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;comment&quot;&gt;#step5&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  dvar = &lt;span class=&quot;number&quot;&gt;0.5&lt;/span&gt; * &lt;span class=&quot;number&quot;&gt;1.&lt;/span&gt; /np.sqrt(var+eps) * dsqrtvar&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;comment&quot;&gt;#step4&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  dsq = &lt;span class=&quot;number&quot;&gt;1.&lt;/span&gt; /N * np.ones((N,D)) * dvar&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;comment&quot;&gt;#step3&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  dxmu2 = &lt;span class=&quot;number&quot;&gt;2&lt;/span&gt; * xmu * dsq&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;comment&quot;&gt;#step2&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  dx1 = (dxmu1 + dxmu2)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  dmu = &lt;span class=&quot;number&quot;&gt;-1&lt;/span&gt; * np.sum(dxmu1+dxmu2, axis=&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;comment&quot;&gt;#step1&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  dx2 = &lt;span class=&quot;number&quot;&gt;1.&lt;/span&gt; /N * np.ones((N,D)) * dmu&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;comment&quot;&gt;#step0&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  dx = dx1 + dx2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; dx, dgamma, dbeta&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;h2 id=&quot;卷积层batch-normalization&quot;&gt;&lt;a href=&quot;#卷积层batch-normalization&quot; class=&quot;headerlink&quot; title=&quot;卷积层batch normalization&quot;&gt;&lt;/a&gt;卷积层batch normalization&lt;/h2&gt;&lt;p&gt;这里有一点需要注意，像卷积层这样具有权值共享的层，Wx+b的均值和方差是对整张map求得的，在batch_size * channel * height * width这么大的一层中，对总共batch_size*height*width个像素点统计得到一个均值和一个标准差，共得到channel组参数。&lt;/p&gt;
&lt;p&gt;也就是说把每个channel看出一批数据，然后就可以调用全连接层的batch normalization 算法了。&lt;/p&gt;
&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;47&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;48&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;49&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;50&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;spatial_batchnorm_forward&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(x, gamma, beta, bn_param)&lt;/span&gt;:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;string&quot;&gt;&quot;&quot;&quot;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  Computes the forward pass for spatial batch normalization.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  Inputs:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  - x: Input data of shape (N, C, H, W)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  - gamma: Scale parameter, of shape (C,)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  - beta: Shift parameter, of shape (C,)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  - bn_param: Dictionary with the following keys:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    - mode: &#39;train&#39; or &#39;test&#39;; required&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    - eps: Constant for numeric stability&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    - momentum: Constant for running mean / variance. momentum=0 means that&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      old information is discarded completely at every time step, while&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      momentum=1 means that new information is never incorporated. The&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      default of momentum=0.9 should work well in most situations.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    - running_mean: Array of shape (D,) giving running mean of features&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    - running_var Array of shape (D,) giving running variance of features&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  Returns a tuple of:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  - out: Output data, of shape (N, C, H, W)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  - cache: Values needed for the backward pass&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &quot;&quot;&quot;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  out, cache = &lt;span class=&quot;keyword&quot;&gt;None&lt;/span&gt;, &lt;span class=&quot;keyword&quot;&gt;None&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  N, C, H, W = x.shape&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  x_flat = x.transpose(&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;3&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;).reshape(&lt;span class=&quot;number&quot;&gt;-1&lt;/span&gt;, C)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  out_flat, cache = batchnorm_forward(x_flat, gamma, beta, bn_param)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  out = out_flat.reshape(N, H, W, C).transpose(&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;3&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; out, cache&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;spatial_batchnorm_backward&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(dout, cache)&lt;/span&gt;:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;string&quot;&gt;&quot;&quot;&quot;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  Computes the backward pass for spatial batch normalization.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  Inputs:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  - dout: Upstream derivatives, of shape (N, C, H, W)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  - cache: Values from the forward pass&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  Returns a tuple of:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  - dx: Gradient with respect to inputs, of shape (N, C, H, W)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  - dgamma: Gradient with respect to scale parameter, of shape (C,)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  - dbeta: Gradient with respect to shift parameter, of shape (C,)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &quot;&quot;&quot;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  dx, dgamma, dbeta = &lt;span class=&quot;keyword&quot;&gt;None&lt;/span&gt;, &lt;span class=&quot;keyword&quot;&gt;None&lt;/span&gt;, &lt;span class=&quot;keyword&quot;&gt;None&lt;/span&gt;                                   &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  N, C, H, W = dout.shape&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  dout_flat = dout.transpose(&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;3&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;).reshape(&lt;span class=&quot;number&quot;&gt;-1&lt;/span&gt;, C)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  dx_flat, dgamma, dbeta = batchnorm_backward(dout_flat, cache)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  dx = dx_flat.reshape(N, H, W, C).transpose(&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;3&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;)                        &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; dx, dgamma, dbeta&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&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;http://blog.csdn.net/hjimce/article/details/50866313&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;Batch Normalization 学习笔记&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://blog.csdn.net/happynear/article/details/44238541&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;《Batch Normalization Accelerating Deep Network Training by Reducing Internal Covariate Shift》阅读笔记与实现&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://zhihu.com/question/38102762/answer/85238569&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;深度学习中 Batch Normalization为什么效果好？ - 回答作者: 魏秀参&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://kratzert.github.io/2016/02/12/understanding-the-gradient-flow-through-the-batch-normalization-layer.html&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;Understanding the backward pass through Batch Normalization Layer&lt;/a&gt;&lt;/p&gt;
</content>
    
    <summary type="html">
    
      &lt;p&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-8-5/21841995.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
    
    </summary>
    
    
      <category term="Deep Learning" scheme="http://buptldy.github.io/tags/Deep-Learning/"/>
    
      <category term="CNN" scheme="http://buptldy.github.io/tags/CNN/"/>
    
  </entry>
  
  <entry>
    <title>Shopping Reviews sentiment analysis</title>
    <link href="http://buptldy.github.io/2016/07/20/2016-07-20-sentiment%20analysis/"/>
    <id>http://buptldy.github.io/2016/07/20/2016-07-20-sentiment analysis/</id>
    <published>2016-07-20T02:00:00.000Z</published>
    <updated>2016-10-04T06:13:08.270Z</updated>
    
    <content type="html">&lt;p&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-7-18/19781698.jpg&quot; alt=&quot;&quot;&gt;&lt;br&gt;&lt;a id=&quot;more&quot;&gt;&lt;/a&gt;&lt;br&gt;情感分析是一种常见的自然语言处理（NLP）方法的应用，特别是在以提取文本的情感内容为目标的分类方法中。通过这种方式，情感分析可以被视为利用一些情感得分指标来量化定性数据的方法。尽管情绪在很大程度上是主观的，但是情感量化分析已经有很多有用的实践，比如企业分析消费者对产品的反馈信息，或者检测在线评论中的差评信息。&lt;/p&gt;
&lt;p&gt;最简单的情感分析方法是利用词语的正负属性来判定。句子中的每个单词都有一个得分，乐观的单词得分为+1，悲观的单词则为-1。然后我们对句子中所有单词得分进行加总求和得到一个最终的情感总分。很明显，这种方法有许多局限之处，最重要的一点在于它忽略了上下文的信息。例如，在这个简易模型中，因为“not”的得分为-1，而“good”的得分为 +1，所以词组“not good”将被归类到中性词组中。但是“not good”通常是消极的。&lt;/p&gt;
&lt;p&gt;另外一个常见的方法是将文本视为一个“词袋”。我们将每个文本看出一个&lt;code&gt;1xN&lt;/code&gt;的向量，其中N表示文本词汇的数量。该向量中每一列都是一个单词，其对应的值为该单词出现的频数。例如，词组“bag of bag of words”可以被编码为&lt;code&gt;[2, 2, 1]&lt;/code&gt;。这些数据可以被应用到机器学习分类算法中（比如罗吉斯回归或者支持向量机），从而预测未知数据的情感状况。需要注意的是，这种有监督学习的方法要求利用已知情感状况的数据作为训练集。虽然这个方法改进了之前的模型，但是它仍然忽略了上下文的信息和数据集的规模情况。&lt;/p&gt;
&lt;h2 id=&quot;Word2Vec-and-Doc2Vec&quot;&gt;&lt;a href=&quot;#Word2Vec-and-Doc2Vec&quot; class=&quot;headerlink&quot; title=&quot;Word2Vec and Doc2Vec&quot;&gt;&lt;/a&gt;Word2Vec and Doc2Vec&lt;/h2&gt;&lt;p&gt;谷歌开发了一个叫做Word2Vec的方法，该方法可以在捕捉语境信息的同时压缩数据规模。Word2Vec实际上是两种不同的方法：Continuous Bag of Words (CBOW) 和 Skip-gram。CBOW的目标是根据上下文来预测当前词语。Skip-gram刚好相反：根据当前词语来预测上下文。这两种方法都利用人工神经网络作为它们的分类算法。起初，每个单词都是一个随机的 N 维向量。经过训练之后，该算法利用 CBOW 或者 Skip-gram 的方法获得了每个单词的最优向量。&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-5-24/80870876.jpg&quot; alt=&quot;&quot;&gt;&lt;br&gt;在上图中 $w(t)$ 表示当前的词汇，$w(t-2)$ ， $w(t-1)$ 等表示上下文词汇。&lt;/p&gt;
&lt;p&gt;现在这些词向量已经捕捉到上下文的信息。我们可以利用基本代数公式来发现单词之间的关系（比如，“国王”-“男人”+“女人”=“王后”）。这些词向量可以代替词袋用来预测未知数据的情感状况。该模型的优点在于不仅考虑了语境信息还压缩了数据规模（通常情况下，词汇量规模大约在300个单词左右而不是之前模型的100000个单词）。因为神经网络可以替我们提取出这些特征的信息，所以我们仅需要做很少的手动工作。&lt;/p&gt;
&lt;h2 id=&quot;使用SVM和Word2Vec进行情感分类&quot;&gt;&lt;a href=&quot;#使用SVM和Word2Vec进行情感分类&quot; class=&quot;headerlink&quot; title=&quot;使用SVM和Word2Vec进行情感分类&quot;&gt;&lt;/a&gt;使用SVM和Word2Vec进行情感分类&lt;/h2&gt;&lt;p&gt;我们使用的训练数据是网友&lt;a href=&quot;http://spaces.ac.cn/archives/3414/&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;苏剑林&lt;/a&gt;收集分享的两万多条中文标注语料，涉及六个领域的评论数据。&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-5-25/48028586.jpg&quot; alt=&quot;&quot;&gt;&lt;br&gt;我们随机正负这两组数据中抽取样本，构建比例为8：2的训练集和测试集。随后，我们对训练集数据构建Word2Vec模型，其中分类器的输入值为推文中所有词向量的加权平均值。word2vec工具和svm分类器分别使用python中的&lt;a href=&quot;https://radimrehurek.com/gensim/&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;gensim&lt;/a&gt;库和&lt;a href=&quot;http://scikit-learn.org/&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;sklearn&lt;/a&gt;库。&lt;/p&gt;
&lt;p&gt;加载文件，并分词&lt;/p&gt;
&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;# 加载文件，导入数据,分词&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;loadfile&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;()&lt;/span&gt;:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    neg=pd.read_excel(&lt;span class=&quot;string&quot;&gt;&#39;data/neg.xls&#39;&lt;/span&gt;,header=&lt;span class=&quot;keyword&quot;&gt;None&lt;/span&gt;,index=&lt;span class=&quot;keyword&quot;&gt;None&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    pos=pd.read_excel(&lt;span class=&quot;string&quot;&gt;&#39;data/pos.xls&#39;&lt;/span&gt;,header=&lt;span class=&quot;keyword&quot;&gt;None&lt;/span&gt;,index=&lt;span class=&quot;keyword&quot;&gt;None&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    cw = &lt;span class=&quot;keyword&quot;&gt;lambda&lt;/span&gt; x: list(jieba.cut(x))&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    pos[&lt;span class=&quot;string&quot;&gt;&#39;words&#39;&lt;/span&gt;] = pos[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;].apply(cw)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    neg[&lt;span class=&quot;string&quot;&gt;&#39;words&#39;&lt;/span&gt;] = neg[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;].apply(cw)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;#print pos[&#39;words&#39;]&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;#use 1 for positive sentiment, 0 for negative&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    y = np.concatenate((np.ones(len(pos)), np.zeros(len(neg))))&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    x_train, x_test, y_train, y_test = train_test_split(np.concatenate((pos[&lt;span class=&quot;string&quot;&gt;&#39;words&#39;&lt;/span&gt;], neg[&lt;span class=&quot;string&quot;&gt;&#39;words&#39;&lt;/span&gt;])), y, test_size=&lt;span class=&quot;number&quot;&gt;0.2&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    np.save(&lt;span class=&quot;string&quot;&gt;&#39;svm_data/y_train.npy&#39;&lt;/span&gt;,y_train)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    np.save(&lt;span class=&quot;string&quot;&gt;&#39;svm_data/y_test.npy&#39;&lt;/span&gt;,y_test)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; x_train,x_test&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;计算词向量，并对每个评论的所有词向量取均值作为每个评论的输入&lt;br&gt;&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;#对每个句子的所有词向量取均值&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;buildWordVector&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(text, size,imdb_w2v)&lt;/span&gt;:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    vec = np.zeros(size).reshape((&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;, size))&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    count = &lt;span class=&quot;number&quot;&gt;0.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; word &lt;span class=&quot;keyword&quot;&gt;in&lt;/span&gt; text:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;try&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            vec += imdb_w2v[word].reshape((&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;, size))&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            count += &lt;span class=&quot;number&quot;&gt;1.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;except&lt;/span&gt; KeyError:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;continue&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; count != &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        vec /= count&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; vec&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;#计算词向量&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;get_train_vecs&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(x_train,x_test)&lt;/span&gt;:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    n_dim = &lt;span class=&quot;number&quot;&gt;300&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;#Initialize model and build vocab&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    imdb_w2v = Word2Vec(size=n_dim, min_count=&lt;span class=&quot;number&quot;&gt;10&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    imdb_w2v.build_vocab(x_train)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;#Train the model over train_reviews (this may take several minutes)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    imdb_w2v.train(x_train)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    train_vecs = np.concatenate([buildWordVector(z, n_dim,imdb_w2v) &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; z &lt;span class=&quot;keyword&quot;&gt;in&lt;/span&gt; x_train])&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;#train_vecs = scale(train_vecs)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    np.save(&lt;span class=&quot;string&quot;&gt;&#39;svm_data/train_vecs.npy&#39;&lt;/span&gt;,train_vecs)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;print&lt;/span&gt; train_vecs.shape&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;#Train word2vec on test tweets&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    imdb_w2v.train(x_test)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    imdb_w2v.save(&lt;span class=&quot;string&quot;&gt;&#39;svm_data/w2v_model/w2v_model.pkl&#39;&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;#Build test tweet vectors then scale&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    test_vecs = np.concatenate([buildWordVector(z, n_dim,imdb_w2v) &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; z &lt;span class=&quot;keyword&quot;&gt;in&lt;/span&gt; x_test])&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;#test_vecs = scale(test_vecs)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    np.save(&lt;span class=&quot;string&quot;&gt;&#39;svm_data/test_vecs.npy&#39;&lt;/span&gt;,test_vecs)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;print&lt;/span&gt; test_vecs.shape&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;训练svm模型&lt;/p&gt;
&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;##训练svm模型&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;svm_train&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(train_vecs,y_train,test_vecs,y_test)&lt;/span&gt;:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    clf=SVC(kernel=&lt;span class=&quot;string&quot;&gt;&#39;rbf&#39;&lt;/span&gt;,verbose=&lt;span class=&quot;keyword&quot;&gt;True&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    clf.fit(train_vecs,y_train)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    joblib.dump(clf, &lt;span class=&quot;string&quot;&gt;&#39;svm_data/svm_model/model.pkl&#39;&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;print&lt;/span&gt; clf.score(test_vecs,y_test)&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;在没有创建任何类型的特性和最小文本预处理的情况下，我们利用Scikit-Learn构建的简单线性模型的预测精度为80%左右。有趣的是，删除标点符号会影响预测精度，这说明Word2Vec模型可以提取出文档中符号所包含的信息。处理单独的单词，训练更长时间，做更多的数据预处理工作，和调整模型的参数都可以提高预测精度。用svm分类有一个缺点是，我们把每个句子的词向量求平均丢失了句子词语之间的顺序信息。&lt;/p&gt;
&lt;h2 id=&quot;使用LSTM和Word2Vec进行情感分类&quot;&gt;&lt;a href=&quot;#使用LSTM和Word2Vec进行情感分类&quot; class=&quot;headerlink&quot; title=&quot;使用LSTM和Word2Vec进行情感分类&quot;&gt;&lt;/a&gt;使用LSTM和Word2Vec进行情感分类&lt;/h2&gt;&lt;p&gt;人类的思维不是每时每刻都是崭新的，就像你阅读一篇文章时，你理解当前词语的基础是基于对之前词语的理解，人类的思维是能保持一段时间的。传统的人工神经网络，并不能模拟人类思维具有记忆性这一特征，例如，你想要分类电影在某一时间点发生了什么事情，使用传统的人工神经网络并不能清楚的表现出之前出现的镜头对当前镜头的提示。循环神经网络能够很好的处理这个问题。&lt;/p&gt;
&lt;p&gt;&lt;center&gt;&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-7-8/34980285.jpg&quot; alt=&quot;&quot;&gt;&lt;br&gt;&lt;/center&gt;&lt;br&gt;RNN相对于传统的神经网络，它允许我们对向量序列进行操作：输入序列、输出序列、或大部分的输入输出序列。如下图所示，每一个矩形是一个向量，箭头则表示函数（比如矩阵相乘）。输入向量用红色标出，输出向量用蓝色标出，绿色的矩形是RNN的状态（下面会详细介绍）。从做到右：（1）没有使用RNN的Vanilla模型，从固定大小的输入得到固定大小输出（比如图像分类）。（2）序列输出（比如图片字幕，输入一张图片输出一段文字序列）。（3）序列输入（比如情感分析，输入一段文字然后将它分类成积极或者消极情感）。（4）序列输入和序列输出（比如机器翻译：一个RNN读取一条英文语句然后将它以法语形式输出）。（5）同步序列输入输出（比如视频分类，对视频中每一帧打标签）。我们注意到在每一个案例中，都没有对序列长度进行预先特定约束，因为递归变换（绿色部分）是固定的，而且我们可以多次使用。&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-5-25/61310852.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;单纯循环神经网络因为无法处理随着递归，权重指数级爆炸或消失的问题（Vanishing gradient problem），难以捕捉长期时间关联；而结合不同的LSTM可以很好解决这个问题。&lt;/p&gt;
&lt;p&gt;LSTM 全称叫 Long Short Term Memory networks，它和传统 RNN 唯一的不同就在与其中的神经元（感知机）的构造不同。传统的 RNN 每个神经元和一般神经网络的感知机没啥区别，但在 LSTM 中，每个神经元是一个“记忆细胞”，细胞里面有一个“输入门”（input gate）, 一个“遗忘门”（forget gate）， 一个“输出门”（output gate）。&lt;/p&gt;
&lt;p&gt;这个设计的用意在于，能够使得LSTM维持两条线，一条明线：当前时刻的数据流（包括其他细胞的输入和来自数据的输入）；一条暗线：这个细胞本身的记忆流。两条线互相呼应，互相纠缠，就像佛祖青灯里的两根灯芯。典型的工作流如下：在“输入门”中，根据当前的数据流来控制接受细胞记忆的影响；接着，在“遗忘门”里，更新这个细胞的记忆和数据流；然后在“输出门”里产生输出更新后的记忆和数据流。LSTM 模型的关键之一就在于这个“遗忘门”， 它能够控制训练时候梯度在这里的收敛性（从而避免了 RNN 中的梯度 vanishing/exploding问题），同时也能够保持长期的记忆性。&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-5-25/14675212.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;实现步骤&quot;&gt;&lt;a href=&quot;#实现步骤&quot; class=&quot;headerlink&quot; title=&quot;实现步骤:&quot;&gt;&lt;/a&gt;实现步骤:&lt;/h3&gt;&lt;p&gt;加载训练文件并分词&lt;br&gt;&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;#加载训练文件&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;loadfile&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;()&lt;/span&gt;:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    neg=pd.read_excel(&lt;span class=&quot;string&quot;&gt;&#39;data/neg.xls&#39;&lt;/span&gt;,header=&lt;span class=&quot;keyword&quot;&gt;None&lt;/span&gt;,index=&lt;span class=&quot;keyword&quot;&gt;None&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    pos=pd.read_excel(&lt;span class=&quot;string&quot;&gt;&#39;data/pos.xls&#39;&lt;/span&gt;,header=&lt;span class=&quot;keyword&quot;&gt;None&lt;/span&gt;,index=&lt;span class=&quot;keyword&quot;&gt;None&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    combined=np.concatenate((pos[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;], neg[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;]))&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    y = np.concatenate((np.ones(len(pos),dtype=int), np.zeros(len(neg),dtype=int)))&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; combined,y&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;#对句子经行分词，并去掉换行符&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;tokenizer&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(text)&lt;/span&gt;:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;string&quot;&gt;&#39;&#39;&#39; Simple Parser converting each document to lower-case, then&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        removing the breaks for new lines and finally splitting on the&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        whitespace&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &#39;&#39;&#39;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    text = [jieba.lcut(document.replace(&lt;span class=&quot;string&quot;&gt;&#39;\n&#39;&lt;/span&gt;, &lt;span class=&quot;string&quot;&gt;&#39;&#39;&lt;/span&gt;)) &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; document &lt;span class=&quot;keyword&quot;&gt;in&lt;/span&gt; text]&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; text&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;创建词语字典，并返回每个词语的索引，词向量，以及每个句子所对应的词语索引&lt;/p&gt;
&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;47&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;48&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;create_dictionaries&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(model=None,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        combined=None)&lt;/span&gt;:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;string&quot;&gt;&#39;&#39;&#39; Function does are number of Jobs:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        1- Creates a word to index mapping&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        2- Creates a word to vector mapping&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        3- Transforms the Training and Testing Dictionaries&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &#39;&#39;&#39;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (combined &lt;span class=&quot;keyword&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;None&lt;/span&gt;) &lt;span class=&quot;keyword&quot;&gt;and&lt;/span&gt; (model &lt;span class=&quot;keyword&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;None&lt;/span&gt;):&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        gensim_dict = Dictionary()&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        gensim_dict.doc2bow(model.vocab.keys(),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                            allow_update=&lt;span class=&quot;keyword&quot;&gt;True&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        w2indx = &amp;#123;v: k+&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; k, v &lt;span class=&quot;keyword&quot;&gt;in&lt;/span&gt; gensim_dict.items()&amp;#125;&lt;span class=&quot;comment&quot;&gt;#所有频数超过10的词语的索引&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        w2vec = &amp;#123;word: model[word] &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; word &lt;span class=&quot;keyword&quot;&gt;in&lt;/span&gt; w2indx.keys()&amp;#125;&lt;span class=&quot;comment&quot;&gt;#所有频数超过10的词语的词向量&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;parse_dataset&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(combined)&lt;/span&gt;:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;string&quot;&gt;&#39;&#39;&#39; Words become integers&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &#39;&#39;&#39;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            data=[]&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; sentence &lt;span class=&quot;keyword&quot;&gt;in&lt;/span&gt; combined:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                new_txt = []&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; word &lt;span class=&quot;keyword&quot;&gt;in&lt;/span&gt; sentence:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;keyword&quot;&gt;try&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        new_txt.append(w2indx[word])&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;keyword&quot;&gt;except&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        new_txt.append(&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                data.append(new_txt)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; data&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        combined=parse_dataset(combined)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        combined= sequence.pad_sequences(combined, maxlen=maxlen)&lt;span class=&quot;comment&quot;&gt;#每个句子所含词语对应的索引，所以句子中含有频数小于10的词语，索引为0&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; w2indx, w2vec,combined&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;&#39;No data provided...&#39;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;#创建词语字典，并返回每个词语的索引，词向量，以及每个句子所对应的词语索引&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;word2vec_train&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(combined)&lt;/span&gt;:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    model = Word2Vec(size=vocab_dim,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                     min_count=n_exposures,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                     window=window_size,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                     workers=cpu_count,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                     iter=n_iterations)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    model.build_vocab(combined)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    model.train(combined)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    model.save(&lt;span class=&quot;string&quot;&gt;&#39;lstm_data/Word2vec_model.pkl&#39;&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    index_dict, word_vectors,combined = create_dictionaries(model=model,combined=combined)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt;   index_dict, word_vectors,combined&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;训练网络，并保存模型，其中LSTM的实现采用Python中的&lt;a href=&quot;http://keras.io/&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;keras&lt;/a&gt;库&lt;/p&gt;
&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;47&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;48&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;49&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;50&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;51&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;52&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;53&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;54&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;55&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;56&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;get_data&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(index_dict,word_vectors,combined,y)&lt;/span&gt;:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    n_symbols = len(index_dict) + &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;  &lt;span class=&quot;comment&quot;&gt;# 所有单词的索引数，频数小于10的词语索引为0，所以加1&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    embedding_weights = np.zeros((n_symbols, vocab_dim))&lt;span class=&quot;comment&quot;&gt;#索引为0的词语，词向量全为0&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; word, index &lt;span class=&quot;keyword&quot;&gt;in&lt;/span&gt; index_dict.items():&lt;span class=&quot;comment&quot;&gt;#从索引为1的词语开始，对每个词语对应其词向量&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        embedding_weights[index, :] = word_vectors[word]&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    x_train, x_test, y_train, y_test = train_test_split(combined, y, test_size=&lt;span class=&quot;number&quot;&gt;0.2&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;print&lt;/span&gt; x_train.shape,y_train.shape&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; n_symbols,embedding_weights,x_train,y_train,x_test,y_test&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;##定义网络结构&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;train_lstm&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(n_symbols,embedding_weights,x_train,y_train,x_test,y_test)&lt;/span&gt;:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;&#39;Defining a Simple Keras Model...&#39;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    model = Sequential()  &lt;span class=&quot;comment&quot;&gt;# or Graph or whatever&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    model.add(Embedding(output_dim=vocab_dim,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        input_dim=n_symbols,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        mask_zero=&lt;span class=&quot;keyword&quot;&gt;True&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        weights=[embedding_weights],&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        input_length=input_length))  &lt;span class=&quot;comment&quot;&gt;# Adding Input Length&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    model.add(LSTM(output_dim=&lt;span class=&quot;number&quot;&gt;50&lt;/span&gt;, activation=&lt;span class=&quot;string&quot;&gt;&#39;sigmoid&#39;&lt;/span&gt;, inner_activation=&lt;span class=&quot;string&quot;&gt;&#39;hard_sigmoid&#39;&lt;/span&gt;))&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    model.add(Dropout(&lt;span class=&quot;number&quot;&gt;0.5&lt;/span&gt;))&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    model.add(Dense(&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;))&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    model.add(Activation(&lt;span class=&quot;string&quot;&gt;&#39;sigmoid&#39;&lt;/span&gt;))&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;&#39;Compiling the Model...&#39;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    model.compile(loss=&lt;span class=&quot;string&quot;&gt;&#39;binary_crossentropy&#39;&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                  optimizer=&lt;span class=&quot;string&quot;&gt;&#39;adam&#39;&lt;/span&gt;,metrics=[&lt;span class=&quot;string&quot;&gt;&#39;accuracy&#39;&lt;/span&gt;])&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;&quot;Train...&quot;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    model.fit(x_train, y_train, batch_size=batch_size, nb_epoch=n_epoch,verbose=&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;, validation_data=(x_test, y_test),show_accuracy=&lt;span class=&quot;keyword&quot;&gt;True&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;&quot;Evaluate...&quot;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    score = model.evaluate(x_test, y_test,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                                batch_size=batch_size)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    yaml_string = model.to_yaml()&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;with&lt;/span&gt; open(&lt;span class=&quot;string&quot;&gt;&#39;lstm_data/lstm.yml&#39;&lt;/span&gt;, &lt;span class=&quot;string&quot;&gt;&#39;w&#39;&lt;/span&gt;) &lt;span class=&quot;keyword&quot;&gt;as&lt;/span&gt; outfile:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        outfile.write( yaml.dump(yaml_string, default_flow_style=&lt;span class=&quot;keyword&quot;&gt;True&lt;/span&gt;) )&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    model.save_weights(&lt;span class=&quot;string&quot;&gt;&#39;lstm_data/lstm.h5&#39;&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;&#39;Test score:&#39;&lt;/span&gt;, score&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;#训练模型，并保存&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;train&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;()&lt;/span&gt;:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;&#39;Loading Data...&#39;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    combined,y=loadfile()&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;print&lt;/span&gt; len(combined),len(y)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;&#39;Tokenising...&#39;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    combined = tokenizer(combined)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;&#39;Training a Word2vec model...&#39;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    index_dict, word_vectors,combined=word2vec_train(combined)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;&#39;Setting up Arrays for Keras Embedding Layer...&#39;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    n_symbols,embedding_weights,x_train,y_train,x_test,y_test=get_data(index_dict, word_vectors,combined,y)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;print&lt;/span&gt; x_train.shape,y_train.shape&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    train_lstm(n_symbols,embedding_weights,x_train,y_train,x_test,y_test)&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;h3 id=&quot;结果分析&quot;&gt;&lt;a href=&quot;#结果分析&quot; class=&quot;headerlink&quot; title=&quot;结果分析&quot;&gt;&lt;/a&gt;结果分析&lt;/h3&gt;&lt;p&gt; 使用LSTM网络在测试集上的准确率为92%，比用SVM分类提高了不少。&lt;/p&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://github.com/BUPTLdy/Sentiment-Analysis&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;https://github.com/BUPTLdy/Sentiment-Analysis&lt;/a&gt;&lt;/p&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;http://www.15yan.com/story/huxAyyeuYAj/&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;http://www.15yan.com/story/huxAyyeuYAj/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://colah.github.io/posts/2015-08-Understanding-LSTMs/&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;http://colah.github.io/posts/2015-08-Understanding-LSTMs/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://karpathy.github.io/2015/05/21/rnn-effectiveness/&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;http://karpathy.github.io/2015/05/21/rnn-effectiveness/&lt;/a&gt;&lt;/p&gt;
</content>
    
    <summary type="html">
    
      &lt;p&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-7-18/19781698.jpg&quot; alt=&quot;&quot;&gt;&lt;br&gt;
    
    </summary>
    
    
      <category term="Deep Learning" scheme="http://buptldy.github.io/tags/Deep-Learning/"/>
    
      <category term="LSTM" scheme="http://buptldy.github.io/tags/LSTM/"/>
    
      <category term="NLP" scheme="http://buptldy.github.io/tags/NLP/"/>
    
  </entry>
  
  <entry>
    <title>Solve Linear Classifier by SGD</title>
    <link href="http://buptldy.github.io/2016/06/20/2016-06-20-SVM%20Softmax%20SGD/"/>
    <id>http://buptldy.github.io/2016/06/20/2016-06-20-SVM Softmax SGD/</id>
    <published>2016-06-20T02:00:00.000Z</published>
    <updated>2016-10-04T06:07:13.593Z</updated>
    
    <content type="html">&lt;p&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-6-20/61070235.jpg&quot; alt=&quot;&quot;&gt;&lt;br&gt;&lt;a id=&quot;more&quot;&gt;&lt;/a&gt;&lt;/p&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;br&gt;$$f(x_i,W,b)=Wx_i+b （1）$$&lt;br&gt;在上面的公式中，如果是对图像经行分类，$x_i$表示对一张图片展开成一个列向量维数为[D,1],矩阵&lt;strong&gt;W&lt;/strong&gt;维数为[K,D],向量&lt;strong&gt;b&lt;/strong&gt;维数为[K,1]。参数&lt;strong&gt;W&lt;/strong&gt;通常成为权值，&lt;strong&gt;b&lt;/strong&gt;为偏置。&lt;/p&gt;
&lt;h3 id=&quot;导入数据&quot;&gt;&lt;a href=&quot;#导入数据&quot; class=&quot;headerlink&quot; title=&quot;导入数据&quot;&gt;&lt;/a&gt;导入数据&lt;/h3&gt;&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;import&lt;/span&gt; numpy &lt;span class=&quot;keyword&quot;&gt;as&lt;/span&gt; np&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;from&lt;/span&gt; sklearn.datasets &lt;span class=&quot;keyword&quot;&gt;import&lt;/span&gt; load_digits&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;from&lt;/span&gt; sklearn.cross_validation &lt;span class=&quot;keyword&quot;&gt;import&lt;/span&gt; train_test_split&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;import&lt;/span&gt; matplotlib.pyplot &lt;span class=&quot;keyword&quot;&gt;as&lt;/span&gt; plt&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;# This is a bit of magic to make matplotlib figures appear inline in the&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;# notebook rather than in a new window.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;%matplotlib inline&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;plt.rcParams[&lt;span class=&quot;string&quot;&gt;&#39;figure.figsize&#39;&lt;/span&gt;] = (&lt;span class=&quot;number&quot;&gt;10.0&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;8.0&lt;/span&gt;) &lt;span class=&quot;comment&quot;&gt;# set default size of plots&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;plt.rcParams[&lt;span class=&quot;string&quot;&gt;&#39;image.interpolation&#39;&lt;/span&gt;] = &lt;span class=&quot;string&quot;&gt;&#39;nearest&#39;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;plt.rcParams[&lt;span class=&quot;string&quot;&gt;&#39;image.cmap&#39;&lt;/span&gt;] = &lt;span class=&quot;string&quot;&gt;&#39;gray&#39;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;digits=load_digits()&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;X_train, X_test, y_train, y_test = train_test_split(digits.data, digits.target, test_size=&lt;span class=&quot;number&quot;&gt;0.2&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;X_train, X_val, y_train, y_val = train_test_split(X_train, y_train, test_size=&lt;span class=&quot;number&quot;&gt;0.1&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;print&lt;/span&gt; X_train.shape, y_train.shape&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;print&lt;/span&gt; X_val.shape, y_val.shape&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;print&lt;/span&gt; X_test.shape, y_test.shape&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;pre&gt;&lt;code&gt;(1293, 64) (1293,)
(144, 64) (144,)
(360, 64) (360,)
&lt;/code&gt;&lt;/pre&gt;&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;classes = [&lt;span class=&quot;string&quot;&gt;&#39;0&#39;&lt;/span&gt;, &lt;span class=&quot;string&quot;&gt;&#39;1&#39;&lt;/span&gt;, &lt;span class=&quot;string&quot;&gt;&#39;2&#39;&lt;/span&gt;, &lt;span class=&quot;string&quot;&gt;&#39;3&#39;&lt;/span&gt;, &lt;span class=&quot;string&quot;&gt;&#39;4&#39;&lt;/span&gt;, &lt;span class=&quot;string&quot;&gt;&#39;5&#39;&lt;/span&gt;, &lt;span class=&quot;string&quot;&gt;&#39;6&#39;&lt;/span&gt;, &lt;span class=&quot;string&quot;&gt;&#39;7&#39;&lt;/span&gt;, &lt;span class=&quot;string&quot;&gt;&#39;8&#39;&lt;/span&gt;, &lt;span class=&quot;string&quot;&gt;&#39;9&#39;&lt;/span&gt;]&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;num_classes = len(classes)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;samples_per_class = &lt;span class=&quot;number&quot;&gt;3&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; y, cls &lt;span class=&quot;keyword&quot;&gt;in&lt;/span&gt; enumerate(classes):&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    idxs = np.flatnonzero(y_train == y)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    idxs = np.random.choice(idxs, samples_per_class, replace=&lt;span class=&quot;keyword&quot;&gt;False&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; i, idx &lt;span class=&quot;keyword&quot;&gt;in&lt;/span&gt; enumerate(idxs):&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        plt_idx = i * num_classes + y + &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        plt.subplot(samples_per_class, num_classes, plt_idx)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        plt.imshow(X_train[idx].astype(&lt;span class=&quot;string&quot;&gt;&#39;uint8&#39;&lt;/span&gt;).reshape(&lt;span class=&quot;number&quot;&gt;8&lt;/span&gt;,&lt;span class=&quot;number&quot;&gt;8&lt;/span&gt;))&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        plt.axis(&lt;span class=&quot;string&quot;&gt;&#39;off&#39;&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; i == &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            plt.title(cls)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;plt.show()&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-6-20/14165529.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;比如在数字手写识别数据集中，要分类[0-9]共十类数字手写图片，每张图片的像素为8×8，如上图所示。分类器的目的就是通过训练得到参数&lt;strong&gt;W,b&lt;/strong&gt;，应为我们知道输入数据是 $(x_i,y_i)$ （$x_i$是输入图片像素值，$y_i$为对应类别号）是给定而且是固定的，我们的目标就是通过控制参数&lt;strong&gt;W,b&lt;/strong&gt;来尽量拟合公式(1), 使得公式(1)能通过参数对输入数据$x_i$计算得到正确的$y_i$。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Bias trick&lt;/strong&gt;,在公式(1)中有两个参数&lt;strong&gt;W,b&lt;/strong&gt;，通过一个小技巧可以把这两个参数组合在一个矩阵中，通过把$x_i$增加一维，设置值为1，就可以把公式(1)写为：&lt;br&gt;$$f(x_i,W)=Wx_i$$&lt;br&gt;原理如下图所示：&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-6-20/17970270.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;X_train = np.hstack([X_train, np.ones((X_train.shape[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;], &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;))])&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;X_val = np.hstack([X_val, np.ones((X_val.shape[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;], &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;))])&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;X_test = np.hstack([X_test, np.ones((X_test.shape[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;], &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;))])&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;print&lt;/span&gt; X_train.shape, X_val.shape, X_test.shape&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;pre&gt;&lt;code&gt;(1293, 65) (144, 65) (360, 65)
&lt;/code&gt;&lt;/pre&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;上面说到使用公式$f(x_i,W)=Wx_i$对输入图片经行每一类的打分，但是开始时线性分类器预测的打分和我们真实的类别可能相差比较远，我们需要一个函数来表示真实的分数和分类器所计算到的分数之间的距离，这个函数就叫损失函数。&lt;/p&gt;
&lt;p&gt;比如说我们输入一张图像像素值$x_i$，其真实类别为$y_i$,我们通过分类器计算每类的得分 $f(x_i,W)$ 。 例如 $s_j=f(x_i,W)_ j$ 表示分类器对输入数据 $x_i$ 预测为第j类的可能性，那么损失函数就可以定义为：&lt;/p&gt;
&lt;p&gt;$$L_i=\sum _{j\neq y_i}max(0,s_j-s_{y_i}+\Delta) (2)$$&lt;/p&gt;
&lt;p&gt;假如我们有三类通过分类器得到每类的分数为[13,-7,11],并假设第一类是正确的类别($y_i=0$), 并假设 $\Delta=10$ ，我们可以通过上述公式计算得到损失函数值为：&lt;br&gt;$$L_i=max(0,−7−13+10)+max(0,11−13+10)$$&lt;/p&gt;
&lt;p&gt;我们可以看到第一个max函数求得的值为0，我们可以理解为对第一类的打分13和第二类的打分-7之间的距离为20已经超过我们设置的间隔10，所以不需要惩罚，即这一部分计算得到的损失函数值为0；第一类与第三类的打分距离为2，小于设定的间隔10，所以计算得到损失函数为8。通过上诉例子我们发现损失函数就是用来描述我们对预测的不满意程度，如下图所示，如果预测到的真实类别的分数与错误类别的分数之间的距离都大于我们设置的阈值，则损失函数的值为0。&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-6-20/62536190.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;这种损失函数就称为&lt;strong&gt;hinge loss&lt;/strong&gt;，因为$s_j=w_j^Tx_i$ ， $w_j$为矩阵&lt;strong&gt;W&lt;/strong&gt;的第$j$行展成的列向量，所以公式(2)可以写为：&lt;/p&gt;
&lt;p&gt; $$L_i=\sum _ {j\neq y_i}max(0,w_j^Tx_i-w_{y_i}^Tx_i+\Delta) (3)$$&lt;/p&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;strong&gt;W&lt;/strong&gt;值的大小，L2正则如下所示，会惩罚过大的参数值：&lt;/p&gt;
&lt;p&gt;$$R(W)=\sum _ k \sum _ lW _ {k,l}^2$$&lt;/p&gt;
&lt;p&gt;所以对整个数据集总的损失函数如下所示：&lt;/p&gt;
&lt;p&gt;$$L= \frac {1}{N} \sum _ i \sum _ {j \neq y_i} [max(0, f(x_i;W) _ j -f(x_i;W) _ { y_i} +\Delta)]+\lambda\sum _ k \sum _ lW _ {k,l}^2 $$&lt;/p&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;对公式(2)的 $w_{y_i}$ 求导，可以得到：&lt;/p&gt;
&lt;p&gt;$$\nabla _ {W _ {y _ i}}L_i =- (\sum _ {j \neq y_i}1(w_j^Tx_i-w _ {y_i}^Tx_i + \Delta &amp;gt;0))x_i$$&lt;/p&gt;
&lt;p&gt;其中&lt;strong&gt;1&lt;/strong&gt;为指示函数，当括号里的条件成立是函数值为1，否则为0。所以上述&lt;strong&gt;对正确类别所对应分类器权值的求导结果就是把错误类别的打分与正确类别打分间距小于阈值的个数再乘以输入数据$x_i$&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;对 $j\neq y_i$ 的其他行，求导结果如下所示，也就是如果这一行所对应的滤波器打分相对于正确的类别分数间隔小于阈值，则对这一行求导所得就是 $x_i$&lt;/p&gt;
&lt;p&gt;$$\nabla _ {W _ {j}}L_i =1(w_j^Tx_i-w _ {y_i}^Tx_i + \Delta &amp;gt;0)x_i$$&lt;/p&gt;
&lt;p&gt;其中SVM的hinge loss以及梯度计算如下所示：&lt;/p&gt;
&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;svm_loss_vectorized&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(W, X, y, reg)&lt;/span&gt;:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  loss = &lt;span class=&quot;number&quot;&gt;0.0&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  dW = np.zeros(W.shape) &lt;span class=&quot;comment&quot;&gt;# initialize the gradient as zero&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  N=X.shape[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;]&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  D=X.shape[&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;]&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  scores = X.dot(W)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  correct_scores = scores[np.arange(N),y]&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  margin = np.maximum(np.zeros(scores.shape),scores+&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;-correct_scores.reshape(N,&lt;span class=&quot;number&quot;&gt;-1&lt;/span&gt;))&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  margin[np.arange(N),y] = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  loss = np.sum(margin)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  loss /= N&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  loss += &lt;span class=&quot;number&quot;&gt;0.5&lt;/span&gt; * reg * np.sum(W * W)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  binary = margin&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  binary[margin&amp;gt;&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;] = &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  row_sum = np.sum(binary, axis=&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  binary[np.arange(N), y] = -row_sum[np.arange(N)]&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  dW = X.T.dot(binary)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  dW /= N&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  dW += reg * W&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; loss, dW&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;h2 id=&quot;Softmax分类器&quot;&gt;&lt;a href=&quot;#Softmax分类器&quot; class=&quot;headerlink&quot; title=&quot;Softmax分类器&quot;&gt;&lt;/a&gt;Softmax分类器&lt;/h2&gt;&lt;p&gt; 分类器相对于SVM分类器来说，增加了一个计算概率的过程，SVM选择得分最大的一类输出，Softmax把所有的得分转换为每一类的概率，如下公式所示：&lt;br&gt;$$P(y_i|x_i;W)=\frac{e^{f _ {y_i}}}{\sum_je^{f_j}}$$&lt;br&gt;其中$f_j$为分类器对每一类的打分。&lt;/p&gt;
&lt;p&gt;Softmax 分类器的损失函数为&lt;strong&gt;cross-entropy loss&lt;/strong&gt;，如下所示，其实就是正确类别概率取对数再乘以-1。&lt;br&gt;$$L_i = -\log\left(\frac{e^{f_{y_i}}}{ \sum_j e^{f_j} }\right) \hspace{0.5in} \text{或等于} \hspace{0.5in} L_i = -f_{y_i} + \log\sum_j e^{f_j}$$&lt;/p&gt;
&lt;p&gt;Softmax 和 SVM分类器的联系区别如下图所示：&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-6-20/8049276.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;cross-entropy loss求导&lt;/p&gt;
&lt;p&gt;对$w_{y_i}$:&lt;br&gt;$$\nabla _ {W _ {y _ i}}L_i =-x_i+p _ {y_i}x_i$$&lt;/p&gt;
&lt;p&gt;对$w_j(j \neq y_i)$:&lt;br&gt;$$\nabla _ {W _ {y _ i}}L_i =p _ {j}x_i$$&lt;br&gt;其中 $p_{j}$ 为Softmax分类器输出为第 $j$ 类的概率。&lt;/p&gt;
&lt;p&gt;Softmax的cross-entropy loss以及梯度计算如下所示：&lt;/p&gt;
&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;softmax_loss_vectorized&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(W, X, y, reg)&lt;/span&gt;:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;string&quot;&gt;&quot;&quot;&quot;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  Softmax loss function, vectorized version.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  Inputs and outputs are the same as softmax_loss_naive.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &quot;&quot;&quot;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;comment&quot;&gt;# Initialize the loss and gradient to zero.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  loss = &lt;span class=&quot;number&quot;&gt;0.0&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  dW = np.zeros_like(W)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  N, D = X.shape&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  scores = X.dot(W) &lt;span class=&quot;comment&quot;&gt;#(N,C)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  p = np.exp(scores.T)/np.sum(np.exp(scores.T),axis=&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  p=p.T&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  loss = -np.sum(np.log(p[np.arange(N), y]))&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  p[np.arange(N), y] = p[np.arange(N), y]&lt;span class=&quot;number&quot;&gt;-1&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  dW = X.T.dot(p)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  loss /=N&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  dW /=N&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  loss += &lt;span class=&quot;number&quot;&gt;0.5&lt;/span&gt; * reg * np.sum(W * W)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  dW += reg * W&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; loss, dW&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&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;/p&gt;
&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;47&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;48&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;49&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;50&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;51&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;52&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;53&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;54&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;55&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;56&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;class&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;LinearClassifier&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(object)&lt;/span&gt;:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(self)&lt;/span&gt;:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    self.W = &lt;span class=&quot;keyword&quot;&gt;None&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;train&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(self, X, y, learning_rate=&lt;span class=&quot;number&quot;&gt;1e-3&lt;/span&gt;, reg=&lt;span class=&quot;number&quot;&gt;1e-5&lt;/span&gt;, num_iters=&lt;span class=&quot;number&quot;&gt;100&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            batch_size=&lt;span class=&quot;number&quot;&gt;200&lt;/span&gt;, verbose=False)&lt;/span&gt;:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    num_train, dim = X.shape&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    num_classes = np.max(y) + &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;comment&quot;&gt;# assume y takes values 0...K-1 where K is number of classes&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; self.W &lt;span class=&quot;keyword&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;None&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      &lt;span class=&quot;comment&quot;&gt;# lazily initialize W&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      self.W = &lt;span class=&quot;number&quot;&gt;0.001&lt;/span&gt; * np.random.randn(dim, num_classes)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;# Run stochastic gradient descent to optimize W&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    loss_history = []&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; it &lt;span class=&quot;keyword&quot;&gt;in&lt;/span&gt; xrange(num_iters):&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      X_batch = &lt;span class=&quot;keyword&quot;&gt;None&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      y_batch = &lt;span class=&quot;keyword&quot;&gt;None&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      index=np.random.choice(num_train,batch_size,replace=&lt;span class=&quot;keyword&quot;&gt;False&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      X_batch=X[index]&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      y_batch = y[index]&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      loss, grad = self.loss(X_batch, y_batch, reg)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      loss_history.append(loss)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      self.W -= learning_rate*grad&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; verbose &lt;span class=&quot;keyword&quot;&gt;and&lt;/span&gt; it % &lt;span class=&quot;number&quot;&gt;100&lt;/span&gt; == &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;&#39;iteration %d / %d: loss %f&#39;&lt;/span&gt; % (it, num_iters, loss)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; loss_history&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;predict&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(self, X)&lt;/span&gt;:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    y_pred = np.zeros(X.shape[&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;])&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    scores = X.dot(self.W)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    y_pred = np.argmax(scores,axis=&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; y_pred&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;loss&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(self, X_batch, y_batch, reg)&lt;/span&gt;:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;pass&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;class&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;LinearSVM&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(LinearClassifier)&lt;/span&gt;:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;loss&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(self, X_batch, y_batch, reg)&lt;/span&gt;:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; svm_loss_vectorized(self.W, X_batch, y_batch, reg)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;class&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;Softmax&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(LinearClassifier)&lt;/span&gt;:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;string&quot;&gt;&quot;&quot;&quot; A subclass that uses the Softmax + Cross-entropy loss function &quot;&quot;&quot;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;loss&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(self, X_batch, y_batch, reg)&lt;/span&gt;:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; softmax_loss_vectorized(self.W, X_batch, y_batch, reg)&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;训练SVM：&lt;/p&gt;
&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;svm = LinearSVM()&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;svm.train(X_train, y_train, learning_rate=&lt;span class=&quot;number&quot;&gt;1e-3&lt;/span&gt;, reg=&lt;span class=&quot;number&quot;&gt;1e0&lt;/span&gt;, num_iters=&lt;span class=&quot;number&quot;&gt;400&lt;/span&gt;,verbose=&lt;span class=&quot;keyword&quot;&gt;True&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;y_train_pred = svm.predict(X_train)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;acc_train = np.mean(y_train == y_train_pred)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;y_val_pred = svm.predict(X_val)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;acc_val = np.mean(y_val == y_val_pred)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;y_test_pred = svm.predict(X_test)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;acc_test = np.mean(y_test == y_test_pred)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;print&lt;/span&gt; train_accuracy, val_accuracy, acc_test&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;pre&gt;&lt;code&gt;iteration 0 / 400: loss 8.953550
iteration 100 / 400: loss 0.208299
iteration 200 / 400: loss 0.287735
iteration 300 / 400: loss 0.233046
0.940448569219 0.951388888889 0.952777777778
&lt;/code&gt;&lt;/pre&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;strong&gt;W&lt;/strong&gt;的每一行可以理解为一个图像模板，每个类别的得分就是输入图片与每一行的图片模板&lt;strong&gt;内积&lt;/strong&gt;的结果，看输出的图片最符合哪个图片模板，也就是最可能符合哪一类。也就是说通过训练，分类器的每一行学习到了每类图片的模板，如下图所示，线性SVM分类器学习到的每一类数字的模板图片。&lt;/p&gt;
&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;w = svm.W[:&lt;span class=&quot;number&quot;&gt;-1&lt;/span&gt;,:] &lt;span class=&quot;comment&quot;&gt;# strip out the bias&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;#print w&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;w = w.reshape(&lt;span class=&quot;number&quot;&gt;8&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;8&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;10&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;w_min, w_max = np.min(w), np.max(w)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; i &lt;span class=&quot;keyword&quot;&gt;in&lt;/span&gt; xrange(&lt;span class=&quot;number&quot;&gt;10&lt;/span&gt;):&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  plt.subplot(&lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;5&lt;/span&gt;, i + &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;comment&quot;&gt;#Rescale the weights to be between 0 and 255&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  wimg = &lt;span class=&quot;number&quot;&gt;255.0&lt;/span&gt; * (w[:, :, i].squeeze() - w_min) / (w_max - w_min)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;comment&quot;&gt;#wimg = w[:, :, i]&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  plt.imshow(wimg.astype(&lt;span class=&quot;string&quot;&gt;&#39;uint8&#39;&lt;/span&gt;))&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  plt.axis(&lt;span class=&quot;string&quot;&gt;&#39;off&#39;&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  plt.title(classes[i])&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-6-20/94762256.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;sf = Softmax()&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;sf.train(X_train, y_train, learning_rate=&lt;span class=&quot;number&quot;&gt;1e-2&lt;/span&gt;, reg=&lt;span class=&quot;number&quot;&gt;0.5&lt;/span&gt;, num_iters=&lt;span class=&quot;number&quot;&gt;500&lt;/span&gt;,verbose=&lt;span class=&quot;keyword&quot;&gt;True&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;y_train_pred = sf.predict(X_train)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;acc_train = np.mean(y_train == y_train_pred)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;y_val_pred = sf.predict(X_val)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;acc_val = np.mean(y_val == y_val_pred)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;y_test_pred = sf.predict(X_test)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;acc_test = np.mean(y_test == y_test_pred)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;print&lt;/span&gt; train_accuracy, val_accuracy, acc_test&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;pre&gt;&lt;code&gt;iteration 0 / 500: loss 2.301230
iteration 100 / 500: loss 0.362278
iteration 200 / 500: loss 0.361298
iteration 300 / 500: loss 0.352944
iteration 400 / 500: loss 0.365702
0.940448569219 0.951388888889 0.95
&lt;/code&gt;&lt;/pre&gt;&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;w = sf.W[:&lt;span class=&quot;number&quot;&gt;-1&lt;/span&gt;,:] &lt;span class=&quot;comment&quot;&gt;# strip out the bias&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;print&lt;/span&gt; w.shape&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;w = w.reshape(&lt;span class=&quot;number&quot;&gt;8&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;8&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;10&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;w_min, w_max = np.min(w), np.max(w)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; i &lt;span class=&quot;keyword&quot;&gt;in&lt;/span&gt; xrange(&lt;span class=&quot;number&quot;&gt;10&lt;/span&gt;):&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  plt.subplot(&lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;5&lt;/span&gt;, i + &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;comment&quot;&gt;#Rescale the weights to be between 0 and 255&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  wimg = &lt;span class=&quot;number&quot;&gt;255.0&lt;/span&gt; * (w[:, :, i].squeeze() - w_min) / (w_max - w_min)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;comment&quot;&gt;#wimg = w[:, :, i]&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  plt.imshow(wimg.astype(&lt;span class=&quot;string&quot;&gt;&#39;uint8&#39;&lt;/span&gt;))&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  plt.axis(&lt;span class=&quot;string&quot;&gt;&#39;off&#39;&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  plt.title(classes[i])&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;pre&gt;&lt;code&gt;(64, 10)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-6-20/30387585.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&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;http://cs231n.github.io/&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;CS231n: Convolutional Neural Networks for Visual Recognition. &lt;/a&gt;&lt;/p&gt;
</content>
    
    <summary type="html">
    
      &lt;p&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-6-20/61070235.jpg&quot; alt=&quot;&quot;&gt;&lt;br&gt;
    
    </summary>
    
    
      <category term="SVM" scheme="http://buptldy.github.io/tags/SVM/"/>
    
      <category term="Softmax" scheme="http://buptldy.github.io/tags/Softmax/"/>
    
  </entry>
  
  <entry>
    <title>Speed-up with Cython and Numpy in Python</title>
    <link href="http://buptldy.github.io/2016/06/15/2016-06-15-Python%20Cython/"/>
    <id>http://buptldy.github.io/2016/06/15/2016-06-15-Python Cython/</id>
    <published>2016-06-15T02:00:00.000Z</published>
    <updated>2016-10-04T05:52:53.761Z</updated>
    
    <content type="html">&lt;p&gt;&lt;center&gt;&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-6-15/20612896.jpg&quot; alt=&quot;&quot;&gt;&lt;br&gt;&lt;/center&gt;&lt;br&gt;&lt;a id=&quot;more&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;Cython代码和Python代码区别&quot;&gt;&lt;a href=&quot;#Cython代码和Python代码区别&quot; class=&quot;headerlink&quot; title=&quot;Cython代码和Python代码区别&quot;&gt;&lt;/a&gt;Cython代码和Python代码区别&lt;/h2&gt;&lt;p&gt;代码运行在&lt;a href=&quot;https://ipython.org/notebook.html&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;IPython-Notebook&lt;/a&gt;中，在IPython-Notebook中导入cython环境。&lt;/p&gt;
&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;%load_ext cython&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;Cython可以在Python中掺杂C和C++的静态类型，cython编译器可以把Cython源码编译成C或C++代码，编译后的代码可以单独执行或者作为Python中的模型使用。Cython中的强大之处在于可以把Python和C结合起来，它使得看起来像Python语言的Cython代码有着和C相似的运行速度。&lt;/p&gt;
&lt;p&gt;我们使用一个简单的Fibonacci函数来比较下Python和Cython的区别：&lt;/p&gt;
&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;#python&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;fib1&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(n)&lt;/span&gt;:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    a,b=&lt;span class=&quot;number&quot;&gt;0.0&lt;/span&gt;,&lt;span class=&quot;number&quot;&gt;1.0&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; i &lt;span class=&quot;keyword&quot;&gt;in&lt;/span&gt; range(n):&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        a,b=a+b,a&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; a&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;下面代码使用&lt;code&gt;%%cython&lt;/code&gt;标志表示下面的代码使用cython编译&lt;br&gt;&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;%%cython&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;fib2&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(int n)&lt;/span&gt;:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    cdef double a=&lt;span class=&quot;number&quot;&gt;0.0&lt;/span&gt;, b=&lt;span class=&quot;number&quot;&gt;1.0&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; i &lt;span class=&quot;keyword&quot;&gt;in&lt;/span&gt; range(n):&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        a,b = a+b,a&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; a&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;通过比较上面的代码，为了把Python中的动态类型转换为Cython中的静态类型，我们用&lt;code&gt;cdef&lt;/code&gt;来定义C语言中的变量&lt;code&gt;i&lt;/code&gt;，&lt;code&gt;a&lt;/code&gt;，&lt;code&gt;b&lt;/code&gt;。&lt;br&gt;我们用C语言实现Fibonacci函数，然后通过Cython用Python封装，其中&lt;code&gt;cfib.h&lt;/code&gt;为Fibonacci函数C语言实现，如下：&lt;br&gt;&lt;figure class=&quot;highlight c&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;cfib&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(&lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; n)&lt;/span&gt; &lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;keyword&quot;&gt;int&lt;/span&gt; i;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;keyword&quot;&gt;double&lt;/span&gt; a=&lt;span class=&quot;number&quot;&gt;0.0&lt;/span&gt;, b=&lt;span class=&quot;number&quot;&gt;1.0&lt;/span&gt;, tmp;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; (i=&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;; i&amp;lt;n; ++i) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    tmp = a; a = a + b; b = tmp;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; a;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;%%cython&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;cdef extern &lt;span class=&quot;keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;&quot;/home/ldy/MEGA/python/cython/cfib.h&quot;&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    double cfib(int n)  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;fib3&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(n)&lt;/span&gt;:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;string&quot;&gt;&quot;&quot;&quot;Returns the nth Fibonacci number.&quot;&quot;&quot;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; cfib(n)&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;比较不同方法的运行时间：&lt;/p&gt;
&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;%timeit result=fib1(&lt;span class=&quot;number&quot;&gt;1000&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;%timeit result=fib2(&lt;span class=&quot;number&quot;&gt;1000&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;%timeit result=fib3(&lt;span class=&quot;number&quot;&gt;1000&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;pre&gt;&lt;code&gt;10000 loops, best of 3: 73.6 µs per loop
1000000 loops, best of 3: 1.94 µs per loop
1000000 loops, best of 3: 1.92 µs per loop
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&quot;Cython代码的编译&quot;&gt;&lt;a href=&quot;#Cython代码的编译&quot; class=&quot;headerlink&quot; title=&quot;Cython代码的编译&quot;&gt;&lt;/a&gt;Cython代码的编译&lt;/h2&gt;&lt;p&gt;Cython代码的编译为Python可调用模块的过程主要分为两步：第一步是cython编译器把Cython代码优化成C或C++代码；第二步是使用C或C++编译器编译产生的C或C++代码得到Python可调用的模块。&lt;/p&gt;
&lt;p&gt;我们通过一个&lt;code&gt;setup.py&lt;/code&gt;脚本来编译上面写的&lt;code&gt;fib.pyx&lt;/code&gt;Cython代码，如下所示，关键就在第三行，&lt;code&gt;cythonize&lt;/code&gt;函数的作用是通过cython编译器把Cython代码转换为C代码，&lt;code&gt;setup&lt;/code&gt;函数则是把产生的C代码转换成Python可调用模块。&lt;/p&gt;
&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;from&lt;/span&gt; distutils.core &lt;span class=&quot;keyword&quot;&gt;import&lt;/span&gt; setup&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;from&lt;/span&gt; Cython.Build &lt;span class=&quot;keyword&quot;&gt;import&lt;/span&gt; cythonize&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;setup(ext_modules=cythonize(&lt;span class=&quot;string&quot;&gt;&#39;fib.pyx&#39;&lt;/span&gt;))&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;#setup(ext_modules=cythonize(&#39;*.pyx&#39;,&#39;fib1.pyx&#39;))也可以一次编译多个Cython文件&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;写好&lt;code&gt;setup.py&lt;/code&gt;文件后，就可以通过下述命令执行编译：&lt;br&gt;&lt;figure class=&quot;highlight plain&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;python setup.py build_ext --inplace&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;执行后产生了&lt;code&gt;fib.c&lt;/code&gt;代码以及&lt;code&gt;fib.so&lt;/code&gt;文件，以及一些中间结果保存在build文件夹里。&lt;/p&gt;
&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;import&lt;/span&gt; os&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;os.chdir(&lt;span class=&quot;string&quot;&gt;&#39;/home/ldy/MEGA/python/cython/test&#39;&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;os.getcwd()&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;!ls&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;pre&gt;&lt;code&gt;build  fib.c  fib.pyx  fib.so  setup.py
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;通过Python调用产出的&lt;code&gt;fib.so&lt;/code&gt;模块：&lt;/p&gt;
&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;import&lt;/span&gt; fib&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;fib.fib2(&lt;span class=&quot;number&quot;&gt;90&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;pre&gt;&lt;code&gt;2.880067194370816e+18
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&quot;Cython中类型的定义&quot;&gt;&lt;a href=&quot;#Cython中类型的定义&quot; class=&quot;headerlink&quot; title=&quot;Cython中类型的定义&quot;&gt;&lt;/a&gt;Cython中类型的定义&lt;/h2&gt;&lt;p&gt;为什么Cython和Python比会提高很多性能，主要原因有两点：一是Python是解释型语言，在运行之前Python解释器把Python代码解释成Python字节码运行在Python虚拟机上，Python虚拟机把Python字节码最终翻译成CPU能执行的机器码；而Cython代码是事先直接编译成可被Python调用的机器码，在运行时可直接执行。第二个主要的原因是Python是动态类型，Python解释器在解释时需要判断类型，然后再提取出底层能够运行的数据以及操作；然而C语言等比较底层的语言是静态类型，编译器直接提取数据进行操作产生机器码。&lt;/p&gt;
&lt;p&gt;Cython中使用&lt;code&gt;cdef&lt;/code&gt;来定义静态类型：&lt;br&gt;&lt;figure class=&quot;highlight plain&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;cdef int i&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;cdef int j&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;cdef float f&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;也可以一次定义多个：&lt;br&gt;&lt;figure class=&quot;highlight plain&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;cdef:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    int i&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    int j&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    float f&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;Cython中还允许在静态类型和动态类型同时存在及相互赋值：&lt;/p&gt;
&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;%%cython&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;cdef int a=&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;,b=&lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;,c=&lt;span class=&quot;number&quot;&gt;3&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;list_of_ints=[a,b,c]&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;list_of_ints.append(&lt;span class=&quot;number&quot;&gt;4&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;a=list_of_ints[&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;]&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;print&lt;/span&gt; a,list_of_ints&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;pre&gt;&lt;code&gt;2 [1, 2, 3, 4]
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;声明Python类型为静态类型，Cython支持把一些Python内置的如&lt;code&gt;list&lt;/code&gt;,&lt;code&gt;tuple&lt;/code&gt;,&lt;code&gt;dict&lt;/code&gt;等类型声明为静态类型，这样声明使得它们能像正常Python类型一样使用，但是需要约束成只能是他们所申明的类型，不能随意变动。&lt;/p&gt;
&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;%%cython&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;cdef:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    list names&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    dict name_num&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;name_num=&amp;#123;&lt;span class=&quot;string&quot;&gt;&#39;jerry&#39;&lt;/span&gt;:&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;,&lt;span class=&quot;string&quot;&gt;&#39;Tom&#39;&lt;/span&gt;:&lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;,&lt;span class=&quot;string&quot;&gt;&#39;Bell&#39;&lt;/span&gt;:&lt;span class=&quot;number&quot;&gt;3&lt;/span&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;names=list(name_num.keys())&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;print&lt;/span&gt; names&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;other_names=names&lt;span class=&quot;comment&quot;&gt;#动态类型可以从静态类型的Python对象初始化&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;del&lt;/span&gt; other_names[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;]&lt;span class=&quot;comment&quot;&gt;#因为引用了同一个list，所以都会删除第一个元素&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;print&lt;/span&gt; names,other_names&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;other_names=tuple(other_names)&lt;span class=&quot;comment&quot;&gt;#names和other_names的区别在于names只能是list类型，&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;print&lt;/span&gt; other_names           &lt;span class=&quot;comment&quot;&gt;#other_names可以引用任何类型&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;pre&gt;&lt;code&gt;[&amp;apos;Bell&amp;apos;, &amp;apos;jerry&amp;apos;, &amp;apos;Tom&amp;apos;]
[&amp;apos;jerry&amp;apos;, &amp;apos;Tom&amp;apos;] [&amp;apos;jerry&amp;apos;, &amp;apos;Tom&amp;apos;]
(&amp;apos;jerry&amp;apos;, &amp;apos;Tom&amp;apos;)
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&quot;Cython中numpy的使用&quot;&gt;&lt;a href=&quot;#Cython中numpy的使用&quot; class=&quot;headerlink&quot; title=&quot;Cython中numpy的使用&quot;&gt;&lt;/a&gt;Cython中numpy的使用&lt;/h2&gt;&lt;p&gt;我们先构造一个函数来测试下使用纯Python时的运算时间来做对比，这个函数的作用是对一副输入图像求梯度（不必过分关注函数的功能，在这只是使用这个函数作为测试）。函数的输入数据是&lt;code&gt;indata&lt;/code&gt;一个像素为1400*1600的图片；输出为&lt;code&gt;outdata&lt;/code&gt;,为每个像素梯度值，下面是这个函数的纯Python实现：&lt;/p&gt;
&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;import&lt;/span&gt; numpy &lt;span class=&quot;keyword&quot;&gt;as&lt;/span&gt; np&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;indata = np.random.rand(&lt;span class=&quot;number&quot;&gt;1400&lt;/span&gt;,&lt;span class=&quot;number&quot;&gt;1600&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;outdata = np.zeros(shape=indata.shape, dtype=&lt;span class=&quot;string&quot;&gt;&#39;float64&#39;&lt;/span&gt;)  &lt;span class=&quot;comment&quot;&gt;# eventually holds our output&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;from&lt;/span&gt; numpy.lib &lt;span class=&quot;keyword&quot;&gt;import&lt;/span&gt; pad&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;print(&lt;span class=&quot;string&quot;&gt;&quot;shape before&quot;&lt;/span&gt;, indata.shape)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;indata = pad(indata, (&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;), &lt;span class=&quot;string&quot;&gt;&#39;reflect&#39;&lt;/span&gt;, reflect_type=&lt;span class=&quot;string&quot;&gt;&#39;odd&#39;&lt;/span&gt;)  &lt;span class=&quot;comment&quot;&gt;# allow edge calcs&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;print(&lt;span class=&quot;string&quot;&gt;&quot;shape after&quot;&lt;/span&gt;, indata.shape)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;import&lt;/span&gt; math&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;slope&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(indata, outdata)&lt;/span&gt;:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    I = outdata.shape[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;]&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    J = outdata.shape[&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;]&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; i &lt;span class=&quot;keyword&quot;&gt;in&lt;/span&gt; range(I):&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; j &lt;span class=&quot;keyword&quot;&gt;in&lt;/span&gt; range(J):&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;# percent slope using Zevenbergen-Thorne method&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;comment&quot;&gt;# assume edges added, inarr is offset by one on both axes cmp to outarr&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            dzdx = (indata[i+&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;, j] - indata[i+&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;, j+&lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;]) / &lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;  &lt;span class=&quot;comment&quot;&gt;# assume cellsize == one unit, otherwise (2 * cellsize)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            dzdy = (indata[i, j+&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;] - indata[i+&lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;, j+&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;]) / &lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            slp = math.sqrt((dzdx * dzdx) + (dzdy * dzdy)) * &lt;span class=&quot;number&quot;&gt;100&lt;/span&gt;  &lt;span class=&quot;comment&quot;&gt;# percent slope (take math.atan to get angle)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            outdata[i, j] = slp&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;pre&gt;&lt;code&gt;(&amp;apos;shape before&amp;apos;, (1400, 1600))
(&amp;apos;shape after&amp;apos;, (1402, 1602))
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;测试运行时间，为5.31 s每个循环&lt;/p&gt;
&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;%timeit slope(indata, outdata)&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;pre&gt;&lt;code&gt;1 loop, best of 3: 5.31 s per loop
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;重置输出：&lt;/p&gt;
&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;reset_outdata&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;()&lt;/span&gt;:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    outdata = np.zeros(shape=indata.shape, dtype=&lt;span class=&quot;string&quot;&gt;&#39;float64&#39;&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;reset_outdata()&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;使用Cython重写求图像梯度函数,其中函数&lt;code&gt;slope_cython2&lt;/code&gt;使用Cython里的numpy类型，并重写了里面的开方函数，其中&lt;code&gt;%%cython -a&lt;/code&gt;表示使用cython编译Cython代码，并可以对照显示编译器把Cython代码编译成的C代码。&lt;/p&gt;
&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;%%cython&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;import&lt;/span&gt; cython&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;cimport numpy &lt;span class=&quot;keyword&quot;&gt;as&lt;/span&gt; np&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;ctypedef np.float64_t DTYPE_t&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;@cython.boundscheck(False)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;slope_cython2&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(np.ndarray[DTYPE_t, ndim=&lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;] indata, np.ndarray[DTYPE_t, ndim=&lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;] outdata)&lt;/span&gt;:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    cdef int I, J&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    cdef int i, j, x&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    cdef double k, slp, dzdx, dzdy&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    I = outdata.shape[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;]&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    J = outdata.shape[&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;]&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; i &lt;span class=&quot;keyword&quot;&gt;in&lt;/span&gt; range(I):&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; j &lt;span class=&quot;keyword&quot;&gt;in&lt;/span&gt; range(J):&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            dzdx = (indata[i+&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;, j] - indata[i+&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;, j+&lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;]) / &lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            dzdy = (indata[i, j+&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;] - indata[i+&lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;, j+&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;]) / &lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            k = (dzdx * dzdx) + (dzdy * dzdy)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            slp = k**&lt;span class=&quot;number&quot;&gt;0.5&lt;/span&gt; * &lt;span class=&quot;number&quot;&gt;100&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            outdata[i, j] = slp&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;测试运行时间：208ms,快了有25倍左右&lt;/p&gt;
&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;%timeit slope_cython2(indata, outdata)&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;pre&gt;&lt;code&gt;1 loop, best of 3: 208 ms per loop
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&quot;Cython中多进程&quot;&gt;&lt;a href=&quot;#Cython中多进程&quot; class=&quot;headerlink&quot; title=&quot;Cython中多进程&quot;&gt;&lt;/a&gt;Cython中多进程&lt;/h2&gt;&lt;p&gt;Cython还支持&lt;a href=&quot;http://docs.cython.org/src/userguide/parallelism.html&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;并行运算&lt;/a&gt;,后台由OpenMP支持，所以在编译Cython语言时需要加上如下代码第一行所示的标记。在进行并行计算时，需使用&lt;code&gt;nogil&lt;/code&gt;关键词来释放Python里的&lt;a href=&quot;https://wiki.python.org/moin/GlobalInterpreterLock&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;GIL&lt;/a&gt;锁,当代码中只有C而没有Python对象时，这样做是安全的。&lt;/p&gt;
&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;%%cython --compile-args=-fopenmp --link-args=-fopenmp --force&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;import&lt;/span&gt; cython&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;from&lt;/span&gt; cython.parallel &lt;span class=&quot;keyword&quot;&gt;import&lt;/span&gt; prange, parallel&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;@cython.boundscheck(False)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;slope_cython_openmp&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(double [:, :] indata, double [:, :] outdata)&lt;/span&gt;:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    cdef int I, J&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    cdef int i, j, x&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    cdef double k, slp, dzdx, dzdy&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    I = outdata.shape[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;]&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    J = outdata.shape[&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;]&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;with&lt;/span&gt; nogil, parallel(num_threads=&lt;span class=&quot;number&quot;&gt;4&lt;/span&gt;):&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; i &lt;span class=&quot;keyword&quot;&gt;in&lt;/span&gt; prange(I, schedule=&lt;span class=&quot;string&quot;&gt;&#39;dynamic&#39;&lt;/span&gt;):&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; j &lt;span class=&quot;keyword&quot;&gt;in&lt;/span&gt; range(J):&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                dzdx = (indata[i+&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;, j] - indata[i+&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;, j+&lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;]) / &lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                dzdy = (indata[i, j+&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;] - indata[i+&lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;, j+&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;]) / &lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                k = (dzdx * dzdx) + (dzdy * dzdy)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                slp = k**&lt;span class=&quot;number&quot;&gt;0.5&lt;/span&gt; * &lt;span class=&quot;number&quot;&gt;100&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                outdata[i, j] = slp&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;reset_outdata()&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;%timeit slope_cython_openmp(indata, outdata)&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;pre&gt;&lt;code&gt;10 loops, best of 3: 78.2 ms per loop
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;测试的时间如上所示，多进程大概快了2.7倍左右。&lt;/p&gt;
</content>
    
    <summary type="html">
    
      &lt;p&gt;&lt;center&gt;&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-6-15/20612896.jpg&quot; alt=&quot;&quot;&gt;&lt;br&gt;&lt;/center&gt;&lt;br&gt;
    
    </summary>
    
    
      <category term="Python" scheme="http://buptldy.github.io/tags/Python/"/>
    
      <category term="Cython" scheme="http://buptldy.github.io/tags/Cython/"/>
    
  </entry>
  
  <entry>
    <title>Classification in Remote Sensing Optical Images by CNNs</title>
    <link href="http://buptldy.github.io/2016/06/12/2016-06-12-CNN%20Remote%20Sensing%20Optical%20Images/"/>
    <id>http://buptldy.github.io/2016/06/12/2016-06-12-CNN Remote Sensing Optical Images/</id>
    <published>2016-06-12T02:00:00.000Z</published>
    <updated>2016-10-04T05:50:48.736Z</updated>
    
    <content type="html">&lt;p&gt;&lt;center&gt;&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-6-11/17213122.jpg&quot; alt=&quot;&quot;&gt;&lt;br&gt;&lt;/center&gt;&lt;br&gt;&lt;a id=&quot;more&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;CNN简介&quot;&gt;&lt;a href=&quot;#CNN简介&quot; class=&quot;headerlink&quot; title=&quot;CNN简介&quot;&gt;&lt;/a&gt;CNN简介&lt;/h2&gt;&lt;p&gt;从06年开始，深度结构学习方法（深度学习或者分层学习方法）作为机器学习领域的新的研究方向出现。由于芯片处理性能的巨大提升，数据爆炸性增长，在过去的短短几年时间，深度学习技术得到快速发展，已经深深的影响了学术领域，其研究涉及的应用领域包括计算机视觉、语音识别、对话语音识别、图像特征编码、语意表达分类、自然语言理解、手写识别、音频处理、信息检索、机器人学。&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-5-22/96930177.jpg&quot; alt=&quot;&quot;&gt;&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-5-22/75458021.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;由于深度学习在众多领域表现比较好的性能，越来越多的学术机构把目光投入深度学习领域。今年来活跃在机器学习领域的研究机构包括众多高校比如斯坦福，伯克利，还有一些企业例如Google，IBM 研究院，微软研究院，FaceBook，百度等等。&lt;/p&gt;
&lt;h3 id=&quot;神经网络&quot;&gt;&lt;a href=&quot;#神经网络&quot; class=&quot;headerlink&quot; title=&quot;神经网络&quot;&gt;&lt;/a&gt;神经网络&lt;/h3&gt;&lt;p&gt;人工神经网络是一种模仿生物神经网络(动物的中枢神经系统，特别是大脑)的结构和功能的数学模型或计算模型，简单结构如下图所示，包含了输入层，隐含层，和输出层，其中隐含层可能有多层。在神经网络中每个神经元都和它前一层的所有节点相连接，称之为全连接，其中每个连接以一定的权值相连接，&lt;strong&gt;网络训练的过程就是得到权值的过程&lt;/strong&gt;。&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-5-22/86340649.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;不管是机器学习还是深度学习实际上都是在解决分类问题，当数据线性可分时，一个sigmoid函数就可以把数据分开，如下图所示，其中两类数据是线性可分的，我们只需要神经网络的输入和输出层就可以把两类数据分开，其中黄色的连线表示权值为负，蓝色的连线表示权值为正，连线的粗细表示权值的绝对值大小。&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-5-22/47661239.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;如下图，当原本的数据不可分时，我们就需要对数据进行一些非线性的变化，使得数据可分，而神经网络中的隐含层的作用就是对线性不可分的数据进行非线性变化，下图中包含了4个隐含层节点，数据被正确的分类。&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-5-22/28174683.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;卷积神经网络-CNN&quot;&gt;&lt;a href=&quot;#卷积神经网络-CNN&quot; class=&quot;headerlink&quot; title=&quot;卷积神经网络(CNN)&quot;&gt;&lt;/a&gt;卷积神经网络(CNN)&lt;/h3&gt;&lt;p&gt;一维的CNN如下所示，和人工神经网络相比，CNN中的卷积层只与前一层节点的部分节点相连，称为局部连接，且卷积层中的每个神经元的权值相等，这一属性称为权值共享。卷积神经网络为什么有卷积两个字，就是因为这两个属性：局部连接，权值相等，具体原因可参考&lt;a href=&quot;http://colah.github.io/posts/2014-07-Understanding-Convolutions/&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;http://colah.github.io/posts/2014-07-Understanding-Convolutions/&lt;/a&gt;。下图中的max层成为池化层(pooling),下图为max pooling ，就是对两个神经元的输出取其中的较大值。池化操作能够降低特征的维度(相比使用所有提取得到的特征)，同时还会改善结果(不容易过拟合)，池化单元也具有一定的平移不变性。下图中的B层为第二层卷积层卷积层，F层为全连接层，也就是上面所说的人工神经网络。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-5-22/35987179.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;二维卷积神经网络如下所示，二维数据的输入可以看成是一张图像的每个像素值，&lt;strong&gt;卷积层看做是一个滤波器对图像提取特征&lt;/strong&gt;，max pooling层相当于对图像进行更高维的抽象，然后后面连接全连接层(也就是传统的人工神经网络)进行分类。所以总的说来，利用CNN进行图像处理就是前面的卷积层对图像进行特征提取，经过学习提取出利于图像分类的特征，然后对提取出的特征利用人工神经网络进行分类。&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-5-22/1408005.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;训练&lt;/strong&gt;：上面说到了网络训练的过程就是得到权值的过程，我们在开始训练之前网络的权值是随机初始化的，也就是我们的图片滤波器是随机初始化的。比如我们输入一张图片，随机初始化的CNN分类告诉我们有6%的可能是一个&lt;code&gt;网球场&lt;/code&gt;，但实际上我们告诉CNN这是一个&lt;code&gt;飞机场&lt;/code&gt;，然后其中会有一个&lt;a href=&quot;https://zh.wikipedia.org/wiki/%E5%8F%8D%E5%90%91%E4%BC%A0%E6%92%AD%E7%AE%97%E6%B3%95&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;反向传播&lt;/a&gt;的处理过程来稍稍改变滤波器的参数以便它下次碰到相同的图片时会更可能的预测为&lt;code&gt;网球场&lt;/code&gt;。然后我们对我们的训练数据重复这一过程，CNN里的滤波器会逐渐的调整到能够提取我们图片里的供我们分类的重要特征。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-7-8/73324267.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&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;UC Merced Land Use数据集包含21类土地类型，每类图像为100张，每张图像的像素为256*256。&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-5-22/46888988.jpg&quot; alt=&quot;&quot;&gt;&lt;br&gt;数据集特点，数据集比较小，每一类只有100张图片，这个数据集还有其他的一些特点比如类间距离小，如下图所示，不同类的图片之间很相似。&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-5-23/95817534.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;类内距离大，同类图片之间差别较大，如下图所示：&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-5-23/31732082.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;这些特点都是不利于图片的分类的，尤其是数据量太小，如果从头开始用数据集来训练网络肯定会造成严重的过拟合。考虑到这种情况，一个解决方法就是使用训练好的网络进行微调以适应我们自己的数据集，这种方法不仅能解决数据集小的问题，也能大大加快训练的速度。&lt;/p&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;网络微调就是使用事先已经训练好的网络，对网络进行微小的改造再训练以适用与我们自己的数据库。为什么别人训练好的网络，我们自己拿到改改就能使用呢？就像之前所说的，CNN的卷积层是用来提取图像的特征的，事实上图片的线条一级色彩纹理大致上是一样的，也就是说一个训练好CNN网络的卷积层也可以用来提取其他数据集图像的特征，因为图像的特征基本相似。特别的，能够使用网络微调的一个重要因素是使用的事先训练好的网络使用的数据集要和我们自己的训练集图像之间的‘距离’要比较小。因为我们的数据集是光学遥感图像，所以和我们的光学图像在底层上的特征有非常强的相似性。&lt;/p&gt;
&lt;p&gt;下图是Imagenet数据集的部分图片，也是我们要使用的预先训练好的所用网络的数据集。&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-5-23/54435346.jpg&quot; alt=&quot;&quot;&gt;&lt;br&gt;基于遥感SAR图像每个像素级别的统计特性，这种用光学图像训练好的网络微调的方法是不适用与SAR图像分类的。SAR图像如下所示，直观上看也与光学图像差别很大。&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-5-23/59029562.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;我们选择Caffe里预先使用Imagnet训练好的CaffeNet网络来经行微调，CaffeNet网络结构如下所示，fc6前为CNN中的卷积层用来提取图像特征，f6、fc7、fc8为全连接层(可以看成是人工神经网络的输入层，隐含层，输出层)，因为CaffeNet网络是用来分类1000类的图像的，所以最后一层有1000个神经元。&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-5-23/63655708.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;而我们的数据集是分开21类的图像，所以微调网络中的调整主要就体现在这里，修改上述网络以使用我们自己的数据集，如下所示，只要把网络的输出层改为21个神经元即可。&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-5-23/18035393.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;我们说的要使用要使用预先训练好的网络就是要使用它事先训练好的权值，比较上述两个网络，只有最后一层不同，所以它们的其他层的权值的维数都是相同的，所以我们把CaffeNet训练好的权值直接用在我们自己定义的网络上，最后一层的权值则随机初始化并设置较大的学习速率，然后就可以用我们定义好的网络训练我们自己的数据集。&lt;/p&gt;
&lt;p&gt;定义好网络之后就可以开始训练了，把数据集按4:1分为训练集和测试集，在测试集上的预测准确率在92%左右。&lt;/p&gt;
&lt;p&gt;还有一种常用的方法是不用CNN的最后一层分类，用CNN提取到的特征用SVM来分类，也能达到不错的效果。在这里我们提取fc7层输出的特征，根据上面定义的网络结构，fc7层共有4096个神经元，所以每张图片的特征维数为4096维，维数比较大，所以我们使用SVM的线性核即可达到分类效果。&lt;/p&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;fine-turning结果展示：&lt;br&gt;其中对预测结果做了一些可视化展示，左图表示为预测前五类的概率，左右为图片真实的类别。&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-5-23/60490439.jpg&quot; alt=&quot;&quot;&gt;&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-5-23/91330851.jpg&quot; alt=&quot;&quot;&gt;&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-5-23/20682353.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;CNN提取特征，SVM分类结果展示：&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-5-23/64622617.jpg&quot; alt=&quot;&quot;&gt;&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-5-23/23497392.jpg&quot; alt=&quot;&quot;&gt;&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-5-23/62208562.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;从两种方法中可以看出，虽然都分类正确了，但用SVM作为分类器的正确分类的概率更高。&lt;/p&gt;
&lt;p&gt;fine-turning方法每个类别的准确率：&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-5-23/23347725.jpg&quot; alt=&quot;&quot;&gt;&lt;br&gt;从上图中我们可以看出，tenniscount类别的预测准确率最低，我们来看看有哪些tenniscount类是预测错了的：&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-5-23/83947048.jpg&quot; alt=&quot;&quot;&gt;&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-5-23/49629661.jpg&quot; alt=&quot;&quot;&gt;&lt;br&gt;从上面两个图片中可以看出，其实并不能说是预测错误，因为上面两张图中既包含了tenniscount类和CNN预测的类别，可以说本来就是有两个类。&lt;/p&gt;
&lt;h3 id=&quot;t-sne特征降维可视化&quot;&gt;&lt;a href=&quot;#t-sne特征降维可视化&quot; class=&quot;headerlink&quot; title=&quot;t-sne特征降维可视化&quot;&gt;&lt;/a&gt;t-sne特征降维可视化&lt;/h3&gt;&lt;p&gt;对CNN中第七层提取到的4096维特征经行降维可视化，从下图可以看出，分类准备率比较低的类别靠的都比较紧密，难以区分。&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-7-8/84288255.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;CNN+SVM每个类别的准确率：&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-5-23/97608126.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;CNN中间层可视化&quot;&gt;&lt;a href=&quot;#CNN中间层可视化&quot; class=&quot;headerlink&quot; title=&quot;CNN中间层可视化&quot;&gt;&lt;/a&gt;CNN中间层可视化&lt;/h2&gt;&lt;p&gt;神经网络不仅仅是一个黑盒子，我们可以查看一些中间结果和参数。上面我们也说了一个卷积层就相当与一个图像滤波器，在上面的网络的第一层的卷积层中我们定义了96个滤波器，96个滤波器可视化如下图所示，学过图像处理的同学都知道，下图中第一个滤波器是提取斜向下的边缘特征，第二个滤波器是提取斜向上的边缘特征，前面的滤波器大多数是在提取边缘特征，后面的大多是在统计颜色特征。&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-5-23/15829905.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;我们输入一张图片，并输出其经过第一层卷积层滤波器滤波后的输出：&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-5-23/12013586.jpg&quot; alt=&quot;&quot;&gt;&lt;br&gt;从第一层滤波后的结果可以看出，前面两个滤波器就是在显示斜向下和斜向上的边缘。&lt;/p&gt;
&lt;p&gt;第五层卷积层滤波器输出如下图所示，高层的滤波器输出比较抽象。&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-5-23/58707834.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&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;当我们数据集不够的时候可以使用微调的方法，探索CNN怎么应用于SAR图像分类，解决图片类标签的分类问题。&lt;/p&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://github.com/BUPTLdy/Land_Use_CNN&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;land_use_CNN&lt;/a&gt;&lt;/p&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;http://vision.ucmerced.edu/datasets/landuse.html&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;http://vision.ucmerced.edu/datasets/landuse.html&lt;/a&gt;&lt;br&gt;&lt;a href=&quot;http://ufldl.stanford.edu/wiki/index.php/%E6%B1%A0%E5%8C%96&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;http://ufldl.stanford.edu/wiki/index.php/%E6%B1%A0%E5%8C%96&lt;/a&gt;&lt;br&gt;&lt;a href=&quot;http://colah.github.io/posts/2014-07-Conv-Nets-Modular/&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;http://colah.github.io/posts/2014-07-Conv-Nets-Modular/&lt;/a&gt;&lt;br&gt;&lt;a href=&quot;http://playground.tensorflow.org/#activation=tanh&amp;amp;batchSize=10&amp;amp;dataset=xor&amp;amp;regDataset=reg-plane&amp;amp;learningRate=0.03&amp;amp;regularizationRate=0&amp;amp;noise=0&amp;amp;networkShape=4&amp;amp;seed=0.38108&amp;amp;showTestData=false&amp;amp;discretize=false&amp;amp;percTrainData=50&amp;amp;x=true&amp;amp;y=true&amp;amp;xTimesY=false&amp;amp;xSquared=false&amp;amp;ySquared=false&amp;amp;cosX=false&amp;amp;sinX=false&amp;amp;cosY=false&amp;amp;sinY=false&amp;amp;collectStats=false&amp;amp;problem=classification&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;Tinker With a Neural Network Right Here in Your Browser&lt;/a&gt;&lt;/p&gt;
</content>
    
    <summary type="html">
    
      &lt;p&gt;&lt;center&gt;&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-6-11/17213122.jpg&quot; alt=&quot;&quot;&gt;&lt;br&gt;&lt;/center&gt;&lt;br&gt;
    
    </summary>
    
    
      <category term="Deep Learning" scheme="http://buptldy.github.io/tags/Deep-Learning/"/>
    
      <category term="CNN" scheme="http://buptldy.github.io/tags/CNN/"/>
    
  </entry>
  
  <entry>
    <title>Force-Directed Graph Visualization Based in Location</title>
    <link href="http://buptldy.github.io/2016/06/11/2016-06-11-Force-directed/"/>
    <id>http://buptldy.github.io/2016/06/11/2016-06-11-Force-directed/</id>
    <published>2016-06-11T02:00:00.000Z</published>
    <updated>2016-10-04T05:45:31.767Z</updated>
    
    <content type="html">&lt;p&gt;&lt;center&gt;&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-6-11/65263838.jpg&quot; alt=&quot;&quot;&gt;&lt;br&gt;&lt;/center&gt;&lt;br&gt;&lt;a id=&quot;more&quot;&gt;&lt;/a&gt;&lt;/p&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;图是表现社交网络、知识图谱等关系的主要形式，对图的节点进行布局是图可视化的重要内容。然而，现有方法大多在布局时没有考虑节点地理位置对布局的约束。比如在POI点评应用中，我们希望一个“餐厅”节点出现在它实际的地理位置上，或者在热点事件应用中，希望“北京”节点出现在“上海”节点的北方（上方）。在布局中加入地理位置约束，能够使图的可视化结果更好的与位置关联，包含地理信息相关隐喻，在增加其承载信息量的同时，更好的辅助地理空间数据的可视分析。&lt;br&gt;任务1：调研图可视化中节点布局相关方法，特别是力引导方法和二分图布局方法，形成小综述；&lt;br&gt;任务2：将二分图中一类节点加入绝对地理位置或彼此间相对位置不变作为约束条件，改进一种基于力引导布局的二分图可视化方法，给出模型、公式、算法流程描述；&lt;br&gt;任务3：基于给定数据集（两类节点，一类节点包含地理坐标），选择一种可视化工具（如VTK、D3等），对上述改进算法进行实现。&lt;/p&gt;
&lt;p&gt;数据集形式如下所示：&lt;/p&gt;
&lt;p&gt;文件PlaceTolation.txt内容如下，分别为地名和经纬度&lt;br&gt;&lt;figure class=&quot;highlight plain&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;地名	纬度,经度&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;北京	39.90,116.40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;北京市	39.90,116.40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;北京站	39.90,116.40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;北京路	39.90,116.40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;天安门	39.90,116.38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;崇文	39.88,116.43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;崇文区	39.88,116.43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;......&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;文件TitlePlace.txt内容如下,分别为序号,新闻标题和从该新闻中抽取出来的地名实体&lt;br&gt;&lt;figure class=&quot;highlight plain&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1	落马高官忏悔：从未感觉到还有党组织存在	中国&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2	佩帅：442阵型没问题对方进球很无解不怪门将	利物浦,切尔西&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3	今日数据趣谈：半场20+命中率8成5小加变大加	北京,德安,奎尔,孟菲斯&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4	工业领域控煤计划将出台：2020年力争节煤1.6亿吨	北京,河北,山西&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5	公交乘客与司机扭打发生车祸致1人重伤(图)	呼和浩特,呼和浩特市,青城,内蒙古,赛罕区,青洲&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6	深圳机场行人围观飞机起降被撞倒已致5死24伤	深圳&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7	云南临沧发生3.5级地震震源深度14千米	中国,云南省,临沧市,沧源佤族自治县,云南&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;......&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;需要构建的二分图中两类节点分别为新闻标题和地名，节点间的关系为标题和地名的映射关系（多对多的），其中地名节点具有经纬度属性。&lt;/p&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;/p&gt;
&lt;p&gt;要想判读每个地名所属的省市，那我们就需要每个省市的经纬度范围，在网上找到的中国地图的&lt;a href=&quot;http://www.ourd3js.com/demo/rm/R-10.0/china.geojson&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;JSON&lt;/a&gt;文件,其中包含了每个省边界的经纬度值，为一系列的点，判断某个地点属于哪一个省实际上就是根据地点的经纬度判断这一点是否在某所有省边界点围成的多边形里，也就是一个&lt;a href=&quot;https://en.wikipedia.org/wiki/Point_in_polygon&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;Point in Polygon&lt;/a&gt;问题。&lt;/p&gt;
&lt;p&gt;Python matplotlib包中的Path提供了相应的函数：&lt;br&gt;&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;import&lt;/span&gt; matplotlib.path &lt;span class=&quot;keyword&quot;&gt;as&lt;/span&gt; mplPath&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;bbPath = mplPath.Path(np.array([[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;,&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;],[&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;,&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;],[&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;,&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;],[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;,&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;]]))&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;bbPath.contains_point((&lt;span class=&quot;number&quot;&gt;0.5&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;0.5&lt;/span&gt;))&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&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;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-5-22/7813444.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;力导向图（Force-Directed Graph），是绘图的一种算法。在二维或三维空间里配置节点，节点之间用线连接，称为连线。各连线的长度几乎相等，且尽可能不相交。节点和连线都被施加了力的作用，力是根据节点和连线的相对位置计算的。根据力的作用，来计算节点和连线的运动轨迹，并不断降低它们的能量，最终达到一种能量很低的安定状态。力导向图能表示节点之间的多对多的关系。&lt;/p&gt;
&lt;p&gt;d3.layout.force()包含了力导向算法的实现，其主要参数为：&lt;/p&gt;
&lt;p&gt;d3.layout.force - 使用物理模拟排放链接节点的位置。&lt;br&gt;force.alpha - 取得或者设置力布局的冷却参数。&lt;br&gt;force.chargeDistance - 取得或者设置最大电荷距离。&lt;br&gt;force.charge - 取得或者设置电荷强度。&lt;br&gt;force.drag - 给节点绑定拖动行为。&lt;br&gt;force.friction - 取得或者设置摩擦系数。&lt;br&gt;force.gravity - 取得或者设置重力强度。&lt;br&gt;force.linkDistance - 取得或者设置链接距离。&lt;br&gt;force.linkStrength - 取得或者设置链接强度。&lt;br&gt;force.links - 取得或者设置节点间的链接数组。&lt;br&gt;force.nodes - 取得或者设置布局的节点数组。&lt;br&gt;force.on - 监听在计算布局位置时的更新。&lt;br&gt;force.resume - 重新加热冷却参数，并重启模拟。&lt;br&gt;force.size - 取得或者设置布局大小。&lt;br&gt;force.start - 当节点变化时启动或者重启模拟。&lt;br&gt;force.stop - 立即停止模拟。&lt;br&gt;force.theta - 取得或者设置电荷作用的精度。&lt;br&gt;force.tick - 运行布局模拟的一步。&lt;/p&gt;
&lt;p&gt;关于d3.layout.force()的使用可参考&lt;a href=&quot;http://www.ourd3js.com/wordpress/?p=196&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;力导向图的制作&lt;/a&gt;&lt;/p&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;br&gt;&lt;figure class=&quot;highlight javascript&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;var&lt;/span&gt; nodes = [&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;              &amp;#123;name:&lt;span class=&quot;string&quot;&gt;&quot;青海&quot;&lt;/span&gt;,x:青海[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;],y:青海[&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;],fixed:&lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;,&lt;span class=&quot;string&quot;&gt;&quot;group&quot;&lt;/span&gt;:&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;&amp;#125;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;              &amp;#123;name:&lt;span class=&quot;string&quot;&gt;&quot;河南&quot;&lt;/span&gt;,x:河南[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;],y:河南[&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;],fixed:&lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;,&lt;span class=&quot;string&quot;&gt;&quot;group&quot;&lt;/span&gt;:&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;&amp;#125;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;              &amp;#123;name:&lt;span class=&quot;string&quot;&gt;&quot;山东&quot;&lt;/span&gt;,x:山东[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;],y:山东[&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;],fixed:&lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;,&lt;span class=&quot;string&quot;&gt;&quot;group&quot;&lt;/span&gt;:&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;&amp;#125;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;              .&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;              .&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;              .&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;              &amp;#123;name:&lt;span class=&quot;string&quot;&gt;&quot;从WCBA争冠到无缘新赛季浙江女篮怎么了&quot;&lt;/span&gt;,fixed:&lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;,&lt;span class=&quot;string&quot;&gt;&quot;group&quot;&lt;/span&gt;:&lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;&amp;#125;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;              &amp;#123;name:&lt;span class=&quot;string&quot;&gt;&quot;成都的哥:专车司机玩着跑半个月超过我月收入&quot;&lt;/span&gt;,fixed:&lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;,&lt;span class=&quot;string&quot;&gt;&quot;group&quot;&lt;/span&gt;:&lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;&amp;#125;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;              &amp;#123;name:&lt;span class=&quot;string&quot;&gt;&quot;部分农村教师月薪不到2千暑假当小工补贴家用&quot;&lt;/span&gt;,fixed:&lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;,&lt;span class=&quot;string&quot;&gt;&quot;group&quot;&lt;/span&gt;:&lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                ];&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;其中第一类节点为固定地点节点，第二类节点为新闻节点，使用力导向算法计算节点的位置。所以我们需要提供地点节点的位置，在定义节点之前，加上地点经纬度：&lt;br&gt;&lt;figure class=&quot;highlight javascript&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;var&lt;/span&gt; 青海 =[&lt;span class=&quot;number&quot;&gt;96.5122866869&lt;/span&gt;,&lt;span class=&quot;number&quot;&gt;35.12781926&lt;/span&gt;];&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;var&lt;/span&gt; 河南 =[&lt;span class=&quot;number&quot;&gt;114.130772484&lt;/span&gt;,&lt;span class=&quot;number&quot;&gt;34.00715756&lt;/span&gt;];&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;var&lt;/span&gt; 山东 =[&lt;span class=&quot;number&quot;&gt;118.354817653&lt;/span&gt;,&lt;span class=&quot;number&quot;&gt;36.2612648184&lt;/span&gt;];&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;.&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;接下来是连线之间的定义，某一新闻里包含哪几个地点，则这几个地点就和这个新闻之间连一条线，其中0表示上面定义的第一个节点,185表示第186个节点。&lt;br&gt;&lt;figure class=&quot;highlight javascript&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;var&lt;/span&gt; edges = [&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &amp;#123;source:&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;,target:&lt;span class=&quot;number&quot;&gt;185&lt;/span&gt;&amp;#125;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &amp;#123;source:&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;,target:&lt;span class=&quot;number&quot;&gt;204&lt;/span&gt;&amp;#125;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &amp;#123;source:&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;,target:&lt;span class=&quot;number&quot;&gt;389&lt;/span&gt;&amp;#125;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &amp;#123;source:&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;,target:&lt;span class=&quot;number&quot;&gt;430&lt;/span&gt;&amp;#125;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &amp;#123;source:&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;,target:&lt;span class=&quot;number&quot;&gt;494&lt;/span&gt;&amp;#125;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &amp;#123;source:&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;,target:&lt;span class=&quot;number&quot;&gt;42&lt;/span&gt;&amp;#125;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                .&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                .&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                .&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;              ]&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;定义好数据之后，就可以开始布局了&lt;/p&gt;
&lt;p&gt;定义一个力导向图的布局如下。&lt;/p&gt;
&lt;figure class=&quot;highlight javascript&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;var&lt;/span&gt; force = d3.layout.force()&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      .nodes(nodes) &lt;span class=&quot;comment&quot;&gt;//指定节点数组&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      .links(edges) &lt;span class=&quot;comment&quot;&gt;//指定连线数组&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      .size([width,height]) &lt;span class=&quot;comment&quot;&gt;//指定作用域范围&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      .linkDistance(&lt;span class=&quot;number&quot;&gt;150&lt;/span&gt;) &lt;span class=&quot;comment&quot;&gt;//指定连线长度&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      .charge([&lt;span class=&quot;number&quot;&gt;-400&lt;/span&gt;]); &lt;span class=&quot;comment&quot;&gt;//相互之间的作用力&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;然后，使力学作用生效：&lt;/p&gt;
&lt;figure class=&quot;highlight javascript&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;force.start();    &lt;span class=&quot;comment&quot;&gt;//开始作用&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&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;/p&gt;
&lt;p&gt;分别绘制三种图形元素：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;line，线段，表示连线。&lt;/li&gt;
&lt;li&gt;circle，圆，表示节点。&lt;/li&gt;
&lt;li&gt;text，文字，描述节点。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;代码如下：&lt;/p&gt;
&lt;figure class=&quot;highlight javascript&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;//添加连线&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;span class=&quot;keyword&quot;&gt;var&lt;/span&gt; svg_edges = svg.selectAll(&lt;span class=&quot;string&quot;&gt;&quot;line&quot;&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     .data(edges)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     .enter()&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     .append(&lt;span class=&quot;string&quot;&gt;&quot;line&quot;&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     .style(&lt;span class=&quot;string&quot;&gt;&quot;stroke&quot;&lt;/span&gt;,&lt;span class=&quot;string&quot;&gt;&quot;#ccc&quot;&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     .style(&lt;span class=&quot;string&quot;&gt;&quot;stroke-width&quot;&lt;/span&gt;,&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;span class=&quot;keyword&quot;&gt;var&lt;/span&gt; color = d3.scale.category20();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;span class=&quot;comment&quot;&gt;//添加节点&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;span class=&quot;keyword&quot;&gt;var&lt;/span&gt; svg_nodes = svg.selectAll(&lt;span class=&quot;string&quot;&gt;&quot;circle&quot;&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     .data(nodes)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     .enter()&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     .append(&lt;span class=&quot;string&quot;&gt;&quot;circle&quot;&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     .attr(&lt;span class=&quot;string&quot;&gt;&quot;r&quot;&lt;/span&gt;,&lt;span class=&quot;number&quot;&gt;20&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     .style(&lt;span class=&quot;string&quot;&gt;&quot;fill&quot;&lt;/span&gt;,&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;(&lt;span class=&quot;params&quot;&gt;d,i&lt;/span&gt;)&lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;         &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; color(i);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     &amp;#125;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     .call(force.drag);  &lt;span class=&quot;comment&quot;&gt;//使得节点能够拖动&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;span class=&quot;comment&quot;&gt;//添加描述节点的文字&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; &lt;span class=&quot;keyword&quot;&gt;var&lt;/span&gt; svg_texts = svg.selectAll(&lt;span class=&quot;string&quot;&gt;&quot;text&quot;&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     .data(nodes)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     .enter()&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     .append(&lt;span class=&quot;string&quot;&gt;&quot;text&quot;&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     .style(&lt;span class=&quot;string&quot;&gt;&quot;fill&quot;&lt;/span&gt;, &lt;span class=&quot;string&quot;&gt;&quot;black&quot;&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     .attr(&lt;span class=&quot;string&quot;&gt;&quot;dx&quot;&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;20&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     .attr(&lt;span class=&quot;string&quot;&gt;&quot;dy&quot;&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;8&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     .text(&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;(&lt;span class=&quot;params&quot;&gt;d&lt;/span&gt;)&lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; d.name;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;     &amp;#125;);&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;调用 call( force.drag ) 后节点可被拖动。force.drag() 是一个函数，将其作为 call() 的参数，相当于将当前选择的元素传到 force.drag() 函数中。&lt;/p&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;http://buptldy.github.io/DEMO/news_map.html&quot;&gt;http://buptldy.github.io/DEMO/news_map.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-5-21/3836519.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
</content>
    
    <summary type="html">
    
      &lt;p&gt;&lt;center&gt;&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-6-11/65263838.jpg&quot; alt=&quot;&quot;&gt;&lt;br&gt;&lt;/center&gt;&lt;br&gt;
    
    </summary>
    
    
      <category term="D3" scheme="http://buptldy.github.io/tags/D3/"/>
    
      <category term="Data Visualization" scheme="http://buptldy.github.io/tags/Data-Visualization/"/>
    
  </entry>
  
  <entry>
    <title>Basic Sorting Algorithms Implemented In Python</title>
    <link href="http://buptldy.github.io/2016/05/09/2016-05-09-Python%20sorting/"/>
    <id>http://buptldy.github.io/2016/05/09/2016-05-09-Python sorting/</id>
    <published>2016-05-09T04:00:00.000Z</published>
    <updated>2016-10-04T05:31:41.975Z</updated>
    
    <content type="html">&lt;p&gt;&lt;center&gt;&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-5-9/51291175.jpg&quot; alt=&quot;&quot;&gt;&lt;br&gt;&lt;/center&gt;&lt;br&gt;&lt;a id=&quot;more&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1 id=&quot;冒泡排序&quot;&gt;&lt;a href=&quot;#冒泡排序&quot; class=&quot;headerlink&quot; title=&quot;冒泡排序&quot;&gt;&lt;/a&gt;冒泡排序&lt;/h1&gt;&lt;p&gt;冒泡排序比较简单，主要过程如下：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;比较相邻的元素。如果第一个比第二个大，就交换他们两个。&lt;/li&gt;
&lt;li&gt;对每一对相邻元素作同样的工作，从开始第一对到结尾的最后一对。这步做完后，最后的元素会是最大的数。&lt;/li&gt;
&lt;li&gt;针对所有的元素重复以上的步骤，除了最后一个。&lt;/li&gt;
&lt;li&gt;持续每次对越来越少的元素重复上面的步骤，直到没有任何一对数字需要比较。&lt;/li&gt;
&lt;/ul&gt;
&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;BubbleSort&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(array)&lt;/span&gt;:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; i &lt;span class=&quot;keyword&quot;&gt;in&lt;/span&gt; xrange(len(array)):&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; j &lt;span class=&quot;keyword&quot;&gt;in&lt;/span&gt; xrange(len(array)&lt;span class=&quot;number&quot;&gt;-1&lt;/span&gt;):&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; array[j]&amp;gt;array[j+&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;]:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                array[j],array[j+&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;]=array[j+&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;],array[j]&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; array&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;h1 id=&quot;选择排序&quot;&gt;&lt;a href=&quot;#选择排序&quot; class=&quot;headerlink&quot; title=&quot;选择排序&quot;&gt;&lt;/a&gt;选择排序&lt;/h1&gt;&lt;p&gt;选择排序（Selection sort）是一种简单直观的排序算法。它的工作原理如下。首先在未排序序列中找到最小（大）元素，存放到排序序列的起始位置，然后，再从剩余未排序元素中继续寻找最小（大）元素，然后放到已排序序列的末尾。以此类推，直到所有元素均排序完毕。&lt;/p&gt;
&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;SelectionSort&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(array)&lt;/span&gt;:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; i &lt;span class=&quot;keyword&quot;&gt;in&lt;/span&gt; xrange(len(array)):&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        min_index=i&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; j &lt;span class=&quot;keyword&quot;&gt;in&lt;/span&gt; xrange(i+&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;,len(array)):&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; array[j]&amp;lt;array[min_index]:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                min_index=j&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        array[i],array[min_index]=array[min_index],array[i]&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; array&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;h1 id=&quot;插入排序&quot;&gt;&lt;a href=&quot;#插入排序&quot; class=&quot;headerlink&quot; title=&quot;插入排序&quot;&gt;&lt;/a&gt;插入排序&lt;/h1&gt;&lt;p&gt;插入排序（英语：Insertion Sort）是一种简单直观的排序算法。它的工作原理是通过构建有序序列，对于未排序数据，在已排序序列中从后向前扫描，找到相应位置并插入。插入排序在实现上，通常采用in-place排序（即只需用到O(1)的额外空间的排序），因而在从后向前扫描过程中，需要反复把已排序元素逐步向后挪位，为最新元素提供插入空间。&lt;/p&gt;
&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;InsertionSort&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(array)&lt;/span&gt;:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; i &lt;span class=&quot;keyword&quot;&gt;in&lt;/span&gt; xrange(&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;,len(array)):&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        temp=array[i]&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; j &lt;span class=&quot;keyword&quot;&gt;in&lt;/span&gt; xrange(i,&lt;span class=&quot;number&quot;&gt;-1&lt;/span&gt;,&lt;span class=&quot;number&quot;&gt;-1&lt;/span&gt;):&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; temp&amp;gt;array[j&lt;span class=&quot;number&quot;&gt;-1&lt;/span&gt;]:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;break&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                array[j]=array[j&lt;span class=&quot;number&quot;&gt;-1&lt;/span&gt;]&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        array[j]=temp&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; array&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;h1 id=&quot;归并排序&quot;&gt;&lt;a href=&quot;#归并排序&quot; class=&quot;headerlink&quot; title=&quot;归并排序&quot;&gt;&lt;/a&gt;归并排序&lt;/h1&gt;&lt;p&gt;归并排序（英语：Merge sort，或mergesort），是创建在归并操作上的一种有效的排序算法，效率为O(n log n)。1945年由约翰·冯·诺伊曼首次提出。该算法是采用分治法（Divide and Conquer）的一个非常典型的应用，且各层分治递归可以同时进行。&lt;/p&gt;
&lt;p&gt;有关归并排序中的详细内容可以参考&lt;a href=&quot;http://buptldy.github.io/2016/01/06/2016-01-06-%E5%88%86%E6%B2%BB%E7%AD%96%E7%95%A5[Divide%20and%20Conquer]/&quot;&gt;分治策略中的归并排序&lt;/a&gt;&lt;/p&gt;
&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;MergeSort&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(array)&lt;/span&gt;:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    n=len(array)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; n&amp;lt;=&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; array&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        n=n/&lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        left=MergeSort(array[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;:n])&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        right=MergeSort(array[n:])&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; Merge(left,right)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;Merge&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(left,right)&lt;/span&gt;:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    array=[]&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;while&lt;/span&gt; len(left)&amp;gt;&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;and&lt;/span&gt; len(right)&amp;gt;&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; left[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;]&amp;lt;right[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;]:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            array.append(left[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;])&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;del&lt;/span&gt; left[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;]&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            array.append(right[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;])&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;del&lt;/span&gt; right[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;]&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; len(left)&amp;gt;&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        array.extend(left)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; len(right)&amp;gt;&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        array.extend(right)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; array&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;h1 id=&quot;快速排序&quot;&gt;&lt;a href=&quot;#快速排序&quot; class=&quot;headerlink&quot; title=&quot;快速排序&quot;&gt;&lt;/a&gt;快速排序&lt;/h1&gt;&lt;p&gt;快速排序使用分治法（Divide and conquer）策略来把一个序列（list）分为两个子序列（sub-lists）。&lt;/p&gt;
&lt;p&gt;步骤为：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;从数列中挑出一个元素，称为”基准”（pivot），重新排序数列，所有元素比基准值小的摆放在基准前面，所有元素比基准值大的摆在基准的后面（相同的数可以到任一边）。在这个分区结束之后，该基准就处于数列的中间位置。这个称为分区（partition）操作。&lt;/li&gt;
&lt;li&gt;递归地（recursive）把小于基准值元素的子数列和大于基准值元素的子数列排序。&lt;/li&gt;
&lt;li&gt;递归的最底部情形，是数列的大小是零或一，也就是永远都已经被排序好了。虽然一直递归下去，但是这个算法总会结束，因为在每次的迭代（iteration）中，它至少会把一个元素摆到它最后的位置去。&lt;/li&gt;
&lt;/ul&gt;
&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;QuickSort&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(array)&lt;/span&gt;:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; len(array)&amp;lt;=&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; array&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    pivot=array[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;]&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    left=[x &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; x &lt;span class=&quot;keyword&quot;&gt;in&lt;/span&gt; array[&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;:]&lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; x&amp;lt;pivot ]&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    right=[x &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; x &lt;span class=&quot;keyword&quot;&gt;in&lt;/span&gt; array[&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;:] &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; x&amp;gt;=pivot]&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; QuickSort(left)+[pivot]+QuickSort(right)&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;h1 id=&quot;堆排序&quot;&gt;&lt;a href=&quot;#堆排序&quot; class=&quot;headerlink&quot; title=&quot;堆排序&quot;&gt;&lt;/a&gt;堆排序&lt;/h1&gt;&lt;p&gt;在堆的数据结构中，堆中的最大值总是位于根节点。堆中定义以下几种操作：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;最大堆调整（Max_Heapify）：将堆的末端子节点作调整，使得子节点永远小于父节点&lt;/li&gt;
&lt;li&gt;创建最大堆（Build_Max_Heap）：将堆所有数据重新排序&lt;/li&gt;
&lt;li&gt;堆排序（HeapSort）：移除位在第一个数据的根节点，并做最大堆调整的递归运算&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;堆排序可以参考这篇博文：[&lt;a href=&quot;http://www.cnblogs.com/cj723/archive/2011/04/22/2024269.html]（http://www.cnblogs.com/cj723/archive/2011/04/22/2024269.html）&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;http://www.cnblogs.com/cj723/archive/2011/04/22/2024269.html]（http://www.cnblogs.com/cj723/archive/2011/04/22/2024269.html）&lt;/a&gt;&lt;/p&gt;
&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;heap_sort&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(array)&lt;/span&gt;:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;sift_down&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(start, end)&lt;/span&gt;:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;string&quot;&gt;&quot;&quot;&quot;最大堆调整&quot;&quot;&quot;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;root = start&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;True&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    child = &lt;span class=&quot;number&quot;&gt;2&lt;/span&gt; * root + &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;    &lt;span class=&quot;comment&quot;&gt;#左子节点&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; child &amp;gt; end:         &lt;span class=&quot;comment&quot;&gt;#如果没有子节点退出&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;break&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; child + &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt; &amp;lt;= end &lt;span class=&quot;keyword&quot;&gt;and&lt;/span&gt; array[child] &amp;lt; array[child + &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;]: &lt;span class=&quot;comment&quot;&gt;#如果左子节点值小于右子节点&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        child += &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;                             &lt;span class=&quot;comment&quot;&gt;#下标由左子节点更换为右子节点&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; array[root] &amp;lt; array[child]:             &lt;span class=&quot;comment&quot;&gt;#如果父节点小与子节点，则值相互交换&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        array[root], array[child] = array[child], array[root]&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        root = child                           &lt;span class=&quot;comment&quot;&gt;#对发生变化的子节点向下递归，重复上述过程&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;break&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;# 创建最大堆&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; start &lt;span class=&quot;keyword&quot;&gt;in&lt;/span&gt; xrange((len(array) - &lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;) // &lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;-1&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;-1&lt;/span&gt;):&lt;span class=&quot;comment&quot;&gt;#从最后一个非叶子节点开始构造最大堆&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;sift_down(start, len(array) - &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;# 堆排序&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; end &lt;span class=&quot;keyword&quot;&gt;in&lt;/span&gt; xrange(len(array) - &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;-1&lt;/span&gt;):&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;array[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;], array[end] = array[end], array[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;] &lt;span class=&quot;comment&quot;&gt;#把最大值放在最后&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;sift_down(&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;, end - &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;)                      &lt;span class=&quot;comment&quot;&gt;#除最大值之外的继续构造最大堆&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; array&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
</content>
    
    <summary type="html">
    
      &lt;p&gt;&lt;center&gt;&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-5-9/51291175.jpg&quot; alt=&quot;&quot;&gt;&lt;br&gt;&lt;/center&gt;&lt;br&gt;
    
    </summary>
    
    
      <category term="Algorithms" scheme="http://buptldy.github.io/tags/Algorithms/"/>
    
      <category term="Python" scheme="http://buptldy.github.io/tags/Python/"/>
    
  </entry>
  
  <entry>
    <title>Implementing a Singly Linked List in Python</title>
    <link href="http://buptldy.github.io/2016/05/09/2016-05-09-Python%20linked%20list/"/>
    <id>http://buptldy.github.io/2016/05/09/2016-05-09-Python linked list/</id>
    <published>2016-05-09T03:00:00.000Z</published>
    <updated>2016-10-04T05:25:36.558Z</updated>
    
    <content type="html">&lt;center&gt;&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-5-9/62221771.jpg&quot; alt=&quot;&quot;&gt;&lt;br&gt;&lt;/center&gt;&lt;br&gt;&lt;a id=&quot;more&quot;&gt;&lt;/a&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;链表中最简单的一种是单向链表，它包含两个域，一个信息域和一个指针域。这个链接指向列表中的下一个节点，而最后一个节点则指向一个空值。一个单向链表的节点被分成两个部分。第一个部分保存或者显示关于节点的信息，第二个部分存储下一个节点的地址。单向链表只可向一个方向遍历。&lt;br&gt;&lt;br&gt;&lt;center&gt;&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-5-9/37737204.jpg&quot; alt=&quot;&quot;&gt;&lt;br&gt;&lt;/center&gt;

&lt;h1 id=&quot;链表节点类的实现&quot;&gt;&lt;a href=&quot;#链表节点类的实现&quot; class=&quot;headerlink&quot; title=&quot;链表节点类的实现&quot;&gt;&lt;/a&gt;链表节点类的实现&lt;/h1&gt;&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;class&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;Node&lt;/span&gt;:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(self,initdata)&lt;/span&gt;:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        self.data = initdata&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        self.next = &lt;span class=&quot;keyword&quot;&gt;None&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;getData&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(self)&lt;/span&gt;:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; self.data&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;getNext&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(self)&lt;/span&gt;:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; self.next&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;setData&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(self,newdata)&lt;/span&gt;:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        self.data = newdata&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;setNext&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(self,newnext)&lt;/span&gt;:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        self.next = newnext&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;生成一个节点对象：&lt;/p&gt;
&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;temp = Node(&lt;span class=&quot;number&quot;&gt;93&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;temp.getData()&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;number&quot;&gt;93&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;结构如下图所示：&lt;/p&gt;
&lt;center&gt;&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-5-9/39620482.jpg&quot; alt=&quot;&quot;&gt;&lt;br&gt;&lt;/center&gt;

&lt;h1 id=&quot;链表类的实现&quot;&gt;&lt;a href=&quot;#链表类的实现&quot; class=&quot;headerlink&quot; title=&quot;链表类的实现&quot;&gt;&lt;/a&gt;链表类的实现&lt;/h1&gt;&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;class&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;UnorderedList&lt;/span&gt;:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(self)&lt;/span&gt;:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        self.head = &lt;span class=&quot;keyword&quot;&gt;None&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;新建一个链表对象：&lt;br&gt;&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;mylist = UnorderedList()&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;h1 id=&quot;往链表前端中加入节点&quot;&gt;&lt;a href=&quot;#往链表前端中加入节点&quot; class=&quot;headerlink&quot; title=&quot;往链表前端中加入节点&quot;&gt;&lt;/a&gt;往链表前端中加入节点&lt;/h1&gt;&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(self,item)&lt;/span&gt;:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    temp = Node(item)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    temp.setNext(self.head)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    self.head = temp&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;mylist.add(&lt;span class=&quot;number&quot;&gt;31&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;mylist.add(&lt;span class=&quot;number&quot;&gt;77&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;mylist.add(&lt;span class=&quot;number&quot;&gt;17&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;mylist.add(&lt;span class=&quot;number&quot;&gt;93&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;mylist.add(&lt;span class=&quot;number&quot;&gt;26&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;meta&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;mylist.add(&lt;span class=&quot;number&quot;&gt;54&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;现在链表结构如下图所示：&lt;/p&gt;
&lt;center&gt;&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-5-9/89034482.jpg&quot; alt=&quot;&quot;&gt;&lt;br&gt;&lt;/center&gt;

&lt;h1 id=&quot;在链表尾端添加节点&quot;&gt;&lt;a href=&quot;#在链表尾端添加节点&quot; class=&quot;headerlink&quot; title=&quot;在链表尾端添加节点&quot;&gt;&lt;/a&gt;在链表尾端添加节点&lt;/h1&gt;&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(self,item)&lt;/span&gt;:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    temp=Node(item)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; self.head == &lt;span class=&quot;keyword&quot;&gt;None&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        self.head=item&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        current=self.head&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;while&lt;/span&gt; current.getNext()!=&lt;span class=&quot;keyword&quot;&gt;None&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            current=current.getNext&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        current.setNext(temp)&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;h1 id=&quot;链表的长度计算&quot;&gt;&lt;a href=&quot;#链表的长度计算&quot; class=&quot;headerlink&quot; title=&quot;链表的长度计算&quot;&gt;&lt;/a&gt;链表的长度计算&lt;/h1&gt;&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(self)&lt;/span&gt;:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    count=&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    current=self.head&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;while&lt;/span&gt; current.getNext !=&lt;span class=&quot;keyword&quot;&gt;None&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        count=count+&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        current=current.getNext&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;计算过程如下图所示：&lt;/p&gt;
&lt;center&gt;&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-5-9/28270792.jpg&quot; alt=&quot;&quot;&gt;&lt;br&gt;&lt;/center&gt;

&lt;h1 id=&quot;寻找是否存在某一节点&quot;&gt;&lt;a href=&quot;#寻找是否存在某一节点&quot; class=&quot;headerlink&quot; title=&quot;寻找是否存在某一节点&quot;&gt;&lt;/a&gt;寻找是否存在某一节点&lt;/h1&gt;&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;serch&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(self,item)&lt;/span&gt;:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    current=self.head&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;while&lt;/span&gt; current.getNext()!=&lt;span class=&quot;keyword&quot;&gt;None&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; current.getData==item:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;True&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            current=current.getNext()&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;False&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;h1 id=&quot;删除某一节点&quot;&gt;&lt;a href=&quot;#删除某一节点&quot; class=&quot;headerlink&quot; title=&quot;删除某一节点&quot;&gt;&lt;/a&gt;删除某一节点&lt;/h1&gt;&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;remove&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(self,item)&lt;/span&gt;:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    current=self.head&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    pre=&lt;span class=&quot;keyword&quot;&gt;None&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;while&lt;/span&gt; current!=&lt;span class=&quot;keyword&quot;&gt;None&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; current.getData()==item:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;not&lt;/span&gt; pre:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                self.head=current.getNext()&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                pre.setNext(current.getNext())&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;break&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            pre=current&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            current=current.getNext()&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;h1 id=&quot;链表反转&quot;&gt;&lt;a href=&quot;#链表反转&quot; class=&quot;headerlink&quot; title=&quot;链表反转&quot;&gt;&lt;/a&gt;链表反转&lt;/h1&gt;&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;rev&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(self)&lt;/span&gt;:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    pre=&lt;span class=&quot;keyword&quot;&gt;None&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    current=self.head&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;while&lt;/span&gt; current!=&lt;span class=&quot;keyword&quot;&gt;None&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        next=current.getNext()&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        current.setNext=pre&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        pre=current&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        curren=next&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; pre&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;h1 id=&quot;链表成对调换&quot;&gt;&lt;a href=&quot;#链表成对调换&quot; class=&quot;headerlink&quot; title=&quot;链表成对调换&quot;&gt;&lt;/a&gt;链表成对调换&lt;/h1&gt;&lt;p&gt;例如：&lt;code&gt;1-&amp;gt;2-&amp;gt;3-&amp;gt;4&lt;/code&gt;转换成&lt;code&gt;2-&amp;gt;1-&amp;gt;4-&amp;gt;3&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;pairswap&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(self)&lt;/span&gt;:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    curren=self.head&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;while&lt;/span&gt; curren!=&lt;span class=&quot;keyword&quot;&gt;None&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;and&lt;/span&gt; curren.getNext().getNext()!=&lt;span class=&quot;keyword&quot;&gt;None&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        temp=curren.getData()&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        curren.setData(curren.getNext().getData())&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        curren.getNext().setData(temp)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        curren=curren.getNext().getNext()&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
</content>
    
    <summary type="html">
    
      &lt;center&gt;&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-5-9/62221771.jpg&quot; alt=&quot;&quot;&gt;&lt;br&gt;&lt;/center&gt;&lt;br&gt;
    
    </summary>
    
    
      <category term="Python" scheme="http://buptldy.github.io/tags/Python/"/>
    
      <category term="Data Structure" scheme="http://buptldy.github.io/tags/Data-Structure/"/>
    
  </entry>
  
  <entry>
    <title>Python Binary Search Tree implementation</title>
    <link href="http://buptldy.github.io/2016/05/09/2016-05-09-Python%20BST/"/>
    <id>http://buptldy.github.io/2016/05/09/2016-05-09-Python BST/</id>
    <published>2016-05-09T02:00:00.000Z</published>
    <updated>2016-10-04T05:35:07.544Z</updated>
    
    <content type="html">&lt;center&gt;&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-5-9/90589523.jpg&quot; alt=&quot;&quot;&gt;&lt;br&gt;&lt;/center&gt;&lt;br&gt;&lt;a id=&quot;more&quot;&gt;&lt;/a&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;二叉查找树（英语：Binary Search Tree），也称二叉搜索树、有序二叉树（英语：ordered binary tree），排序二叉树（英语：sorted binary tree），是指一棵空树或者具有下列性质的二叉树：&lt;br&gt;&lt;br&gt;- 任意节点的左子树不空，则左子树上所有结点的值均小于它的根结点的值；&lt;br&gt;- 任意节点的右子树不空，则右子树上所有结点的值均大于它的根结点的值；&lt;br&gt;- 任意节点的左、右子树也分别为二叉查找树；&lt;br&gt;- 没有键值相等的节点。&lt;br&gt;如下所示为一棵二叉查找树：&lt;br&gt;&lt;center&gt;&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-5-8/57493358.jpg&quot; alt=&quot;&quot;&gt;&lt;br&gt;&lt;/center&gt;

&lt;h1 id=&quot;定义节点类&quot;&gt;&lt;a href=&quot;#定义节点类&quot; class=&quot;headerlink&quot; title=&quot;定义节点类&quot;&gt;&lt;/a&gt;定义节点类&lt;/h1&gt;&lt;p&gt;二叉树的每个节点有三个属性:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;左节点&lt;/li&gt;
&lt;li&gt;右节点&lt;/li&gt;
&lt;li&gt;节点值&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;所以用Python定义一个节点类为：&lt;br&gt;&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;class&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;Node&lt;/span&gt;:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(self, data,left=None,right=None)&lt;/span&gt;:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        self.left = left&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        self.right = right&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        self.data = data&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;现在来创建一个根节点为8的树：&lt;br&gt;&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;root=Node(&lt;span class=&quot;number&quot;&gt;8&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;如下图所示：&lt;/p&gt;
&lt;center&gt;&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-5-8/11936419.jpg&quot; alt=&quot;&quot;&gt;&lt;br&gt;&lt;/center&gt;

&lt;h1 id=&quot;插入节点&quot;&gt;&lt;a href=&quot;#插入节点&quot; class=&quot;headerlink&quot; title=&quot;插入节点&quot;&gt;&lt;/a&gt;插入节点&lt;/h1&gt;&lt;p&gt;比较要插入数据和根节点的大小，递归的调用插入方法&lt;br&gt;&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;class&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;Node&lt;/span&gt;:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ...&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;insert&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(self, data)&lt;/span&gt;:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; self.data:&lt;span class=&quot;comment&quot;&gt;#如果存在根节点&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; data &amp;lt; self.data:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; self.left &lt;span class=&quot;keyword&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;None&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    self.left = Node(data)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    self.left.insert(data)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;elif&lt;/span&gt; data &amp;gt; self.data:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; self.right &lt;span class=&quot;keyword&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;None&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    self.right = Node(data)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    self.right.insert(data)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            self.data = data&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;现在来插入三个节点：&lt;/p&gt;
&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;root.insert(&lt;span class=&quot;number&quot;&gt;3&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;root.insert(&lt;span class=&quot;number&quot;&gt;10&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;root.insert(&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;现在的二叉树如下所示：&lt;/p&gt;
&lt;center&gt;&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-5-8/48415300.jpg&quot; alt=&quot;&quot;&gt;&lt;br&gt;&lt;/center&gt;

&lt;p&gt;继续增加一些节点，让二叉树看起来更完整：&lt;br&gt;&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;root.insert(&lt;span class=&quot;number&quot;&gt;6&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;root.insert(&lt;span class=&quot;number&quot;&gt;4&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;root.insert(&lt;span class=&quot;number&quot;&gt;7&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;root.insert(&lt;span class=&quot;number&quot;&gt;14&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;root.insert(&lt;span class=&quot;number&quot;&gt;13&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;center&gt;&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-5-9/52855138.jpg&quot; alt=&quot;&quot;&gt;&lt;br&gt;&lt;/center&gt;

&lt;h1 id=&quot;二叉查找树的查找&quot;&gt;&lt;a href=&quot;#二叉查找树的查找&quot; class=&quot;headerlink&quot; title=&quot;二叉查找树的查找&quot;&gt;&lt;/a&gt;二叉查找树的查找&lt;/h1&gt;&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;class&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;Node&lt;/span&gt;:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ...&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;lookup&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(self, data, parent=None)&lt;/span&gt;:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; data &amp;lt; self.data:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; self.left &lt;span class=&quot;keyword&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;None&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;None&lt;/span&gt;, &lt;span class=&quot;keyword&quot;&gt;None&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; self.left.lookup(data, self)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;elif&lt;/span&gt; data &amp;gt; self.data:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; self.right &lt;span class=&quot;keyword&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;None&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;None&lt;/span&gt;, &lt;span class=&quot;keyword&quot;&gt;None&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; self.right.lookup(data, self)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; self, parent&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;查找是否存在节点6，并返回这个节点和其父节点：&lt;br&gt;&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;node, parent = root.lookup(&lt;span class=&quot;number&quot;&gt;6&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;其中查找的过程如下所示：&lt;/p&gt;
&lt;center&gt;&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-5-9/13534624.jpg&quot; alt=&quot;&quot;&gt;&lt;br&gt;&lt;/center&gt;

&lt;h1 id=&quot;删除节点&quot;&gt;&lt;a href=&quot;#删除节点&quot; class=&quot;headerlink&quot; title=&quot;删除节点&quot;&gt;&lt;/a&gt;删除节点&lt;/h1&gt;&lt;p&gt;在删除节点时，首先得统计节点孩子的个数：&lt;/p&gt;
&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;class&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;Node&lt;/span&gt;:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ...&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;children_count&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(self)&lt;/span&gt;:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        cnt = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; self.left:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            cnt += &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; self.right:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            cnt += &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; cnt&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;删除节点，分三种情况：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;要删除的节点没有孩子节点&lt;/li&gt;
&lt;li&gt;要删除的节点有一个孩子节点&lt;/li&gt;
&lt;li&gt;要删除的节点有两个孩子节点&lt;/li&gt;
&lt;/ul&gt;
&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;47&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;48&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;class&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;Node&lt;/span&gt;:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ...&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;delete&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(self, data)&lt;/span&gt;:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        node, parent = self.lookup(data)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; node &lt;span class=&quot;keyword&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;None&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            children_count = node.children_count()&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; children_count == &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;comment&quot;&gt;# if node has no children, just remove it&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; parent:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; parent.left &lt;span class=&quot;keyword&quot;&gt;is&lt;/span&gt; node:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                            parent.left = &lt;span class=&quot;keyword&quot;&gt;None&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                            parent.right = &lt;span class=&quot;keyword&quot;&gt;None&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &lt;span class=&quot;keyword&quot;&gt;del&lt;/span&gt; node&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        self.data = &lt;span class=&quot;keyword&quot;&gt;None&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;elif&lt;/span&gt; children_count == &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                      &lt;span class=&quot;comment&quot;&gt;# if node has 1 child&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                      &lt;span class=&quot;comment&quot;&gt;# replace node with its child&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; node.left:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        n = node.left&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        n = node.right&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; parent:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; parent.left &lt;span class=&quot;keyword&quot;&gt;is&lt;/span&gt; node:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                            parent.left = n&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                            parent.right = n&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        &lt;span class=&quot;keyword&quot;&gt;del&lt;/span&gt; node&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        self.left = n.left&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        self.right = n.right&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        self.data = n.data&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;comment&quot;&gt;# if node has 2 children&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;comment&quot;&gt;# find its successor&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    parent = node&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    successor = node.right&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;keyword&quot;&gt;while&lt;/span&gt; successor.left:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        parent = successor&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        successor = successor.left&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;comment&quot;&gt;# replace node data by its successor data&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    node.data = successor.data&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;comment&quot;&gt;# fix successor&#39;s parent&#39;s child&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; parent.left == successor:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        parent.left = successor.right&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                    &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        parent.right = successor.right&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;h1 id=&quot;打印二叉树&quot;&gt;&lt;a href=&quot;#打印二叉树&quot; class=&quot;headerlink&quot; title=&quot;打印二叉树&quot;&gt;&lt;/a&gt;打印二叉树&lt;/h1&gt;&lt;p&gt;按照中序打印二叉树，前序和后序只需要修改打印的顺序就行。&lt;br&gt;&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;class&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;Node&lt;/span&gt;:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ...&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;print_tree&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(self)&lt;/span&gt;:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;string&quot;&gt;&quot;&quot;&quot;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        Print tree content inorder&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &quot;&quot;&quot;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; self.left:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            self.left.print_tree()&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;print&lt;/span&gt; self.data,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; self.right:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            self.right.print_tree()&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;按层次打印一个树：&lt;br&gt;&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;class&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;Node&lt;/span&gt;:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ...&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;print_each_level&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(self)&lt;/span&gt;:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      &lt;span class=&quot;comment&quot;&gt;# Start off with root node&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      thislevel = [self]&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      &lt;span class=&quot;comment&quot;&gt;# While there is another level&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      &lt;span class=&quot;keyword&quot;&gt;while&lt;/span&gt; thislevel:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        nextlevel = list()&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;#Print all the nodes in the current level, and   store the next level in a list&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; node &lt;span class=&quot;keyword&quot;&gt;in&lt;/span&gt; thislevel:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;          &lt;span class=&quot;keyword&quot;&gt;print&lt;/span&gt; node.data&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;          &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; node.left: nextlevel.append(node.left)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;          &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; node.right: nextlevel.append(node.right)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;          &lt;span class=&quot;keyword&quot;&gt;print&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;          thislevel = nextlevel&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;h1 id=&quot;比较两棵树&quot;&gt;&lt;a href=&quot;#比较两棵树&quot; class=&quot;headerlink&quot; title=&quot;比较两棵树&quot;&gt;&lt;/a&gt;比较两棵树&lt;/h1&gt;&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;class&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;Node&lt;/span&gt;:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ...&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;compare_trees&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(self, node)&lt;/span&gt;:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; node &lt;span class=&quot;keyword&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;None&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;False&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; self.data != node.data:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;False&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        res = &lt;span class=&quot;keyword&quot;&gt;True&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; self.left &lt;span class=&quot;keyword&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;None&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; node.left:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;False&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            res = self.left.compare_trees(node.left)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; res &lt;span class=&quot;keyword&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;False&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;False&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; self.right &lt;span class=&quot;keyword&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;None&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; node.right:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;False&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            res = self.right.compare_trees(node.right)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; res&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;h1 id=&quot;二叉树的重建&quot;&gt;&lt;a href=&quot;#二叉树的重建&quot; class=&quot;headerlink&quot; title=&quot;二叉树的重建&quot;&gt;&lt;/a&gt;二叉树的重建&lt;/h1&gt;&lt;p&gt;根据前序遍历和中序遍历来重建树，重建的原理可以参看这篇博文&lt;a href=&quot;http://blog.csdn.net/hinyunsin/article/details/6315502&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;根据二叉树的前序和中序求后序&lt;/a&gt;:&lt;br&gt;&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;rebuilt&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(preorder,inorder)&lt;/span&gt;:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; preorder==&lt;span class=&quot;string&quot;&gt;&#39;&#39;&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;or&lt;/span&gt; inorder==&lt;span class=&quot;string&quot;&gt;&#39;&#39;&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;None&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    root=preorder[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;]&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    index=inorder.index(root)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; Node(root,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                rebuilt(preorder[&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;:&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;+index],inorder[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;:index]),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                rebuilt(preorder[index+&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;:],inorder[index+&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;:]))&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;根据中序和后序来重建树：&lt;/p&gt;
&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;rebuilt1&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(inorder,postorder)&lt;/span&gt;:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; postorder==&lt;span class=&quot;string&quot;&gt;&#39;&#39;&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;or&lt;/span&gt; inorder==&lt;span class=&quot;string&quot;&gt;&#39;&#39;&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;None&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    root=postorder[&lt;span class=&quot;number&quot;&gt;-1&lt;/span&gt;]&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    index=inorder.index(root)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; Node(root,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                rebuilt1(inorder[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;:index],postorder[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;:index]),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                rebuilt1(inorder[index+&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;:],postorder[index:&lt;span class=&quot;number&quot;&gt;-1&lt;/span&gt;]))&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;h1 id=&quot;参考&quot;&gt;&lt;a href=&quot;#参考&quot; class=&quot;headerlink&quot; title=&quot;参考&quot;&gt;&lt;/a&gt;参考&lt;/h1&gt;&lt;p&gt;&lt;a href=&quot;https://zh.wikipedia.org/wiki/%E4%BA%8C%E5%85%83%E6%90%9C%E5%B0%8B%E6%A8%B9&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;二叉搜索树&lt;/a&gt;&lt;br&gt;&lt;a href=&quot;http://www.laurentluce.com/posts/binary-search-tree-library-in-python/&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;Binary Search Tree library in Python&lt;/a&gt;&lt;/p&gt;
</content>
    
    <summary type="html">
    
      &lt;center&gt;&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-5-9/90589523.jpg&quot; alt=&quot;&quot;&gt;&lt;br&gt;&lt;/center&gt;&lt;br&gt;
    
    </summary>
    
    
      <category term="Python" scheme="http://buptldy.github.io/tags/Python/"/>
    
      <category term="Data Structure" scheme="http://buptldy.github.io/tags/Data-Structure/"/>
    
  </entry>
  
  <entry>
    <title>Learning with Caffe in Python</title>
    <link href="http://buptldy.github.io/2016/05/05/2016-05-05-Caffe%20Python/"/>
    <id>http://buptldy.github.io/2016/05/05/2016-05-05-Caffe Python/</id>
    <published>2016-05-05T02:00:00.000Z</published>
    <updated>2016-10-04T05:23:59.861Z</updated>
    
    <content type="html">&lt;p&gt;&lt;center&gt;&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-5-5/41421657.jpg&quot; alt=&quot;&quot;&gt;&lt;br&gt;&lt;/center&gt;&lt;br&gt;&lt;a id=&quot;more&quot;&gt;&lt;/a&gt;&lt;br&gt;在这个例子中，我们开始尝试通过Python调用&lt;code&gt;Solver&lt;/code&gt;接口来训练一个网络。&lt;/p&gt;
&lt;h3 id=&quot;环境设置&quot;&gt;&lt;a href=&quot;#环境设置&quot; class=&quot;headerlink&quot; title=&quot;环境设置&quot;&gt;&lt;/a&gt;环境设置&lt;/h3&gt;&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;from&lt;/span&gt; pylab &lt;span class=&quot;keyword&quot;&gt;import&lt;/span&gt; *&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;%matplotlib inline&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;caffe_root = &lt;span class=&quot;string&quot;&gt;&#39;/home/ldy/workspace/caffe/&#39;&lt;/span&gt;  &lt;span class=&quot;comment&quot;&gt;# this file should be run from &amp;#123;caffe_root&amp;#125;/examples (otherwise change this line)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;import&lt;/span&gt; sys&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;sys.path.insert(&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;, caffe_root + &lt;span class=&quot;string&quot;&gt;&#39;python&#39;&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;import&lt;/span&gt; caffe&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;ul&gt;
&lt;li&gt;下载训练用的数据，并导入lmdb&lt;/li&gt;
&lt;/ul&gt;
&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;# run scripts from caffe root&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;import&lt;/span&gt; os&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;os.chdir(caffe_root)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;# Download data&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;!data/mnist/get_mnist.sh&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;# Prepare data&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;!examples/mnist/create_mnist.sh&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;# back to examples&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;os.chdir(&lt;span class=&quot;string&quot;&gt;&#39;examples&#39;&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;pre&gt;&lt;code&gt;Downloading...
Creating lmdb...
I0505 20:49:32.535013 18388 db_lmdb.cpp:35] Opened lmdb examples/mnist/mnist_train_lmdb
I0505 20:49:32.535306 18388 convert_mnist_data.cpp:88] A total of 60000 items.
I0505 20:49:32.535323 18388 convert_mnist_data.cpp:89] Rows: 28 Cols: 28
I0505 20:49:32.547651 18388 db_lmdb.cpp:101] Doubling LMDB map size to 2MB ...
I0505 20:49:32.556696 18388 db_lmdb.cpp:101] Doubling LMDB map size to 4MB ...
I0505 20:49:32.578054 18388 db_lmdb.cpp:101] Doubling LMDB map size to 8MB ...
I0505 20:49:32.627709 18388 db_lmdb.cpp:101] Doubling LMDB map size to 16MB ...
I0505 20:49:32.718138 18388 db_lmdb.cpp:101] Doubling LMDB map size to 32MB ...
I0505 20:49:32.960189 18388 db_lmdb.cpp:101] Doubling LMDB map size to 64MB ...
I0505 20:49:33.271764 18388 convert_mnist_data.cpp:108] Processed 60000 files.
I0505 20:49:33.403015 18390 db_lmdb.cpp:35] Opened lmdb examples/mnist/mnist_test_lmdb
I0505 20:49:33.403692 18390 convert_mnist_data.cpp:88] A total of 10000 items.
I0505 20:49:33.403733 18390 convert_mnist_data.cpp:89] Rows: 28 Cols: 28
I0505 20:49:33.423638 18390 db_lmdb.cpp:101] Doubling LMDB map size to 2MB ...
I0505 20:49:33.439213 18390 db_lmdb.cpp:101] Doubling LMDB map size to 4MB ...
I0505 20:49:33.470553 18390 db_lmdb.cpp:101] Doubling LMDB map size to 8MB ...
I0505 20:49:33.525192 18390 db_lmdb.cpp:101] Doubling LMDB map size to 16MB ...
I0505 20:49:33.546480 18390 convert_mnist_data.cpp:108] Processed 10000 files.
Done.
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;搭建网络&quot;&gt;&lt;a href=&quot;#搭建网络&quot; class=&quot;headerlink&quot; title=&quot;搭建网络&quot;&gt;&lt;/a&gt;搭建网络&lt;/h3&gt;&lt;p&gt;搭建网络结构，并保存为lenet_auto_train.prototxt（训练网络），lenet_auto_test.prototxt（测试网络）。&lt;/p&gt;
&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;from&lt;/span&gt; caffe &lt;span class=&quot;keyword&quot;&gt;import&lt;/span&gt; layers &lt;span class=&quot;keyword&quot;&gt;as&lt;/span&gt; L, params &lt;span class=&quot;keyword&quot;&gt;as&lt;/span&gt; P&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;lenet&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(lmdb, batch_size)&lt;/span&gt;:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;# our version of LeNet: a series of linear and simple nonlinear transformations&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    n = caffe.NetSpec()&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    n.data, n.label = L.Data(batch_size=batch_size, backend=P.Data.LMDB, source=lmdb,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                             transform_param=dict(scale=&lt;span class=&quot;number&quot;&gt;1.&lt;/span&gt;/&lt;span class=&quot;number&quot;&gt;255&lt;/span&gt;), ntop=&lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    n.conv1 = L.Convolution(n.data, kernel_size=&lt;span class=&quot;number&quot;&gt;5&lt;/span&gt;, num_output=&lt;span class=&quot;number&quot;&gt;20&lt;/span&gt;, weight_filler=dict(type=&lt;span class=&quot;string&quot;&gt;&#39;xavier&#39;&lt;/span&gt;))&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    n.pool1 = L.Pooling(n.conv1, kernel_size=&lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;, stride=&lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;, pool=P.Pooling.MAX)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    n.conv2 = L.Convolution(n.pool1, kernel_size=&lt;span class=&quot;number&quot;&gt;5&lt;/span&gt;, num_output=&lt;span class=&quot;number&quot;&gt;50&lt;/span&gt;, weight_filler=dict(type=&lt;span class=&quot;string&quot;&gt;&#39;xavier&#39;&lt;/span&gt;))&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    n.pool2 = L.Pooling(n.conv2, kernel_size=&lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;, stride=&lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;, pool=P.Pooling.MAX)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    n.fc1 =   L.InnerProduct(n.pool2, num_output=&lt;span class=&quot;number&quot;&gt;500&lt;/span&gt;, weight_filler=dict(type=&lt;span class=&quot;string&quot;&gt;&#39;xavier&#39;&lt;/span&gt;))&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    n.relu1 = L.ReLU(n.fc1, in_place=&lt;span class=&quot;keyword&quot;&gt;True&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    n.score = L.InnerProduct(n.relu1, num_output=&lt;span class=&quot;number&quot;&gt;10&lt;/span&gt;, weight_filler=dict(type=&lt;span class=&quot;string&quot;&gt;&#39;xavier&#39;&lt;/span&gt;))&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    n.loss =  L.SoftmaxWithLoss(n.score, n.label)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; n.to_proto()&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;with&lt;/span&gt; open(&lt;span class=&quot;string&quot;&gt;&#39;mnist/lenet_auto_train.prototxt&#39;&lt;/span&gt;, &lt;span class=&quot;string&quot;&gt;&#39;w&#39;&lt;/span&gt;) &lt;span class=&quot;keyword&quot;&gt;as&lt;/span&gt; f:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    f.write(str(lenet(&lt;span class=&quot;string&quot;&gt;&#39;mnist/mnist_train_lmdb&#39;&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;64&lt;/span&gt;)))&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;with&lt;/span&gt; open(&lt;span class=&quot;string&quot;&gt;&#39;mnist/lenet_auto_test.prototxt&#39;&lt;/span&gt;, &lt;span class=&quot;string&quot;&gt;&#39;w&#39;&lt;/span&gt;) &lt;span class=&quot;keyword&quot;&gt;as&lt;/span&gt; f:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    f.write(str(lenet(&lt;span class=&quot;string&quot;&gt;&#39;mnist/mnist_test_lmdb&#39;&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;100&lt;/span&gt;)))&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;查看训练网络结构：&lt;/p&gt;
&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;!cat mnist/lenet_auto_train.prototxt&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;pre&gt;&lt;code&gt;layer {
  name: &amp;quot;data&amp;quot;
  type: &amp;quot;Data&amp;quot;
  top: &amp;quot;data&amp;quot;
  top: &amp;quot;label&amp;quot;
  transform_param {
    scale: 0.00392156862745
  }
  data_param {
    source: &amp;quot;mnist/mnist_train_lmdb&amp;quot;
    batch_size: 64
    backend: LMDB
  }
}
layer {
  name: &amp;quot;conv1&amp;quot;
  type: &amp;quot;Convolution&amp;quot;
  bottom: &amp;quot;data&amp;quot;
  top: &amp;quot;conv1&amp;quot;
  convolution_param {
    num_output: 20
    kernel_size: 5
    weight_filler {
      type: &amp;quot;xavier&amp;quot;
    }
  }
}
layer {
  name: &amp;quot;pool1&amp;quot;
  type: &amp;quot;Pooling&amp;quot;
  bottom: &amp;quot;conv1&amp;quot;
  top: &amp;quot;pool1&amp;quot;
  pooling_param {
    pool: MAX
    kernel_size: 2
    stride: 2
  }
}
layer {
  name: &amp;quot;conv2&amp;quot;
  type: &amp;quot;Convolution&amp;quot;
  bottom: &amp;quot;pool1&amp;quot;
  top: &amp;quot;conv2&amp;quot;
  convolution_param {
    num_output: 50
    kernel_size: 5
    weight_filler {
      type: &amp;quot;xavier&amp;quot;
    }
  }
}
layer {
  name: &amp;quot;pool2&amp;quot;
  type: &amp;quot;Pooling&amp;quot;
  bottom: &amp;quot;conv2&amp;quot;
  top: &amp;quot;pool2&amp;quot;
  pooling_param {
    pool: MAX
    kernel_size: 2
    stride: 2
  }
}
layer {
  name: &amp;quot;fc1&amp;quot;
  type: &amp;quot;InnerProduct&amp;quot;
  bottom: &amp;quot;pool2&amp;quot;
  top: &amp;quot;fc1&amp;quot;
  inner_product_param {
    num_output: 500
    weight_filler {
      type: &amp;quot;xavier&amp;quot;
    }
  }
}
layer {
  name: &amp;quot;relu1&amp;quot;
  type: &amp;quot;ReLU&amp;quot;
  bottom: &amp;quot;fc1&amp;quot;
  top: &amp;quot;fc1&amp;quot;
}
layer {
  name: &amp;quot;score&amp;quot;
  type: &amp;quot;InnerProduct&amp;quot;
  bottom: &amp;quot;fc1&amp;quot;
  top: &amp;quot;score&amp;quot;
  inner_product_param {
    num_output: 10
    weight_filler {
      type: &amp;quot;xavier&amp;quot;
    }
  }
}
layer {
  name: &amp;quot;loss&amp;quot;
  type: &amp;quot;SoftmaxWithLoss&amp;quot;
  bottom: &amp;quot;score&amp;quot;
  bottom: &amp;quot;label&amp;quot;
  top: &amp;quot;loss&amp;quot;
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;查看学习参数，参数文件已经保存在本地磁盘：&lt;/p&gt;
&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;!cat mnist/lenet_auto_solver.prototxt&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;pre&gt;&lt;code&gt;# The train/test net protocol buffer definition
train_net: &amp;quot;mnist/lenet_auto_train.prototxt&amp;quot;
test_net: &amp;quot;mnist/lenet_auto_test.prototxt&amp;quot;
# test_iter specifies how many forward passes the test should carry out.
# In the case of MNIST, we have test batch size 100 and 100 test iterations,
# covering the full 10,000 testing images.
test_iter: 100
# Carry out testing every 500 training iterations.
test_interval: 500
# The base learning rate, momentum and the weight decay of the network.
base_lr: 0.01
momentum: 0.9
weight_decay: 0.0005
# The learning rate policy
lr_policy: &amp;quot;inv&amp;quot;
gamma: 0.0001
power: 0.75
# Display every 100 iterations
display: 100
# The maximum number of iterations
max_iter: 10000
# snapshot intermediate results
snapshot: 5000
snapshot_prefix: &amp;quot;mnist/lenet&amp;quot;
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;加载并检查solver&quot;&gt;&lt;a href=&quot;#加载并检查solver&quot; class=&quot;headerlink&quot; title=&quot;加载并检查solver&quot;&gt;&lt;/a&gt;加载并检查solver&lt;/h3&gt;&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;caffe.set_device(&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;caffe.set_mode_gpu()&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;### load the solver and create train and test nets&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;solver = &lt;span class=&quot;keyword&quot;&gt;None&lt;/span&gt;  &lt;span class=&quot;comment&quot;&gt;# ignore this workaround for lmdb data (can&#39;t instantiate two solvers on the same data)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;solver = caffe.SGDSolver(&lt;span class=&quot;string&quot;&gt;&#39;mnist/lenet_auto_solver.prototxt&#39;&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;ul&gt;
&lt;li&gt;检查网络参数&lt;/li&gt;
&lt;/ul&gt;
&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;# each output is (batch size, feature dim, spatial dim)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;[(k, v.data.shape) &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; k, v &lt;span class=&quot;keyword&quot;&gt;in&lt;/span&gt; solver.net.blobs.items()]&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;pre&gt;&lt;code&gt;[(&amp;apos;data&amp;apos;, (64, 1, 28, 28)),
 (&amp;apos;label&amp;apos;, (64,)),
 (&amp;apos;conv1&amp;apos;, (64, 20, 24, 24)),
 (&amp;apos;pool1&amp;apos;, (64, 20, 12, 12)),
 (&amp;apos;conv2&amp;apos;, (64, 50, 8, 8)),
 (&amp;apos;pool2&amp;apos;, (64, 50, 4, 4)),
 (&amp;apos;fc1&amp;apos;, (64, 500)),
 (&amp;apos;score&amp;apos;, (64, 10)),
 (&amp;apos;loss&amp;apos;, ())]
&lt;/code&gt;&lt;/pre&gt;&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;# just print the weight sizes (we&#39;ll omit the biases)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;[(k, v[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;].data.shape) &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; k, v &lt;span class=&quot;keyword&quot;&gt;in&lt;/span&gt; solver.net.params.items()]&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;pre&gt;&lt;code&gt;[(&amp;apos;conv1&amp;apos;, (20, 1, 5, 5)),
 (&amp;apos;conv2&amp;apos;, (50, 20, 5, 5)),
 (&amp;apos;fc1&amp;apos;, (500, 800)),
 (&amp;apos;score&amp;apos;, (10, 500))]
&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;
&lt;li&gt;在开始前，我们先检查下训练网络和测试网络是否包含我们的数据&lt;/li&gt;
&lt;/ul&gt;
&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;solver.net.forward()  &lt;span class=&quot;comment&quot;&gt;# train net&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;solver.test_nets[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;].forward()  &lt;span class=&quot;comment&quot;&gt;# test net (there can be more than one)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;pre&gt;&lt;code&gt;{&amp;apos;loss&amp;apos;: array(2.3089799880981445, dtype=float32)}
&lt;/code&gt;&lt;/pre&gt;&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;# we use a little trick to tile the first eight images&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;imshow(solver.net.blobs[&lt;span class=&quot;string&quot;&gt;&#39;data&#39;&lt;/span&gt;].data[:&lt;span class=&quot;number&quot;&gt;8&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;].transpose(&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;).reshape(&lt;span class=&quot;number&quot;&gt;28&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;8&lt;/span&gt;*&lt;span class=&quot;number&quot;&gt;28&lt;/span&gt;), cmap=&lt;span class=&quot;string&quot;&gt;&#39;gray&#39;&lt;/span&gt;); axis(&lt;span class=&quot;string&quot;&gt;&#39;off&#39;&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;&#39;train labels:&#39;&lt;/span&gt;, solver.net.blobs[&lt;span class=&quot;string&quot;&gt;&#39;label&#39;&lt;/span&gt;].data[:&lt;span class=&quot;number&quot;&gt;8&lt;/span&gt;]&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;pre&gt;&lt;code&gt;train labels: [ 5.  0.  4.  1.  9.  2.  1.  3.]
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-5-5/69386136.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;imshow(solver.test_nets[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;].blobs[&lt;span class=&quot;string&quot;&gt;&#39;data&#39;&lt;/span&gt;].data[:&lt;span class=&quot;number&quot;&gt;8&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;].transpose(&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;).reshape(&lt;span class=&quot;number&quot;&gt;28&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;8&lt;/span&gt;*&lt;span class=&quot;number&quot;&gt;28&lt;/span&gt;), cmap=&lt;span class=&quot;string&quot;&gt;&#39;gray&#39;&lt;/span&gt;); axis(&lt;span class=&quot;string&quot;&gt;&#39;off&#39;&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;&#39;test labels:&#39;&lt;/span&gt;, solver.test_nets[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;].blobs[&lt;span class=&quot;string&quot;&gt;&#39;label&#39;&lt;/span&gt;].data[:&lt;span class=&quot;number&quot;&gt;8&lt;/span&gt;]&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;pre&gt;&lt;code&gt;test labels: [ 7.  2.  1.  0.  4.  1.  4.  9.]
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-5-5/12928484.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;开始训练&quot;&gt;&lt;a href=&quot;#开始训练&quot; class=&quot;headerlink&quot; title=&quot;开始训练&quot;&gt;&lt;/a&gt;开始训练&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;先训练一个batch看会有什么结果&lt;/li&gt;
&lt;/ul&gt;
&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;solver.step(&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;运行一次之后，看看我们的第一层卷积层的滤波器是否有变化，20个滤波器如下所示：&lt;/p&gt;
&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;imshow(solver.net.params[&lt;span class=&quot;string&quot;&gt;&#39;conv1&#39;&lt;/span&gt;][&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;].diff[:, &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;].reshape(&lt;span class=&quot;number&quot;&gt;4&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;5&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;5&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;5&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;       .transpose(&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;3&lt;/span&gt;).reshape(&lt;span class=&quot;number&quot;&gt;4&lt;/span&gt;*&lt;span class=&quot;number&quot;&gt;5&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;5&lt;/span&gt;*&lt;span class=&quot;number&quot;&gt;5&lt;/span&gt;), cmap=&lt;span class=&quot;string&quot;&gt;&#39;gray&#39;&lt;/span&gt;); axis(&lt;span class=&quot;string&quot;&gt;&#39;off&#39;&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;pre&gt;&lt;code&gt;(-0.5, 24.5, 19.5, -0.5)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-5-5/2284082.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;上面说明权重已经更新，我们可以在迭代训练的时候，记录一些参数，决定什么时候停止迭代&lt;/p&gt;
&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;%%time&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;niter = &lt;span class=&quot;number&quot;&gt;200&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;test_interval = &lt;span class=&quot;number&quot;&gt;25&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;# losses will also be stored in the log&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;train_loss = zeros(niter)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;test_acc = zeros(int(np.ceil(niter / test_interval)))&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;output = zeros((niter, &lt;span class=&quot;number&quot;&gt;8&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;10&lt;/span&gt;))&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;# the main solver loop&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; it &lt;span class=&quot;keyword&quot;&gt;in&lt;/span&gt; range(niter):&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    solver.step(&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;)  &lt;span class=&quot;comment&quot;&gt;# SGD by Caffe&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;# store the train loss&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    train_loss[it] = solver.net.blobs[&lt;span class=&quot;string&quot;&gt;&#39;loss&#39;&lt;/span&gt;].data&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;# store the output on the first test batch&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;# (start the forward pass at conv1 to avoid loading new data)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    solver.test_nets[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;].forward(start=&lt;span class=&quot;string&quot;&gt;&#39;conv1&#39;&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    output[it] = solver.test_nets[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;].blobs[&lt;span class=&quot;string&quot;&gt;&#39;score&#39;&lt;/span&gt;].data[:&lt;span class=&quot;number&quot;&gt;8&lt;/span&gt;]&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;# run a full test every so often&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;# (Caffe can also do this for us and write to a log, but we show here&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;#  how to do it directly in Python, where more complicated things are easier.)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; it % test_interval == &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;&#39;Iteration&#39;&lt;/span&gt;, it, &lt;span class=&quot;string&quot;&gt;&#39;testing...&#39;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        correct = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; test_it &lt;span class=&quot;keyword&quot;&gt;in&lt;/span&gt; range(&lt;span class=&quot;number&quot;&gt;100&lt;/span&gt;):&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            solver.test_nets[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;].forward()&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            correct += sum(solver.test_nets[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;].blobs[&lt;span class=&quot;string&quot;&gt;&#39;score&#39;&lt;/span&gt;].data.argmax(&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                           == solver.test_nets[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;].blobs[&lt;span class=&quot;string&quot;&gt;&#39;label&#39;&lt;/span&gt;].data)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        test_acc[it // test_interval] = correct / &lt;span class=&quot;number&quot;&gt;1e4&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;pre&gt;&lt;code&gt;Iteration 0 testing...
Iteration 25 testing...
Iteration 50 testing...
Iteration 75 testing...
Iteration 100 testing...
Iteration 125 testing...
Iteration 150 testing...
Iteration 175 testing...
CPU times: user 1min 15s, sys: 15.3 s, total: 1min 31s
Wall time: 1min 18s
&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;
&lt;li&gt;画出train loss和test accuracy&lt;/li&gt;
&lt;/ul&gt;
&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;_, ax1 = subplots()&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;ax2 = ax1.twinx()&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;ax1.plot(arange(niter), train_loss)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;ax2.plot(test_interval * arange(len(test_acc)), test_acc, &lt;span class=&quot;string&quot;&gt;&#39;r&#39;&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;ax1.set_xlabel(&lt;span class=&quot;string&quot;&gt;&#39;iteration&#39;&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;ax1.set_ylabel(&lt;span class=&quot;string&quot;&gt;&#39;train loss&#39;&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;ax2.set_ylabel(&lt;span class=&quot;string&quot;&gt;&#39;test accuracy&#39;&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;ax2.set_title(&lt;span class=&quot;string&quot;&gt;&#39;Test Accuracy: &amp;#123;:.2f&amp;#125;&#39;&lt;/span&gt;.format(test_acc[&lt;span class=&quot;number&quot;&gt;-1&lt;/span&gt;]))&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;matplotlib.text.Text at 0x7feabeae91d0&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-5-5/18901685.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;因为我们保存第一次测试batch的结果，所以可以看看每次迭代结果的变化，下面画出每个图像随迭代次数每个标签的可能性。(只显示了一个数字，其他的数字类似)&lt;/li&gt;
&lt;/ul&gt;
&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; i &lt;span class=&quot;keyword&quot;&gt;in&lt;/span&gt; range(&lt;span class=&quot;number&quot;&gt;8&lt;/span&gt;):&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    figure(figsize=(&lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;))&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    imshow(solver.test_nets[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;].blobs[&lt;span class=&quot;string&quot;&gt;&#39;data&#39;&lt;/span&gt;].data[i, &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;], cmap=&lt;span class=&quot;string&quot;&gt;&#39;gray&#39;&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    figure(figsize=(&lt;span class=&quot;number&quot;&gt;10&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;))&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    imshow(output[:&lt;span class=&quot;number&quot;&gt;50&lt;/span&gt;, i].T, interpolation=&lt;span class=&quot;string&quot;&gt;&#39;nearest&#39;&lt;/span&gt;, cmap=&lt;span class=&quot;string&quot;&gt;&#39;gray&#39;&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    xlabel(&lt;span class=&quot;string&quot;&gt;&#39;iteration&#39;&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ylabel(&lt;span class=&quot;string&quot;&gt;&#39;label&#39;&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-5-5/47308921.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-5-5/21846569.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;尝试改变网络结构和优化函数&quot;&gt;&lt;a href=&quot;#尝试改变网络结构和优化函数&quot; class=&quot;headerlink&quot; title=&quot;尝试改变网络结构和优化函数&quot;&gt;&lt;/a&gt;尝试改变网络结构和优化函数&lt;/h3&gt;&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;47&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;48&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;49&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;50&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;51&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;52&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;53&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;54&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;55&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;56&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;57&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;58&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;59&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;60&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;61&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;62&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;63&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;64&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;65&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;66&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;67&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;68&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;69&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;70&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;71&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;72&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;73&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;74&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;75&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;76&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;77&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;78&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;79&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;80&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;81&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;82&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;83&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;84&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;85&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;86&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;87&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;88&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;89&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;90&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;91&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;92&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;93&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;94&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;95&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;96&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;97&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;98&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;99&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;100&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;101&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;102&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;103&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;104&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;105&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;106&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;107&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;108&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;109&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;110&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;111&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;112&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;113&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;114&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;115&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;116&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;117&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;118&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;119&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;120&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;121&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;122&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;123&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;124&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;125&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;126&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;127&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;128&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;train_net_path = &lt;span class=&quot;string&quot;&gt;&#39;mnist/custom_auto_train.prototxt&#39;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;test_net_path = &lt;span class=&quot;string&quot;&gt;&#39;mnist/custom_auto_test.prototxt&#39;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;solver_config_path = &lt;span class=&quot;string&quot;&gt;&#39;mnist/custom_auto_solver.prototxt&#39;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;### define net&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;custom_net&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(lmdb, batch_size)&lt;/span&gt;:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;# define your own net!&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    n = caffe.NetSpec()&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;# keep this data layer for all networks&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    n.data, n.label = L.Data(batch_size=batch_size, backend=P.Data.LMDB, source=lmdb,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                             transform_param=dict(scale=&lt;span class=&quot;number&quot;&gt;1.&lt;/span&gt;/&lt;span class=&quot;number&quot;&gt;255&lt;/span&gt;), ntop=&lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;# EDIT HERE to try different networks&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;# this single layer defines a simple linear classifier&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;# (in particular this defines a multiway logistic regression)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    n.score =   L.InnerProduct(n.data, num_output=&lt;span class=&quot;number&quot;&gt;10&lt;/span&gt;, weight_filler=dict(type=&lt;span class=&quot;string&quot;&gt;&#39;xavier&#39;&lt;/span&gt;))&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;# EDIT HERE this is the LeNet variant we have already tried&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;# n.conv1 = L.Convolution(n.data, kernel_size=5, num_output=20, weight_filler=dict(type=&#39;xavier&#39;))&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;# n.pool1 = L.Pooling(n.conv1, kernel_size=2, stride=2, pool=P.Pooling.MAX)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;# n.conv2 = L.Convolution(n.pool1, kernel_size=5, num_output=50, weight_filler=dict(type=&#39;xavier&#39;))&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;# n.pool2 = L.Pooling(n.conv2, kernel_size=2, stride=2, pool=P.Pooling.MAX)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;# n.fc1 =   L.InnerProduct(n.pool2, num_output=500, weight_filler=dict(type=&#39;xavier&#39;))&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;# EDIT HERE consider L.ELU or L.Sigmoid for the nonlinearity&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;# n.relu1 = L.ReLU(n.fc1, in_place=True)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;# n.score =   L.InnerProduct(n.fc1, num_output=10, weight_filler=dict(type=&#39;xavier&#39;))&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;# keep this loss layer for all networks&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    n.loss =  L.SoftmaxWithLoss(n.score, n.label)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; n.to_proto()&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;with&lt;/span&gt; open(train_net_path, &lt;span class=&quot;string&quot;&gt;&#39;w&#39;&lt;/span&gt;) &lt;span class=&quot;keyword&quot;&gt;as&lt;/span&gt; f:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    f.write(str(custom_net(&lt;span class=&quot;string&quot;&gt;&#39;mnist/mnist_train_lmdb&#39;&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;64&lt;/span&gt;)))    &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;with&lt;/span&gt; open(test_net_path, &lt;span class=&quot;string&quot;&gt;&#39;w&#39;&lt;/span&gt;) &lt;span class=&quot;keyword&quot;&gt;as&lt;/span&gt; f:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    f.write(str(custom_net(&lt;span class=&quot;string&quot;&gt;&#39;mnist/mnist_test_lmdb&#39;&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;100&lt;/span&gt;)))&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;### define solver&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;from&lt;/span&gt; caffe.proto &lt;span class=&quot;keyword&quot;&gt;import&lt;/span&gt; caffe_pb2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;s = caffe_pb2.SolverParameter()&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;# Set a seed for reproducible experiments:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;# this controls for randomization in training.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;s.random_seed = &lt;span class=&quot;number&quot;&gt;0xCAFFE&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;# Specify locations of the train and (maybe) test networks.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;s.train_net = train_net_path&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;s.test_net.append(test_net_path)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;s.test_interval = &lt;span class=&quot;number&quot;&gt;500&lt;/span&gt;  &lt;span class=&quot;comment&quot;&gt;# Test after every 500 training iterations.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;s.test_iter.append(&lt;span class=&quot;number&quot;&gt;100&lt;/span&gt;) &lt;span class=&quot;comment&quot;&gt;# Test on 100 batches each time we test.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;s.max_iter = &lt;span class=&quot;number&quot;&gt;10000&lt;/span&gt;     &lt;span class=&quot;comment&quot;&gt;# no. of times to update the net (training iterations)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;# EDIT HERE to try different solvers&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;# solver types include &quot;SGD&quot;, &quot;Adam&quot;, and &quot;Nesterov&quot; among others.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;s.type = &lt;span class=&quot;string&quot;&gt;&quot;SGD&quot;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;# Set the initial learning rate for SGD.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;s.base_lr = &lt;span class=&quot;number&quot;&gt;0.01&lt;/span&gt;  &lt;span class=&quot;comment&quot;&gt;# EDIT HERE to try different learning rates&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;# Set momentum to accelerate learning by&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;# taking weighted average of current and previous updates.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;s.momentum = &lt;span class=&quot;number&quot;&gt;0.9&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;# Set weight decay to regularize and prevent overfitting&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;s.weight_decay = &lt;span class=&quot;number&quot;&gt;5e-4&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;# Set `lr_policy` to define how the learning rate changes during training.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;# This is the same policy as our default LeNet.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;s.lr_policy = &lt;span class=&quot;string&quot;&gt;&#39;inv&#39;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;s.gamma = &lt;span class=&quot;number&quot;&gt;0.0001&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;s.power = &lt;span class=&quot;number&quot;&gt;0.75&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;# EDIT HERE to try the fixed rate (and compare with adaptive solvers)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;# `fixed` is the simplest policy that keeps the learning rate constant.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;# s.lr_policy = &#39;fixed&#39;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;# Display the current training loss and accuracy every 1000 iterations.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;s.display = &lt;span class=&quot;number&quot;&gt;1000&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;# Snapshots are files used to store networks we&#39;ve trained.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;# We&#39;ll snapshot every 5K iterations -- twice during training.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;s.snapshot = &lt;span class=&quot;number&quot;&gt;5000&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;s.snapshot_prefix = &lt;span class=&quot;string&quot;&gt;&#39;mnist/custom_net&#39;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;# Train on the GPU&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;s.solver_mode = caffe_pb2.SolverParameter.GPU&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;# Write the solver to a temporary file and return its filename.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;with&lt;/span&gt; open(solver_config_path, &lt;span class=&quot;string&quot;&gt;&#39;w&#39;&lt;/span&gt;) &lt;span class=&quot;keyword&quot;&gt;as&lt;/span&gt; f:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    f.write(str(s))&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;### load the solver and create train and test nets&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;solver = &lt;span class=&quot;keyword&quot;&gt;None&lt;/span&gt;  &lt;span class=&quot;comment&quot;&gt;# ignore this workaround for lmdb data (can&#39;t instantiate two solvers on the same data)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;solver = caffe.get_solver(solver_config_path)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;### solve&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;niter = &lt;span class=&quot;number&quot;&gt;250&lt;/span&gt;  &lt;span class=&quot;comment&quot;&gt;# EDIT HERE increase to train for longer&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;test_interval = niter / &lt;span class=&quot;number&quot;&gt;10&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;# losses will also be stored in the log&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;train_loss = zeros(niter)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;test_acc = zeros(int(np.ceil(niter / test_interval)))&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;# the main solver loop&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; it &lt;span class=&quot;keyword&quot;&gt;in&lt;/span&gt; range(niter):&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    solver.step(&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;)  &lt;span class=&quot;comment&quot;&gt;# SGD by Caffe&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;# store the train loss&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    train_loss[it] = solver.net.blobs[&lt;span class=&quot;string&quot;&gt;&#39;loss&#39;&lt;/span&gt;].data&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;# run a full test every so often&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;# (Caffe can also do this for us and write to a log, but we show here&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;#  how to do it directly in Python, where more complicated things are easier.)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; it % test_interval == &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;&#39;Iteration&#39;&lt;/span&gt;, it, &lt;span class=&quot;string&quot;&gt;&#39;testing...&#39;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        correct = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; test_it &lt;span class=&quot;keyword&quot;&gt;in&lt;/span&gt; range(&lt;span class=&quot;number&quot;&gt;100&lt;/span&gt;):&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            solver.test_nets[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;].forward()&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;            correct += sum(solver.test_nets[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;].blobs[&lt;span class=&quot;string&quot;&gt;&#39;score&#39;&lt;/span&gt;].data.argmax(&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                           == solver.test_nets[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;].blobs[&lt;span class=&quot;string&quot;&gt;&#39;label&#39;&lt;/span&gt;].data)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        test_acc[it // test_interval] = correct / &lt;span class=&quot;number&quot;&gt;1e4&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;_, ax1 = subplots()&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;ax2 = ax1.twinx()&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;ax1.plot(arange(niter), train_loss)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;ax2.plot(test_interval * arange(len(test_acc)), test_acc, &lt;span class=&quot;string&quot;&gt;&#39;r&#39;&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;ax1.set_xlabel(&lt;span class=&quot;string&quot;&gt;&#39;iteration&#39;&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;ax1.set_ylabel(&lt;span class=&quot;string&quot;&gt;&#39;train loss&#39;&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;ax2.set_ylabel(&lt;span class=&quot;string&quot;&gt;&#39;test accuracy&#39;&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;ax2.set_title(&lt;span class=&quot;string&quot;&gt;&#39;Custom Test Accuracy: &amp;#123;:.2f&amp;#125;&#39;&lt;/span&gt;.format(test_acc[&lt;span class=&quot;number&quot;&gt;-1&lt;/span&gt;]))&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;h3 id=&quot;参考&quot;&gt;&lt;a href=&quot;#参考&quot; class=&quot;headerlink&quot; title=&quot;参考&quot;&gt;&lt;/a&gt;参考&lt;/h3&gt;&lt;p&gt;&lt;a href=&quot;http://nbviewer.jupyter.org/github/BVLC/caffe/blob/master/examples/01-learning-lenet.ipynb&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;Solving in Python with LeNet&lt;/a&gt;&lt;/p&gt;
</content>
    
    <summary type="html">
    
      &lt;p&gt;&lt;center&gt;&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-5-5/41421657.jpg&quot; alt=&quot;&quot;&gt;&lt;br&gt;&lt;/center&gt;&lt;br&gt;
    
    </summary>
    
    
      <category term="Python" scheme="http://buptldy.github.io/tags/Python/"/>
    
      <category term="Deep Learning" scheme="http://buptldy.github.io/tags/Deep-Learning/"/>
    
      <category term="Caffe" scheme="http://buptldy.github.io/tags/Caffe/"/>
    
  </entry>
  
  <entry>
    <title>Classification with Caffenet</title>
    <link href="http://buptldy.github.io/2016/05/03/2016-05-03-Classification%20with%20Caffenet/"/>
    <id>http://buptldy.github.io/2016/05/03/2016-05-03-Classification with Caffenet/</id>
    <published>2016-05-03T02:00:00.000Z</published>
    <updated>2016-10-04T05:27:29.942Z</updated>
    
    <content type="html">&lt;center&gt;&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-5-3/46730593.jpg&quot; alt=&quot;&quot;&gt;&lt;br&gt;&lt;/center&gt;

&lt;a id=&quot;more&quot;&gt;&lt;/a&gt;
&lt;p&gt;Caffe直接使用训练好的CaffeNet模型来进行分类，Caffe的安装有很多教程，&lt;a href=&quot;http://ixez.info/?p=105&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;千秋轻松装Caffe教程（含CUDA 7.0和CuDNN）
&lt;/a&gt;这个教程说的很详细，其中比较繁琐的就是CUDA的安装了，可以参考这里：&lt;a href=&quot;http://buptldy.github.io/2016/04/09/2016-04-09-Deepin%20CUDA%E5%AE%89%E8%A3%85%E5%8F%8AKeras%E4%BD%BF%E7%94%A8GPU%E6%A8%A1%E5%BC%8F%E8%BF%90%E8%A1%8C/&quot;&gt;Deepin CUDA安装及Keras使用GPU模式运行&lt;/a&gt;。其中遇到的一个比较大的坑就是cuDNN的安装，首先得确定你的GPU是否支持cuDNN，cuDNN要求GPU的计算能力在3.0以上，这里&lt;a href=&quot;http://developer.nvidia.com/cuda-gpus&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt; http://developer.nvidia.com/cuda-gpus&lt;/a&gt;可以查询GPU的计算能力，也能查询你的GPU是否支持CUDA，如果你的GPU不支持cuDNN但是支持CUDA，在编译配置文件注释掉&lt;code&gt;USE_CUDNN :=1&lt;/code&gt;和&lt;code&gt;CPU_ONLY :=1&lt;/code&gt;就可以使用CUDA了。如果你的GPU支持GUDA和cuDNN，得注意你下的Caffe所支持cuDNN的版本，这里可以查看&lt;a href=&quot;http://caffe.berkeleyvision.org/installation.html&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;http://caffe.berkeleyvision.org/installation.html&lt;/a&gt;。&lt;/p&gt;
&lt;p&gt;在这里我们比较下CPU和GPU模式下，网络的运行速度，并了解模型特征的提取。&lt;/p&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;导入Python,numpy,matplotlib&lt;/p&gt;
&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;import&lt;/span&gt; numpy &lt;span class=&quot;keyword&quot;&gt;as&lt;/span&gt; np&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;import&lt;/span&gt; matplotlib.pyplot &lt;span class=&quot;keyword&quot;&gt;as&lt;/span&gt; plt&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;%matplotlib inline&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;# set display defaults&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;plt.rcParams[&lt;span class=&quot;string&quot;&gt;&#39;figure.figsize&#39;&lt;/span&gt;] = (&lt;span class=&quot;number&quot;&gt;10&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;10&lt;/span&gt;)        &lt;span class=&quot;comment&quot;&gt;# large images&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;plt.rcParams[&lt;span class=&quot;string&quot;&gt;&#39;image.interpolation&#39;&lt;/span&gt;] = &lt;span class=&quot;string&quot;&gt;&#39;nearest&#39;&lt;/span&gt;  &lt;span class=&quot;comment&quot;&gt;# don&#39;t interpolate: show square pixels&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;plt.rcParams[&lt;span class=&quot;string&quot;&gt;&#39;image.cmap&#39;&lt;/span&gt;] = &lt;span class=&quot;string&quot;&gt;&#39;gray&#39;&lt;/span&gt;  &lt;span class=&quot;comment&quot;&gt;# use grayscale output rather than a (potentially misleading) color heatmap&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;导入caffe，其中注意caffe的路径设置&lt;/p&gt;
&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;import&lt;/span&gt; sys&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;caffe_root=&lt;span class=&quot;string&quot;&gt;&#39;/home/ldy/workspace/caffe/&#39;&lt;/span&gt; &lt;span class=&quot;comment&quot;&gt;#设置你caffe的安装目录&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;sys.path.insert(&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;,caffe_root+&lt;span class=&quot;string&quot;&gt;&#39;python&#39;&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;import&lt;/span&gt; caffe                            &lt;span class=&quot;comment&quot;&gt;#导入caffe&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;第一次运行需要联网下载模型&lt;/p&gt;
&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;import&lt;/span&gt; os&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; os.path.isfile(caffe_root + &lt;span class=&quot;string&quot;&gt;&#39;models/bvlc_reference_caffenet/bvlc_reference_caffenet.caffemodel&#39;&lt;/span&gt;):&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;&#39;CaffeNet found.&#39;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt;:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;&#39;Downloading pre-trained CaffeNet model...&#39;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    !/home/ldy/workspace/caffe/scripts/download_model_binary.py /home/ldy/workspace/caffe/models/bvlc_reference_caffenet&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;pre&gt;&lt;code&gt;CaffeNet found.
&lt;/code&gt;&lt;/pre&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;设置CPU模式并从本地加载网络&lt;/p&gt;
&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;caffe.set_mode_cpu()&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;model_def = caffe_root + &lt;span class=&quot;string&quot;&gt;&#39;models/bvlc_reference_caffenet/deploy.prototxt&#39;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;model_weights = caffe_root + &lt;span class=&quot;string&quot;&gt;&#39;models/bvlc_reference_caffenet/bvlc_reference_caffenet.caffemodel&#39;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;net = caffe.Net(model_def,      &lt;span class=&quot;comment&quot;&gt;# defines the structure of the model&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                model_weights,  &lt;span class=&quot;comment&quot;&gt;# contains the trained weights&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                caffe.TEST)     &lt;span class=&quot;comment&quot;&gt;# use test mode (e.g., don&#39;t perform dropout)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;设置输入处理&lt;/p&gt;
&lt;p&gt;CaffeNet默认的输入图像格式是BGR模式，像素值是[0,255]然后减去ImageNet的像素平均值，而且图像通道的维数是在第一维。&lt;/p&gt;
&lt;p&gt;matplotlib导入图像的格式是RGB,像素值的范围是[0,1]，通道维数在第三维，所以我们需要进行转换。&lt;br&gt;&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;# load the mean ImageNet image (as distributed with Caffe) for subtraction&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;mu = np.load(caffe_root + &lt;span class=&quot;string&quot;&gt;&#39;python/caffe/imagenet/ilsvrc_2012_mean.npy&#39;&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;mu = mu.mean(&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;).mean(&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;)  &lt;span class=&quot;comment&quot;&gt;# average over pixels to obtain the mean (BGR) pixel values&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;&#39;mean-subtracted values:&#39;&lt;/span&gt;, zip(&lt;span class=&quot;string&quot;&gt;&#39;BGR&#39;&lt;/span&gt;, mu)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;# create transformer for the input called &#39;data&#39;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;transformer = caffe.io.Transformer(&amp;#123;&lt;span class=&quot;string&quot;&gt;&#39;data&#39;&lt;/span&gt;: net.blobs[&lt;span class=&quot;string&quot;&gt;&#39;data&#39;&lt;/span&gt;].data.shape&amp;#125;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;transformer.set_transpose(&lt;span class=&quot;string&quot;&gt;&#39;data&#39;&lt;/span&gt;, (&lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;,&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;,&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;))  &lt;span class=&quot;comment&quot;&gt;# move image channels to outermost dimension&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;transformer.set_mean(&lt;span class=&quot;string&quot;&gt;&#39;data&#39;&lt;/span&gt;, mu)            &lt;span class=&quot;comment&quot;&gt;# subtract the dataset-mean value in each channel&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;transformer.set_raw_scale(&lt;span class=&quot;string&quot;&gt;&#39;data&#39;&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;255&lt;/span&gt;)      &lt;span class=&quot;comment&quot;&gt;# rescale from [0, 1] to [0, 255]&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;transformer.set_channel_swap(&lt;span class=&quot;string&quot;&gt;&#39;data&#39;&lt;/span&gt;, (&lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;,&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;,&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;))  &lt;span class=&quot;comment&quot;&gt;# swap channels from RGB to BGR&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;mean-subtracted values: [(&amp;apos;B&amp;apos;, 104.0069879317889), (&amp;apos;G&amp;apos;, 116.66876761696767), (&amp;apos;R&amp;apos;, 122.6789143406786)]
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&quot;CPU模式分类&quot;&gt;&lt;a href=&quot;#CPU模式分类&quot; class=&quot;headerlink&quot; title=&quot;CPU模式分类&quot;&gt;&lt;/a&gt;CPU模式分类&lt;/h2&gt;&lt;p&gt;设置输入的大小&lt;/p&gt;
&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;# set the size of the input (we can skip this if we&#39;re happy&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;#  with the default; we can also change it later, e.g., for different batch sizes)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;net.blobs[&lt;span class=&quot;string&quot;&gt;&#39;data&#39;&lt;/span&gt;].reshape(&lt;span class=&quot;number&quot;&gt;50&lt;/span&gt;,        &lt;span class=&quot;comment&quot;&gt;# batch size&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                          &lt;span class=&quot;number&quot;&gt;3&lt;/span&gt;,         &lt;span class=&quot;comment&quot;&gt;# 3-channel (BGR) images&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                          &lt;span class=&quot;number&quot;&gt;227&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;227&lt;/span&gt;)  &lt;span class=&quot;comment&quot;&gt;# image size is 227x227&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;加载图片并转换&lt;/p&gt;
&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;image = caffe.io.load_image(caffe_root + &lt;span class=&quot;string&quot;&gt;&#39;examples/images/cat.jpg&#39;&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;transformed_image = transformer.preprocess(&lt;span class=&quot;string&quot;&gt;&#39;data&#39;&lt;/span&gt;, image)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;plt.imshow(image)&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;matplotlib.image.AxesImage at 0x7f7ba44f0a50&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;center&gt;&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-5-3/52956146.jpg&quot; alt=&quot;&quot;&gt;&lt;br&gt;&lt;/center&gt;

&lt;p&gt;进行分类&lt;/p&gt;
&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;# copy the image data into the memory allocated for the net&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;net.blobs[&lt;span class=&quot;string&quot;&gt;&#39;data&#39;&lt;/span&gt;].data[...] = transformed_image&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;### perform classification&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;output = net.forward()&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;output_prob = output[&lt;span class=&quot;string&quot;&gt;&#39;prob&#39;&lt;/span&gt;][&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;]  &lt;span class=&quot;comment&quot;&gt;# the output probability vector for the first image in the batch&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;&#39;predicted class is:&#39;&lt;/span&gt;, output_prob.argmax()&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;pre&gt;&lt;code&gt;predicted class is: 281
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;从上面的输出，我们得到输入的图片得到的类别可能是第281类，但是并不知道它对应的标签，下面我们来加载ImageNet的标签(首次需要联网)。&lt;/p&gt;
&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;# load ImageNet labels&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;labels_file = caffe_root + &lt;span class=&quot;string&quot;&gt;&#39;data/ilsvrc12/synset_words.txt&#39;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;not&lt;/span&gt; os.path.exists(labels_file):&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    !/home/ldy/workspace/caffe/data/ilsvrc12/get_ilsvrc_aux.sh&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;labels = np.loadtxt(labels_file, str, delimiter=&lt;span class=&quot;string&quot;&gt;&#39;\t&#39;&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;&#39;output label:&#39;&lt;/span&gt;, labels[output_prob.argmax()]&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;pre&gt;&lt;code&gt;Downloading...
--2016-05-03 10:54:43--  http://dl.caffe.berkeleyvision.org/caffe_ilsvrc12.tar.gz
正在解析主机 dl.caffe.berkeleyvision.org (dl.caffe.berkeleyvision.org)... 169.229.222.251
正在连接 dl.caffe.berkeleyvision.org (dl.caffe.berkeleyvision.org)|169.229.222.251|:80... 已连接。
已发出 HTTP 请求，正在等待回应... 200 OK
长度：17858008 (17M) [application/octet-stream]
正在保存至: “caffe_ilsvrc12.tar.gz”

caffe_ilsvrc12.tar. 100%[===================&amp;gt;]  17.03M  2.54MB/s    in 8.9s    

2016-05-03 10:54:53 (1.91 MB/s) - 已保存 “caffe_ilsvrc12.tar.gz” [17858008/17858008])

Unzipping...
Done.
output label: n02123045 tabby, tabby cat
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;现在我们得到了输出为｀tabby cat｀，如果我们想得到其他的可能类别，如下所示：&lt;/p&gt;
&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;# sort top five predictions from softmax output&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;top_inds = output_prob.argsort()[::&lt;span class=&quot;number&quot;&gt;-1&lt;/span&gt;][:&lt;span class=&quot;number&quot;&gt;5&lt;/span&gt;]  &lt;span class=&quot;comment&quot;&gt;# reverse sort and take five largest items&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;&#39;probabilities and labels:&#39;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;zip(output_prob[top_inds], labels[top_inds])&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;pre&gt;&lt;code&gt;probabilities and labels:
[(0.31243625, &amp;apos;n02123045 tabby, tabby cat&amp;apos;),
 (0.23797135, &amp;apos;n02123159 tiger cat&amp;apos;),
 (0.12387258, &amp;apos;n02124075 Egyptian cat&amp;apos;),
 (0.10075716, &amp;apos;n02119022 red fox, Vulpes vulpes&amp;apos;),
 (0.070957333, &amp;apos;n02127052 lynx, catamount&amp;apos;)]
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&quot;切换到GPU模式&quot;&gt;&lt;a href=&quot;#切换到GPU模式&quot; class=&quot;headerlink&quot; title=&quot;切换到GPU模式&quot;&gt;&lt;/a&gt;切换到GPU模式&lt;/h2&gt;&lt;p&gt;查看CPU模式花费的时间&lt;/p&gt;
&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;%timeit net.forward()&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;pre&gt;&lt;code&gt;1 loop, best of 3: 8.87 s per loop
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;切换到GPU模式，查看花费时间&lt;/p&gt;
&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;#caffe.set_device(0)  # if we have multiple GPUs, pick the first one&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;caffe.set_mode_gpu()&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;net.forward()  &lt;span class=&quot;comment&quot;&gt;# run once before timing to set up memory&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;%timeit net.forward()&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;pre&gt;&lt;code&gt;1 loop, best of 3: 2.27 s per loop
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;##查看中间输入&lt;/p&gt;
&lt;p&gt;神经网络不仅仅是一个黑盒子，我们可以查看一些中间结果和参数。&lt;/p&gt;
&lt;p&gt;查看激活函数输出的数据维数，格式为(batch_size, channel_dim, height, width)。&lt;/p&gt;
&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;# for each layer, show the output shape&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; layer_name, blob &lt;span class=&quot;keyword&quot;&gt;in&lt;/span&gt; net.blobs.iteritems():&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;print&lt;/span&gt; layer_name + &lt;span class=&quot;string&quot;&gt;&#39;\t&#39;&lt;/span&gt; + str(blob.data.shape)&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;pre&gt;&lt;code&gt;data    (50, 3, 227, 227)
conv1    (50, 96, 55, 55)
pool1    (50, 96, 27, 27)
norm1    (50, 96, 27, 27)
conv2    (50, 256, 27, 27)
pool2    (50, 256, 13, 13)
norm2    (50, 256, 13, 13)
conv3    (50, 384, 13, 13)
conv4    (50, 384, 13, 13)
conv5    (50, 256, 13, 13)
pool5    (50, 256, 6, 6)
fc6    (50, 4096)
fc7    (50, 4096)
fc8    (50, 1000)
prob    (50, 1000)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;查看权值参数的维数，权值格式为(output_channels, input_channels, filter_height, filter_width)，偏置的格式为(output_channels,)。&lt;/p&gt;
&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; layer_name, param &lt;span class=&quot;keyword&quot;&gt;in&lt;/span&gt; net.params.iteritems():&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;print&lt;/span&gt; layer_name + &lt;span class=&quot;string&quot;&gt;&#39;\t&#39;&lt;/span&gt; + str(param[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;].data.shape), str(param[&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;].data.shape)&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;pre&gt;&lt;code&gt;conv1    (96, 3, 11, 11) (96,)
conv2    (256, 48, 5, 5) (256,)
conv3    (384, 256, 3, 3) (384,)
conv4    (384, 192, 3, 3) (384,)
conv5    (256, 192, 3, 3) (256,)
fc6    (4096, 9216) (4096,)
fc7    (4096, 4096) (4096,)
fc8    (1000, 4096) (1000,)
&lt;/code&gt;&lt;/pre&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;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;vis_square&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(data)&lt;/span&gt;:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;string&quot;&gt;&quot;&quot;&quot;Take an array of shape (n, height, width) or (n, height, width, 3)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;       and visualize each (height, width) thing in a grid of size approx. sqrt(n) by sqrt(n)&quot;&quot;&quot;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;# normalize data for display&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    data = (data - data.min()) / (data.max() - data.min())&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;# force the number of filters to be square&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    n = int(np.ceil(np.sqrt(data.shape[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;])))&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    padding = (((&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;, n ** &lt;span class=&quot;number&quot;&gt;2&lt;/span&gt; - data.shape[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;]),&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;               (&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;), (&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;))                 &lt;span class=&quot;comment&quot;&gt;# add some space between filters&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;               + ((&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;),) * (data.ndim - &lt;span class=&quot;number&quot;&gt;3&lt;/span&gt;))  &lt;span class=&quot;comment&quot;&gt;# don&#39;t pad the last dimension (if there is one)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    data = np.pad(data, padding, mode=&lt;span class=&quot;string&quot;&gt;&#39;constant&#39;&lt;/span&gt;, constant_values=&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;)  &lt;span class=&quot;comment&quot;&gt;# pad with ones (white)&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;# tile the filters into an image&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    data = data.reshape((n, n) + data.shape[&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;:]).transpose((&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;3&lt;/span&gt;) + tuple(range(&lt;span class=&quot;number&quot;&gt;4&lt;/span&gt;, data.ndim + &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;)))&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    data = data.reshape((n * data.shape[&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;], n * data.shape[&lt;span class=&quot;number&quot;&gt;3&lt;/span&gt;]) + data.shape[&lt;span class=&quot;number&quot;&gt;4&lt;/span&gt;:])&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    plt.imshow(data); plt.axis(&lt;span class=&quot;string&quot;&gt;&#39;off&#39;&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;第一层卷积滤波器&lt;br&gt;&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;# the parameters are a list of [weights, biases]&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;filters = net.params[&lt;span class=&quot;string&quot;&gt;&#39;conv1&#39;&lt;/span&gt;][&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;].data&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;vis_square(filters.transpose(&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;3&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;))&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;center&gt;&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-5-3/10647296.jpg&quot; alt=&quot;&quot;&gt;&lt;br&gt;&lt;/center&gt;

&lt;p&gt;第一层卷积层的输出&lt;br&gt;&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;feat = net.blobs[&lt;span class=&quot;string&quot;&gt;&#39;conv1&#39;&lt;/span&gt;].data[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;, :&lt;span class=&quot;number&quot;&gt;36&lt;/span&gt;]&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;vis_square(feat)&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;center&gt;&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-5-3/25648526.jpg&quot; alt=&quot;&quot;&gt;&lt;br&gt;&lt;/center&gt;

&lt;p&gt;第五层pooling之后的输出&lt;br&gt;&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;feat = net.blobs[&lt;span class=&quot;string&quot;&gt;&#39;pool5&#39;&lt;/span&gt;].data[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;]&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;vis_square(feat)&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;center&gt;&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-5-3/47782240.jpg&quot; alt=&quot;&quot;&gt;&lt;br&gt;&lt;/center&gt;

&lt;p&gt;第一个全连接层的输出&lt;/p&gt;
&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;feat = net.blobs[&lt;span class=&quot;string&quot;&gt;&#39;fc6&#39;&lt;/span&gt;].data[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;]&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;plt.subplot(&lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;plt.plot(feat.flat)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;plt.subplot(&lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;_ = plt.hist(feat.flat[feat.flat &amp;gt; &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;], bins=&lt;span class=&quot;number&quot;&gt;100&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;center&gt;&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-5-3/71842859.jpg&quot; alt=&quot;&quot;&gt;&lt;br&gt;&lt;/center&gt;

&lt;p&gt;最后的类别概率输出&lt;br&gt;&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;feat = net.blobs[&lt;span class=&quot;string&quot;&gt;&#39;prob&#39;&lt;/span&gt;].data[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;]&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;plt.figure(figsize=(&lt;span class=&quot;number&quot;&gt;15&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;3&lt;/span&gt;))&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;plt.plot(feat.flat)&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[&amp;lt;matplotlib.lines.Line2D at 0x7f7ba0177d10&amp;gt;]
&lt;/code&gt;&lt;/pre&gt;&lt;center&gt;&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-5-3/77194220.jpg&quot; alt=&quot;&quot;&gt;&lt;br&gt;&lt;/center&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;/p&gt;
&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;# download an image&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;#my_image_url = &quot;...&quot;  # paste your URL here&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;# for example:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;my_image_url = &lt;span class=&quot;string&quot;&gt;&quot;https://upload.wikimedia.org/wikipedia/commons/b/be/Orang_Utan%2C_Semenggok_Forest_Reserve%2C_Sarawak%2C_Borneo%2C_Malaysia.JPG&quot;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;!wget -O image.jpg $my_image_url&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;# transform it and copy it into the net&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;image = caffe.io.load_image(&lt;span class=&quot;string&quot;&gt;&#39;image.jpg&#39;&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;net.blobs[&lt;span class=&quot;string&quot;&gt;&#39;data&#39;&lt;/span&gt;].data[...] = transformer.preprocess(&lt;span class=&quot;string&quot;&gt;&#39;data&#39;&lt;/span&gt;, image)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;# perform classification&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;net.forward()&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;# obtain the output probabilities&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;output_prob = net.blobs[&lt;span class=&quot;string&quot;&gt;&#39;prob&#39;&lt;/span&gt;].data[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;]&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;# sort top five predictions from softmax output&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;top_inds = output_prob.argsort()[::&lt;span class=&quot;number&quot;&gt;-1&lt;/span&gt;][:&lt;span class=&quot;number&quot;&gt;5&lt;/span&gt;]&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;plt.imshow(image)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;&#39;probabilities and labels:&#39;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;zip(output_prob[top_inds], labels[top_inds])&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;pre&gt;&lt;code&gt;--2016-05-03 11:23:33--  https://upload.wikimedia.org/wikipedia/commons/b/be/Orang_Utan%2C_Semenggok_Forest_Reserve%2C_Sarawak%2C_Borneo%2C_Malaysia.JPG
正在解析主机 upload.wikimedia.org (upload.wikimedia.org)... 2620:0:863:ed1a::2:b, 2620:0:863:ed1a::2:b, 198.35.26.112, ...
正在连接 upload.wikimedia.org (upload.wikimedia.org)|2620:0:863:ed1a::2:b|:443... 已连接。
已发出 HTTP 请求，正在等待回应... 200 OK
长度：1443340 (1.4M) [image/jpeg]
正在保存至: “image.jpg”

image.jpg           100%[===================&amp;gt;]   1.38M  1.41MB/s    in 1.0s    

2016-05-03 11:23:35 (1.41 MB/s) - 已保存 “image.jpg” [1443340/1443340])

probabilities and labels:

[(0.9680779, &amp;apos;n02480495 orangutan, orang, orangutang, Pongo pygmaeus&amp;apos;),
 (0.030589299, &amp;apos;n02492660 howler monkey, howler&amp;apos;),
 (0.00085892546, &amp;apos;n02493509 titi, titi monkey&amp;apos;),
 (0.00015429084, &amp;apos;n02493793 spider monkey, Ateles geoffroyi&amp;apos;),
 (7.2596376e-05, &amp;apos;n02488291 langur&amp;apos;)]
&lt;/code&gt;&lt;/pre&gt;&lt;center&gt;&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-5-3/25241651.jpg&quot; alt=&quot;&quot;&gt;&lt;br&gt;&lt;/center&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;http://nbviewer.jupyter.org/github/BVLC/caffe/blob/master/examples/00-classification.ipynb&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;Classification: Instant Recognition with Caffe&lt;/a&gt;&lt;/p&gt;
</content>
    
    <summary type="html">
    
      &lt;center&gt;&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-5-3/46730593.jpg&quot; alt=&quot;&quot;&gt;&lt;br&gt;&lt;/center&gt;
    
    </summary>
    
    
      <category term="Deep Learning" scheme="http://buptldy.github.io/tags/Deep-Learning/"/>
    
      <category term="Caffe" scheme="http://buptldy.github.io/tags/Caffe/"/>
    
  </entry>
  
  <entry>
    <title>Vim Cheat SHeet</title>
    <link href="http://buptldy.github.io/2016/04/23/2016-04-23-Vim/"/>
    <id>http://buptldy.github.io/2016/04/23/2016-04-23-Vim/</id>
    <published>2016-04-23T03:00:00.000Z</published>
    <updated>2016-10-04T05:09:17.297Z</updated>
    
    <content type="html">&lt;p&gt;&lt;center&gt;&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-4-23/88022819.jpg&quot; alt=&quot;&quot;&gt;&lt;br&gt;&lt;/center&gt;&lt;br&gt;&lt;a id=&quot;more&quot;&gt;&lt;/a&gt;&lt;/p&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;ol&gt;
&lt;li&gt;&lt;p&gt;光标在屏幕文本中的移动既可以用箭头键，也可以使用 hjkl 字母键。&lt;br&gt;h (左移)    j (下行)       k (上行)        l (右移)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;欲进入 Vim 编辑器(从命令行提示符)，请输入：vim 文件名 &amp;lt;回车&amp;gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;欲退出 Vim 编辑器，请输入 &lt;esc&gt;   :q!   &amp;lt;回车&amp;gt; 放弃所有改动。或者输入 &lt;esc&gt;   :wq   &amp;lt;回车&amp;gt; 保存改动。&lt;/esc&gt;&lt;/esc&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;在正常模式下删除光标所在位置的字符，请按： x&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;欲插入或添加文本，请输入：&lt;/p&gt;
&lt;p&gt;i   输入欲插入文本   &lt;esc&gt;        在光标前插入文本&lt;br&gt;A   输入欲添加文本   &lt;esc&gt;             在一行后添加文本&lt;/esc&gt;&lt;/esc&gt;&lt;/p&gt;
&lt;p&gt;特别提示：按下 &lt;esc&gt; 键会带您回到正常模式或者撤消一个不想输入或部分完整的命令。&lt;/esc&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&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;ol&gt;
&lt;li&gt;欲从当前光标删除至下一个单词，请输入：dw&lt;/li&gt;
&lt;li&gt;欲从当前光标删除至当前行末尾，请输入：d$&lt;/li&gt;
&lt;li&gt;&lt;p&gt;欲删除整行，请输入：dd&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;欲重复一个动作，请在它前面加上一个数字：2w&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;在正常模式下修改命令的格式是：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;operator   [number]   motion
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;其中：&lt;br&gt;operator - 操作符，代表要做的事情，比如 d 代表删除&lt;br&gt;[number] - 可以附加的数字，代表动作重复的次数&lt;br&gt;motion   - 动作，代表在所操作的文本上的移动，例如 w 代表单词(word)，&lt;br&gt;$ 代表行末等等。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;欲移动光标到行首，请按数字0键：0&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;欲撤消以前的操作，请输入：u (小写的u)&lt;br&gt;欲撤消在一行中所做的改动，请输入：U (大写的U)&lt;br&gt;欲撤消以前的撤消命令，恢复以前的操作结果，请输入：CTRL-R&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&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;ol&gt;
&lt;li&gt;&lt;p&gt;要重新置入已经删除的文本内容，请按小写字母 p 键。该操作可以将已删除&lt;br&gt;的文本内容置于光标之后。如果最后一次删除的是一个整行，那么该行将置&lt;br&gt;于当前光标所在行的下一行。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;要替换光标所在位置的字符，请输入小写的 r 和要替换掉原位置字符的新字&lt;br&gt;符即可。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;更改类命令允许您改变从当前光标所在位置直到动作指示的位置中间的文本。&lt;br&gt;比如输入 ce 可以替换当前光标到单词的末尾的内容；输入 c$ 可以替换当&lt;br&gt;前光标到行末的内容。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;更改类命令的格式是：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;c   [number]   motion
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;/ol&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;ol&gt;
&lt;li&gt;&lt;p&gt;CTRL-G 用于显示当前光标所在位置和文件状态信息。&lt;br&gt;G 用于将光标跳转至文件最后一行。&lt;br&gt;先敲入一个行号然后输入大写 G 则是将光标移动至该行号代表的行。&lt;br&gt;gg 用于将光标跳转至文件第一行。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;输入 / 然后紧随一个字符串是在当前所编辑的文档中正向查找该字符串。&lt;br&gt;输入 ? 然后紧随一个字符串则是在当前所编辑的文档中反向查找该字符串。&lt;br&gt;完成一次查找之后按 n 键是重复上一次的命令，可在同一方向上查&lt;br&gt;找下一个匹配字符串所在；或者按大写 N 向相反方向查找下一匹配字符串所在。&lt;br&gt;CTRL-O 带您跳转回较旧的位置，CTRL-I 则带您到较新的位置。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;如果光标当前位置是括号(、)、[、]、{、}，按 % 会将光标移动到配对的括号上。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;在一行内替换头一个字符串 old 为新的字符串 new，请输入  :s/old/new&lt;br&gt;在一行内替换所有的字符串 old 为新的字符串 new，请输入  :s/old/new/g&lt;br&gt;在两行内替换所有的字符串 old 为新的字符串 new，请输入  :#,#s/old/new/g&lt;br&gt;在文件内替换所有的字符串 old 为新的字符串 new，请输入  :%s/old/new/g&lt;br&gt;进行全文替换时询问用户确认每个替换需添加 c 标志        :%s/old/new/gc&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;在-VIM-内执行外部命令的方法&quot;&gt;&lt;a href=&quot;#在-VIM-内执行外部命令的方法&quot; class=&quot;headerlink&quot; title=&quot;在 VIM 内执行外部命令的方法&quot;&gt;&lt;/a&gt;在 VIM 内执行外部命令的方法&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;&lt;p&gt;:!command 用于执行一个外部命令 command。&lt;/p&gt;
&lt;p&gt;请看一些实际例子：&lt;br&gt; :!dir           :!ls           -  用于显示当前目录的内容。&lt;br&gt; :!del FILENAME   :!rm FILENAME   -  用于删除名为 FILENAME 的文件。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;:w FILENAME  可将当前 VIM 中正在编辑的文件保存到名为 FILENAME 的文件中。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;v motion :w FILENAME 可将当前编辑文件中可视模式下选中的内容保存到文件FILENAME 中。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;:r FILENAME 可提取磁盘文件 FILENAME 并将其插入到当前文件的光标位置后面。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;:r !dir 可以读取 dir 命令的输出并将其放置到当前文件的光标位置后面。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&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;ol&gt;
&lt;li&gt;&lt;p&gt;输入小写的 o 可以在光标下方打开新的一行并进入插入模式。&lt;br&gt;输入大写的 O 可以在光标上方打开新的一行。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;输入小写的 a 可以在光标所在位置之后插入文本。&lt;br&gt;输入大写的 A 可以在光标所在行的行末之后插入文本。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;e 命令可以使光标移动到单词末尾。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;操作符 y 复制文本，p 粘贴先前复制的文本。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;输入大写的 R 将进入替换模式，直至按 &lt;esc&gt; 键回到正常模式。&lt;/esc&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;输入 :set xxx 可以设置 xxx 选项。一些有用的选项如下：&lt;br&gt;‘ic’ ‘ignorecase’    查找时忽略字母大小写&lt;br&gt;‘is’ ‘incsearch’    查找短语时显示部分匹配&lt;br&gt;‘hls’ ‘hlsearch’    高亮显示所有的匹配短语&lt;br&gt;选项名可以用完整版本，也可以用缩略版本。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;在选项前加上 no 可以关闭选项：  :set noic&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&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;ol&gt;
&lt;li&gt;&lt;p&gt;输入 :help 或者按 &lt;f1&gt; 键或 &lt;help&gt; 键可以打开帮助窗口。&lt;/help&gt;&lt;/f1&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;输入 :help cmd 可以找到关于 cmd 命令的帮助。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;输入 CTRL-W CTRL-W  可以使您在窗口之间跳转。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;输入 :q 以关闭帮助窗口&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;您可以创建一个 vimrc 启动脚本文件用来保存您偏好的设置。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;当输入 : 命令时，按 CTRL-D 可以查看可能的补全结果。按 &lt;tab&gt; 可以使用一个补全。&lt;/tab&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
</content>
    
    <summary type="html">
    
      &lt;p&gt;&lt;center&gt;&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-4-23/88022819.jpg&quot; alt=&quot;&quot;&gt;&lt;br&gt;&lt;/center&gt;&lt;br&gt;
    
    </summary>
    
    
      <category term="Linux" scheme="http://buptldy.github.io/tags/Linux/"/>
    
  </entry>
  
  <entry>
    <title>Deepin CUDA Install and Run Keras on GPU</title>
    <link href="http://buptldy.github.io/2016/04/09/2016-04-09-Deepin%20CUDA%20Keras%20GPU/"/>
    <id>http://buptldy.github.io/2016/04/09/2016-04-09-Deepin CUDA Keras GPU/</id>
    <published>2016-04-09T03:00:00.000Z</published>
    <updated>2016-11-24T11:25:45.243Z</updated>
    
    <content type="html">&lt;center&gt;&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-4-9/8883646.jpg&quot; alt=&quot;&quot;&gt;&lt;br&gt;&lt;/center&gt;

&lt;a id=&quot;more&quot;&gt;&lt;/a&gt;
&lt;h1 id=&quot;Deepin简介&quot;&gt;&lt;a href=&quot;#Deepin简介&quot; class=&quot;headerlink&quot; title=&quot;Deepin简介&quot;&gt;&lt;/a&gt;Deepin简介&lt;/h1&gt;&lt;p&gt;&lt;a href=&quot;https://www.deepin.org/&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;Deepin&lt;/a&gt;是由武汉深之度科技有限公司开发的Linux发行版,Deepin 为所有人提供稳定、高效的操作系统，强调安全、易用、美观。其口号为“免除新手痛苦，节约老手时间”。&lt;/p&gt;
&lt;h1 id=&quot;cuda安装&quot;&gt;&lt;a href=&quot;#cuda安装&quot; class=&quot;headerlink&quot; title=&quot;cuda安装&quot;&gt;&lt;/a&gt;cuda安装&lt;/h1&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;按照系统的版本下载对应的cuda版本，下载地址：&lt;a href=&quot;https://developer.nvidia.com/cuda-downloads&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;https://developer.nvidia.com/cuda-downloads&lt;/a&gt;&lt;/p&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;注意执行安装文件的时候一定要加上’–­­override’，不然会出现错误：’”Toolkit: Installation Failed. Using unsupported Compiler.”‘&lt;br&gt;&lt;figure class=&quot;highlight plain&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;chmod 755 cuda_7.5.18_linux.run&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;sudo ./cuda_7.5.18_linux.run --­­override&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;如果你电脑里已经装好比cuda内置的NVIDIA驱动更新的版本，那么在安装的时候就不要选择安装NVIDIA驱动。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;安装过程的设置如下所示：&lt;br&gt;&lt;figure class=&quot;highlight plain&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;-------------------------------------------------------------&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;Do you accept the previously read EULA? (accept/decline/quit): accept&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;You are attempting to install on an unsupported configuration. Do you wish to continue? ((y)es/(n)o) [ default is no ]: y&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;Install NVIDIA Accelerated Graphics Driver for Linux-x86_64 352.39? ((y)es/(n)o/(q)uit): n&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;Install the CUDA 7.5 Toolkit? ((y)es/(n)o/(q)uit): y&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;Enter Toolkit Location [ default is /usr/local/cuda-7.5 ]:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;Do you want to install a symbolic link at /usr/local/cuda? ((y)es/(n)o/(q)uit): y&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;Install the CUDA 7.5 Samples? ((y)es/(n)o/(q)uit): y&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;Enter CUDA Samples Location [ default is /home/kinghorn ]: /usr/local/cuda-7.5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;Installing the CUDA Toolkit in /usr/local/cuda-7.5 ...&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;Finished copying samples.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;===========&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;= Summary =&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;===========&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;Driver:   Not Selected&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;Toolkit:  Installed in /usr/local/cuda-7.5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;Samples:  Installed in /usr/local/cuda-7.5&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&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;打开~/.bashrc&lt;br&gt;&lt;figure class=&quot;highlight plain&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;gedit ~/.bashrc&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;添加下面两条语句：&lt;br&gt;&lt;figure class=&quot;highlight plain&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;export PATH=$PATH:/usr/local/cuda/bin&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/cuda/lib64&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;h2 id=&quot;强制cuda使用gcc-5&quot;&gt;&lt;a href=&quot;#强制cuda使用gcc-5&quot; class=&quot;headerlink&quot; title=&quot;强制cuda使用gcc 5&quot;&gt;&lt;/a&gt;强制cuda使用gcc 5&lt;/h2&gt;&lt;p&gt;因为cuda默认不使用gcc&amp;gt;4.8，通过注释掉报错行来强制使用gcc 5。&lt;br&gt;&lt;figure class=&quot;highlight plain&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;sudo gedit /usr/local/cuda/include/host_config.h&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;//注释掉115行&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;//#error -- unsupported GNU version! gcc versions later than 4.9 are not supported!&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;h2 id=&quot;运行cuda内置的例子&quot;&gt;&lt;a href=&quot;#运行cuda内置的例子&quot; class=&quot;headerlink&quot; title=&quot;运行cuda内置的例子&quot;&gt;&lt;/a&gt;运行cuda内置的例子&lt;/h2&gt;&lt;p&gt;为了测试是否安装成功&lt;/p&gt;
&lt;p&gt;进入内置例程&lt;br&gt;&lt;figure class=&quot;highlight plain&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;cd /usr/local/cuda/samples/1_Utilities/deviceQuery&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;编译&lt;br&gt;&lt;figure class=&quot;highlight plain&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;make&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;运行&lt;br&gt;&lt;figure class=&quot;highlight plain&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;./deviceQuery&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;得到结果：&lt;br&gt;&lt;figure class=&quot;highlight plain&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;CUDA Device Query (Runtime API) version (CUDART static linking)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;Detected 1 CUDA Capable device(s)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;Device 0: &amp;quot;GeForce GT 520M&amp;quot;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; CUDA Driver Version / Runtime Version          8.0 / 7.5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; CUDA Capability Major/Minor version number:    2.1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; Total amount of global memory:                 1024 MBytes (1073414144 bytes)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; ( 1) Multiprocessors, ( 48) CUDA Cores/MP:     48 CUDA Cores&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; GPU Max Clock rate:                            1480 MHz (1.48 GHz)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; Memory Clock rate:                             800 Mhz&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; Memory Bus Width:                              64-bit&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; L2 Cache Size:                                 65536 bytes&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; Maximum Texture Dimension Size (x,y,z)         1D=(65536), 2D=(65536, 65535), 3D=(2048, 2048, 2048)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; Maximum Layered 1D Texture Size, (num) layers  1D=(16384), 2048 layers&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; Maximum Layered 2D Texture Size, (num) layers  2D=(16384, 16384), 2048 layers&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; Total amount of constant memory:               65536 bytes&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; Total amount of shared memory per block:       49152 bytes&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; Total number of registers available per block: 32768&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; Warp size:                                     32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; Maximum number of threads per multiprocessor:  1536&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; Maximum number of threads per block:           1024&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; Max dimension size of a thread block (x,y,z): (1024, 1024, 64)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; Max dimension size of a grid size    (x,y,z): (65535, 65535, 65535)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; Maximum memory pitch:                          2147483647 bytes&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; Texture alignment:                             512 bytes&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; Concurrent copy and kernel execution:          Yes with 1 copy engine(s)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; Run time limit on kernels:                     No&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; Integrated GPU sharing Host Memory:            No&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; Support host page-locked memory mapping:       Yes&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; Alignment requirement for Surfaces:            Yes&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; Device has ECC support:                        Disabled&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; Device supports Unified Addressing (UVA):      Yes&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; Device PCI Domain ID / Bus ID / location ID:   0 / 1 / 0&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt; Compute Mode:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;lt; Default (multiple host threads can use ::cudaSetDevice() with device simultaneously) &amp;gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;deviceQuery, CUDA Driver = CUDART, CUDA Driver Version = 8.0, CUDA Runtime Version = 7.5, NumDevs = 1, Device0 = GeForce GT 520M&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;Result = PASS&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;如果编译出错，检查是否有强制设置gcc 5来编译；如果输出结果为fail，说明没有检查到显卡，解决方案是升级你的NVIDIA驱动，确保你电脑的NVIDIA驱动版本要不低于cuda的内置版本。&lt;/p&gt;
&lt;h1 id=&quot;设置Keras运行于GPU模式&quot;&gt;&lt;a href=&quot;#设置Keras运行于GPU模式&quot; class=&quot;headerlink&quot; title=&quot;设置Keras运行于GPU模式&quot;&gt;&lt;/a&gt;设置Keras运行于GPU模式&lt;/h1&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;br&gt;&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;THEANO_FLAGS=device=gpu,floatX=float32 python my_keras_script.py&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&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;设置$HOME/.theanorc文件&lt;/p&gt;
&lt;p&gt;添加如下所示文件&lt;br&gt;&lt;figure class=&quot;highlight plain&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;[global]&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;floatX = float32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;device = gpu&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;[lib]&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;cnmem = 0.9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;[cuda]&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;root = /usr/local/cuda&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&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;br&gt;&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;import&lt;/span&gt; theano&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;theano.config.device = &lt;span class=&quot;string&quot;&gt;&#39;gpu&#39;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;theano.config.floatX = &lt;span class=&quot;string&quot;&gt;&#39;float32&#39;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;我们来运行Keras里的一个用于电影评论情感分析的例子&lt;a href=&quot;https://github.com/fchollet/keras/blob/master/examples/imdb_cnn.py&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;imdb_cnn.py&lt;/a&gt;,第一次运行时需要联网，要下载数据库。&lt;br&gt;&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;42&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;43&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;44&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;45&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;46&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;47&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;48&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;49&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;50&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;51&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;52&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;53&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;54&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;55&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;56&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;57&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;58&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;59&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;60&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;61&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;62&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;63&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;64&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;65&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;66&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;67&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;68&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;69&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;70&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;71&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;72&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;73&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;74&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;75&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;string&quot;&gt;&#39;&#39;&#39;This example demonstrates the use of Convolution1D for text classification.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;Run on GPU: THEANO_FLAGS=mode=FAST_RUN,device=gpu,floatX=float32 python imdb_cnn.py&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;Get to 0.835 test accuracy after 2 epochs. 100s/epoch on K520 GPU.&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&#39;&#39;&#39;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;from&lt;/span&gt; __future__ &lt;span class=&quot;keyword&quot;&gt;import&lt;/span&gt; print_function&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;import&lt;/span&gt; numpy &lt;span class=&quot;keyword&quot;&gt;as&lt;/span&gt; np&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;np.random.seed(&lt;span class=&quot;number&quot;&gt;1337&lt;/span&gt;)  &lt;span class=&quot;comment&quot;&gt;# for reproducibility&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;from&lt;/span&gt; keras.preprocessing &lt;span class=&quot;keyword&quot;&gt;import&lt;/span&gt; sequence&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;from&lt;/span&gt; keras.models &lt;span class=&quot;keyword&quot;&gt;import&lt;/span&gt; Sequential&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;from&lt;/span&gt; keras.layers.core &lt;span class=&quot;keyword&quot;&gt;import&lt;/span&gt; Dense, Dropout, Activation, Flatten&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;from&lt;/span&gt; keras.layers.embeddings &lt;span class=&quot;keyword&quot;&gt;import&lt;/span&gt; Embedding&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;from&lt;/span&gt; keras.layers.convolutional &lt;span class=&quot;keyword&quot;&gt;import&lt;/span&gt; Convolution1D, MaxPooling1D&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;from&lt;/span&gt; keras.datasets &lt;span class=&quot;keyword&quot;&gt;import&lt;/span&gt; imdb&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;# set parameters:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;max_features = &lt;span class=&quot;number&quot;&gt;5000&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;maxlen = &lt;span class=&quot;number&quot;&gt;100&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;batch_size = &lt;span class=&quot;number&quot;&gt;32&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;embedding_dims = &lt;span class=&quot;number&quot;&gt;100&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;nb_filter = &lt;span class=&quot;number&quot;&gt;250&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;filter_length = &lt;span class=&quot;number&quot;&gt;3&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;hidden_dims = &lt;span class=&quot;number&quot;&gt;250&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;nb_epoch = &lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;print(&lt;span class=&quot;string&quot;&gt;&#39;Loading data...&#39;&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;(X_train, y_train), (X_test, y_test) = imdb.load_data(nb_words=max_features,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                                                      test_split=&lt;span class=&quot;number&quot;&gt;0.2&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;print(len(X_train), &lt;span class=&quot;string&quot;&gt;&#39;train sequences&#39;&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;print(len(X_test), &lt;span class=&quot;string&quot;&gt;&#39;test sequences&#39;&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;print(&lt;span class=&quot;string&quot;&gt;&#39;Pad sequences (samples x time)&#39;&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;X_train = sequence.pad_sequences(X_train, maxlen=maxlen)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;X_test = sequence.pad_sequences(X_test, maxlen=maxlen)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;print(&lt;span class=&quot;string&quot;&gt;&#39;X_train shape:&#39;&lt;/span&gt;, X_train.shape)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;print(&lt;span class=&quot;string&quot;&gt;&#39;X_test shape:&#39;&lt;/span&gt;, X_test.shape)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;print(&lt;span class=&quot;string&quot;&gt;&#39;Build model...&#39;&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;model = Sequential()&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;# we start off with an efficient embedding layer which maps&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;# our vocab indices into embedding_dims dimensions&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;model.add(Embedding(max_features, embedding_dims, input_length=maxlen))&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;model.add(Dropout(&lt;span class=&quot;number&quot;&gt;0.25&lt;/span&gt;))&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;# we add a Convolution1D, which will learn nb_filter&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;# word group filters of size filter_length:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;model.add(Convolution1D(nb_filter=nb_filter,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        filter_length=filter_length,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        border_mode=&lt;span class=&quot;string&quot;&gt;&#39;valid&#39;&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        activation=&lt;span class=&quot;string&quot;&gt;&#39;relu&#39;&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;                        subsample_length=&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;))&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;# we use standard max pooling (halving the output of the previous layer):&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;model.add(MaxPooling1D(pool_length=&lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;))&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;# We flatten the output of the conv layer,&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;# so that we can add a vanilla dense layer:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;model.add(Flatten())&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;# We add a vanilla hidden layer:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;model.add(Dense(hidden_dims))&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;model.add(Dropout(&lt;span class=&quot;number&quot;&gt;0.25&lt;/span&gt;))&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;model.add(Activation(&lt;span class=&quot;string&quot;&gt;&#39;relu&#39;&lt;/span&gt;))&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;# We project onto a single unit output layer, and squash it with a sigmoid:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;model.add(Dense(&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;))&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;model.add(Activation(&lt;span class=&quot;string&quot;&gt;&#39;sigmoid&#39;&lt;/span&gt;))&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;model.compile(loss=&lt;span class=&quot;string&quot;&gt;&#39;binary_crossentropy&#39;&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;              optimizer=&lt;span class=&quot;string&quot;&gt;&#39;rmsprop&#39;&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;model.fit(X_train, y_train, batch_size=batch_size,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;          nb_epoch=nb_epoch, show_accuracy=&lt;span class=&quot;keyword&quot;&gt;True&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;          validation_data=(X_test, y_test))&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;运行这个例子，在K520 GPU上是100s一次循环，我电脑显卡型号为GeForce GT 520M，大概需要175s一次循环，不过比在cpu上运行快多啦，在我这四年前旧电脑cpu上运行差不多要一个小时。&lt;/p&gt;
&lt;h1 id=&quot;参考&quot;&gt;&lt;a href=&quot;#参考&quot; class=&quot;headerlink&quot; title=&quot;参考&quot;&gt;&lt;/a&gt;参考&lt;/h1&gt;&lt;p&gt;&lt;a href=&quot;https://www.pugetsystems.com/labs/articles/NVIDIA-CUDA-with-Ubuntu-16-04-beta-on-a-laptop-if-you-just-cannot-wait-775/&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;    NVIDIA CUDA with Ubuntu 16.04 beta on a laptop&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://keras.io/faq/#how-can-i-run-keras-on-gpu&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;Keras FAQ&lt;/a&gt;&lt;/p&gt;
</content>
    
    <summary type="html">
    
      &lt;center&gt;&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-4-9/8883646.jpg&quot; alt=&quot;&quot;&gt;&lt;br&gt;&lt;/center&gt;
    
    </summary>
    
    
      <category term="Keras" scheme="http://buptldy.github.io/tags/Keras/"/>
    
      <category term="Deep Learning" scheme="http://buptldy.github.io/tags/Deep-Learning/"/>
    
      <category term="Cuda" scheme="http://buptldy.github.io/tags/Cuda/"/>
    
  </entry>
  
  <entry>
    <title>Keras Introduction</title>
    <link href="http://buptldy.github.io/2016/04/07/2016-04-07-Keras%20Introduction/"/>
    <id>http://buptldy.github.io/2016/04/07/2016-04-07-Keras Introduction/</id>
    <published>2016-04-07T03:00:00.000Z</published>
    <updated>2016-10-04T05:06:28.040Z</updated>
    
    <content type="html">&lt;center&gt;&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-4-7/16129390.jpg&quot; alt=&quot;&quot;&gt;&lt;br&gt;&lt;/center&gt;

&lt;h1 id=&quot;Keras-简介&quot;&gt;&lt;a href=&quot;#Keras-简介&quot; class=&quot;headerlink&quot; title=&quot;Keras 简介&quot;&gt;&lt;/a&gt;Keras 简介&lt;/h1&gt;&lt;p&gt;&lt;a href=&quot;http://keras.io/&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;Keras&lt;/a&gt;是一个用Python编写的基于 TensorFlow 和 Theano高度模块化的神经网络库。其最大的优点在于样例丰富，现有主流模型封装完美。复杂点的模型可以像搭积木一样搞出来，适合快速地搭建模型。&lt;/p&gt;
&lt;a id=&quot;more&quot;&gt;&lt;/a&gt;
&lt;p&gt;安装：&lt;br&gt;&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;sudo pip install keras&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;h1 id=&quot;Keras里的基本模块&quot;&gt;&lt;a href=&quot;#Keras里的基本模块&quot; class=&quot;headerlink&quot; title=&quot;Keras里的基本模块&quot;&gt;&lt;/a&gt;Keras里的基本模块&lt;/h1&gt;&lt;h2 id=&quot;optimizers&quot;&gt;&lt;a href=&quot;#optimizers&quot; class=&quot;headerlink&quot; title=&quot;optimizers&quot;&gt;&lt;/a&gt;optimizers&lt;/h2&gt;&lt;p&gt;Keras包含了很多优化方法。比如最常用的随机梯度下降法(SGD)，还有Adagrad、Adadelta、RMSprop、Adam等。下面通过具体的代码介绍一下优化器的使用方法。&lt;br&gt;在编译一个Keras模型时，优化器是2个参数之一（另外一个是损失函数）。看如下代码：&lt;/p&gt;
&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;model = Sequential()  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;model.add(Dense(&lt;span class=&quot;number&quot;&gt;64&lt;/span&gt;, init=&lt;span class=&quot;string&quot;&gt;&#39;uniform&#39;&lt;/span&gt;, input_dim=&lt;span class=&quot;number&quot;&gt;10&lt;/span&gt;))  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;model.add(Activation(&lt;span class=&quot;string&quot;&gt;&#39;tanh&#39;&lt;/span&gt;))  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;model.add(Activation(&lt;span class=&quot;string&quot;&gt;&#39;softmax&#39;&lt;/span&gt;))  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;sgd = SGD(lr=&lt;span class=&quot;number&quot;&gt;0.1&lt;/span&gt;, decay=&lt;span class=&quot;number&quot;&gt;1e-6&lt;/span&gt;, momentum=&lt;span class=&quot;number&quot;&gt;0.9&lt;/span&gt;, nesterov=&lt;span class=&quot;keyword&quot;&gt;True&lt;/span&gt;)  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;model.compile(loss=&lt;span class=&quot;string&quot;&gt;&#39;mean_squared_error&#39;&lt;/span&gt;, optimizer=sgd)&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;这个例子中是在调用compile之前实例化了一个优化器。我们也可以通过传递名字的方式调用默认的优化器。代码如下：&lt;/p&gt;
&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;# passoptimizer by name: default parameters will be used  &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;model.compile(loss=&lt;span class=&quot;string&quot;&gt;&#39;mean_squared_error&#39;&lt;/span&gt;, optimizer=&lt;span class=&quot;string&quot;&gt;&#39;sgd&#39;&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;SGD（随机梯度下降优化器，性价比最好的算法）&lt;/p&gt;
&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;keras.optimizers.SGD(lr=&lt;span class=&quot;number&quot;&gt;0.01&lt;/span&gt;, momentum=&lt;span class=&quot;number&quot;&gt;0.&lt;/span&gt;, decay=&lt;span class=&quot;number&quot;&gt;0.&lt;/span&gt;, nesterov=&lt;span class=&quot;keyword&quot;&gt;False&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;参数：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;lr :float&amp;gt;=0，学习速率&lt;/li&gt;
&lt;li&gt;momentum :float&amp;gt;=0 参数更新的动量&lt;/li&gt;
&lt;li&gt;decay : float&amp;gt;=0 每次更新后学习速率的衰减量&lt;/li&gt;
&lt;li&gt;nesterov :Boolean 是否使用Nesterov动量项&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;objectives&quot;&gt;&lt;a href=&quot;#objectives&quot; class=&quot;headerlink&quot; title=&quot;objectives&quot;&gt;&lt;/a&gt;objectives&lt;/h2&gt;&lt;p&gt;目标函数模块，keras提供了mean_squared_error，mean_absolute_error，squared_hinge，hinge，binary_crossentropy，categorical_crossentropy这几种目标函数。&lt;/p&gt;
&lt;p&gt;这里binary_crossentropy 和categorical_crossentropy也就是常说的logloss.&lt;/p&gt;
&lt;h2 id=&quot;Activations&quot;&gt;&lt;a href=&quot;#Activations&quot; class=&quot;headerlink&quot; title=&quot;Activations&quot;&gt;&lt;/a&gt;Activations&lt;/h2&gt;&lt;p&gt;激活函数模块，keras提供了linear、sigmoid、hard_sigmoid、tanh、softplus、relu、softplus，另外softmax也放在Activations模块里。此外，像LeakyReLU和PReLU这种比较新的激活函数，keras在keras.layers.advanced_activations模块里提供。&lt;/p&gt;
&lt;h2 id=&quot;initializations&quot;&gt;&lt;a href=&quot;#initializations&quot; class=&quot;headerlink&quot; title=&quot;initializations&quot;&gt;&lt;/a&gt;initializations&lt;/h2&gt;&lt;p&gt;权值初始化，在Keras中对权值矩阵初始化的方式很简单，就是在add某一层时，同时注明初始化该层的概率分布是什么就可以了。代码如下：&lt;/p&gt;
&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;# init是关键字，’uniform’表示用均匀分布去初始化  &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;model.add(Dense(&lt;span class=&quot;number&quot;&gt;64&lt;/span&gt;, init=&lt;span class=&quot;string&quot;&gt;&#39;uniform&#39;&lt;/span&gt;))&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;keras提供了uniform、lecun_uniform、normal、orthogonal、zero、glorot_normal、he_normal这几种。&lt;/p&gt;
&lt;h2 id=&quot;regularizers&quot;&gt;&lt;a href=&quot;#regularizers&quot; class=&quot;headerlink&quot; title=&quot;regularizers&quot;&gt;&lt;/a&gt;regularizers&lt;/h2&gt;&lt;p&gt;深度学习容易出现过拟合，通过使用&lt;a href=&quot;http://blog.csdn.net/u012162613/article/details/44261657&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;正则化方法&lt;/a&gt;，防止过拟合，提高泛化能力。&lt;/p&gt;
&lt;p&gt;使用示例代码如下：&lt;/p&gt;
&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;from&lt;/span&gt; keras.regularizers &lt;span class=&quot;keyword&quot;&gt;import&lt;/span&gt; l2, activity_l2  &lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;model.add(Dense(&lt;span class=&quot;number&quot;&gt;64&lt;/span&gt;, input_dim=&lt;span class=&quot;number&quot;&gt;64&lt;/span&gt;, W_regularizer=l2(&lt;span class=&quot;number&quot;&gt;0.01&lt;/span&gt;), activity_regularizer=activity_l2(&lt;span class=&quot;number&quot;&gt;0.01&lt;/span&gt;)))&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;h2 id=&quot;constraints&quot;&gt;&lt;a href=&quot;#constraints&quot; class=&quot;headerlink&quot; title=&quot;constraints&quot;&gt;&lt;/a&gt;constraints&lt;/h2&gt;&lt;p&gt;除了正则化外，Keras还有一个约束限制功能。函数可以设置在训练网络到最优时对网络参数的约束。这个约束就是限制参数值的取值范围。比如最大值是多少，不允许为负值等。&lt;/p&gt;
&lt;p&gt;2个关键的参数：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;W_constraint：约束主要的权值矩阵&lt;/li&gt;
&lt;li&gt;b_constraint：约束偏置值&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;使用示例代码如下：&lt;br&gt;&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;from&lt;/span&gt; keras.constraints &lt;span class=&quot;keyword&quot;&gt;import&lt;/span&gt; maxnorm&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;model.add(Dense(&lt;span class=&quot;number&quot;&gt;64&lt;/span&gt;, W_constraint =maxnorm(&lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;)))&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;#限制权值的各个参数不能大于2&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;可用的约束限制&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;maxnorm(m=2): 最大值约束&lt;/li&gt;
&lt;li&gt;nonneg(): 不允许负值&lt;/li&gt;
&lt;li&gt;unitnorm(): 归一化&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&quot;实例：解决XOR问题&quot;&gt;&lt;a href=&quot;#实例：解决XOR问题&quot; class=&quot;headerlink&quot; title=&quot;实例：解决XOR问题&quot;&gt;&lt;/a&gt;实例：解决XOR问题&lt;/h1&gt;&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;import&lt;/span&gt; numpy &lt;span class=&quot;keyword&quot;&gt;as&lt;/span&gt; np&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;from&lt;/span&gt; keras.models &lt;span class=&quot;keyword&quot;&gt;import&lt;/span&gt; Sequential&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;from&lt;/span&gt; keras.layers.core &lt;span class=&quot;keyword&quot;&gt;import&lt;/span&gt; Activation, Dense&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;from&lt;/span&gt; keras.optimizers &lt;span class=&quot;keyword&quot;&gt;import&lt;/span&gt; SGD&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;X = np.zeros((&lt;span class=&quot;number&quot;&gt;4&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;), dtype=&lt;span class=&quot;string&quot;&gt;&#39;uint8&#39;&lt;/span&gt;)&lt;span class=&quot;comment&quot;&gt;#训练数据&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;y = np.zeros(&lt;span class=&quot;number&quot;&gt;4&lt;/span&gt;, dtype=&lt;span class=&quot;string&quot;&gt;&#39;uint8&#39;&lt;/span&gt;)&lt;span class=&quot;comment&quot;&gt;#训练标签&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;X[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;] = [&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;]&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;y[&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;] = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;X[&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;] = [&lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;]&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;y[&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;] = &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;X[&lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;] = [&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;]&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;y[&lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;] = &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;X[&lt;span class=&quot;number&quot;&gt;3&lt;/span&gt;] = [&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;]&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;y[&lt;span class=&quot;number&quot;&gt;3&lt;/span&gt;] = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;model = Sequential()&lt;span class=&quot;comment&quot;&gt;#实例化模型&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;model.add(Dense(&lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;, input_dim=&lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;))&lt;span class=&quot;comment&quot;&gt;#输入层，输入数据维数为2&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;model.add(Activation(&lt;span class=&quot;string&quot;&gt;&#39;sigmoid&#39;&lt;/span&gt;))&lt;span class=&quot;comment&quot;&gt;#设置激活函数&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;model.add(Dense(&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;))&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;model.add(Activation(&lt;span class=&quot;string&quot;&gt;&#39;sigmoid&#39;&lt;/span&gt;))&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;sgd = SGD(lr=&lt;span class=&quot;number&quot;&gt;0.1&lt;/span&gt;, decay=&lt;span class=&quot;number&quot;&gt;1e-6&lt;/span&gt;, momentum=&lt;span class=&quot;number&quot;&gt;0.9&lt;/span&gt;, nesterov=&lt;span class=&quot;keyword&quot;&gt;True&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;model.compile(loss=&lt;span class=&quot;string&quot;&gt;&#39;mean_squared_error&#39;&lt;/span&gt;, optimizer=sgd)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;history = model.fit(X, y, nb_epoch=&lt;span class=&quot;number&quot;&gt;10000&lt;/span&gt;, batch_size=&lt;span class=&quot;number&quot;&gt;4&lt;/span&gt;, show_accuracy=&lt;span class=&quot;keyword&quot;&gt;True&lt;/span&gt;, verbose=&lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;print&lt;/span&gt; model.predict(X)&lt;span class=&quot;comment&quot;&gt;#预测&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;h1 id=&quot;参考&quot;&gt;&lt;a href=&quot;#参考&quot; class=&quot;headerlink&quot; title=&quot;参考&quot;&gt;&lt;/a&gt;参考&lt;/h1&gt;&lt;p&gt;&lt;a href=&quot;http://keras.io/&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;Keras Documentation&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.lai18.com/user/301164.html&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;Keras 学习随笔&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://blog.csdn.net/u012162613/article/details/45397033&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;深度学习框架Keras简介&lt;/a&gt;&lt;/p&gt;
</content>
    
    <summary type="html">
    
      &lt;center&gt;&lt;br&gt;&lt;img src=&quot;http://7xritj.com1.z0.glb.clouddn.com/16-4-7/16129390.jpg&quot; alt=&quot;&quot;&gt;&lt;br&gt;&lt;/center&gt;

&lt;h1 id=&quot;Keras-简介&quot;&gt;&lt;a href=&quot;#Keras-简介&quot; class=&quot;headerlink&quot; title=&quot;Keras 简介&quot;&gt;&lt;/a&gt;Keras 简介&lt;/h1&gt;&lt;p&gt;&lt;a href=&quot;http://keras.io/&quot;&gt;Keras&lt;/a&gt;是一个用Python编写的基于 TensorFlow 和 Theano高度模块化的神经网络库。其最大的优点在于样例丰富，现有主流模型封装完美。复杂点的模型可以像搭积木一样搞出来，适合快速地搭建模型。&lt;/p&gt;
    
    </summary>
    
    
      <category term="Python" scheme="http://buptldy.github.io/tags/Python/"/>
    
      <category term="Keras" scheme="http://buptldy.github.io/tags/Keras/"/>
    
      <category term="Deep Learning" scheme="http://buptldy.github.io/tags/Deep-Learning/"/>
    
  </entry>
  
</feed>
