<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Neural Network on Svtter's Blog</title><link>https://svtter.cn/tags/neural-network/</link><description>Recent content in Neural Network on Svtter's Blog</description><generator>Hugo -- gohugo.io</generator><language>zh-cn</language><lastBuildDate>Fri, 23 Nov 2018 01:00:00 +0800</lastBuildDate><atom:link href="https://svtter.cn/tags/neural-network/index.xml" rel="self" type="application/rss+xml"/><item><title>beam search – 一个搜索策略</title><link>https://svtter.cn/p/beam-search-%E4%B8%80%E4%B8%AA%E6%90%9C%E7%B4%A2%E7%AD%96%E7%95%A5/</link><pubDate>Fri, 23 Nov 2018 01:00:00 +0800</pubDate><guid>https://svtter.cn/p/beam-search-%E4%B8%80%E4%B8%AA%E6%90%9C%E7%B4%A2%E7%AD%96%E7%95%A5/</guid><description>&lt;p&gt;这篇文章不建议读，2018年写的，不知所云。&lt;/p&gt;
&lt;p&gt;beam search 是一个近似搜索策略，用于在候选可能中选择最好的结果。&lt;a class="link" href="https://hackernoon.com/beam-search-a-search-strategy-5d92fb7817f" target="_blank" rel="noopener"
&gt;原文链接&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://svtter.cn/pics/1_HmPwWf0VJV3TeaGKoly4Xw.png"
loading="lazy"
alt="img"
&gt;&lt;/p&gt;
&lt;!-- &lt;img src="" alt="" data-recalc-dims="1" /&gt;&lt;/figure&gt; --&gt;
&lt;p&gt;一个常用例子，BS(beam search) 用于获得与机器翻译等价的结果。对于那些不了解机器翻译的人，也肯定知道 Google Translate。&lt;/p&gt;
&lt;p&gt;这就是为啥要讲这个。这些系统都用 BS 技术来找到与结果最等价的翻译。阅读这个 Wiki 来了解相同文件的定义。&lt;/p&gt;
&lt;p&gt;让我们讨论一下这个使用机器翻译案例的策略。如果你是一个喜欢研究现象背后原理的人，一定要读一下 google encoder-decoder 网络架构。这个东西我就不讲了，有很多人讲。例如，如果你不知道这个架构，看看这个 quora 上的回答。&lt;/p&gt;
&lt;h2 id="一个视角"&gt;一个视角
&lt;/h2&gt;&lt;p&gt;机器翻译模型可以被认为是一种 “条件语言模型”，对于…&lt;/p&gt;
&lt;h2 id="让我们看一下8230"&gt;让我们看一下…
&lt;/h2&gt;&lt;p&gt;BS B(beam 宽度) 是唯一一个调整翻译结果的超参。 B 在一般情况决定了，在每一步，要记忆的单词的个数，来变换概率。&lt;/p&gt;
&lt;h2 id="不翻译了这里有更直接的结果"&gt;不翻译了。。这里有更直接的结果
&lt;/h2&gt;&lt;p&gt;beam search 时在每一个时间点选择 beam_width 个最大的可能类别，然后在每个时间点 beam_width 个类别组成的空间里寻找整体概率最大的一条路径，得到最后得识别输出。而 greedy search 则直接在每个时间点寻找概率最大的类别，然后依次组成这个路径。也就是说，greedy search 是 beam_width=1 版本的 beam search。上图是 CTC 论文里 greedy search 示意图。&lt;/p&gt;</description></item><item><title>对于 CTC 的一个直观理解与解释</title><link>https://svtter.cn/p/%E5%AF%B9%E4%BA%8E-ctc-%E7%9A%84%E4%B8%80%E4%B8%AA%E7%9B%B4%E8%A7%82%E7%90%86%E8%A7%A3%E4%B8%8E%E8%A7%A3%E9%87%8A/</link><pubDate>Thu, 22 Nov 2018 01:00:00 +0800</pubDate><guid>https://svtter.cn/p/%E5%AF%B9%E4%BA%8E-ctc-%E7%9A%84%E4%B8%80%E4%B8%AA%E7%9B%B4%E8%A7%82%E7%90%86%E8%A7%A3%E4%B8%8E%E8%A7%A3%E9%87%8A/</guid><description>&lt;blockquote&gt;
&lt;p&gt;这篇文章是一个翻译：&lt;a class="link" href="https://towardsdatascience.com/intuitively-understanding-connectionist-temporal-classification-3797e43a86c" target="_blank" rel="noopener"
&gt;towardsdatascience-ctc&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;通过 CTC loss 以及编码操作进行文字识别。&lt;/p&gt;
&lt;p&gt;如果想用使用计算机识别文字，神经网络很好用。使用一些列 CNN 从序列中提取特征，使用 RNN 来传播需略的信息。它会输出字符得分，给每个序列元素，通过一个简单的矩阵表示。现在，有两个事情我们想要对矩阵进行处理。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;训练：计算损失值来训练神经网络&lt;/li&gt;
&lt;li&gt;推理：解码矩阵来获得图片中的字符&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;两个任务可以同时被 CTC 操作完成。对于手写数字系统的描述，可以参见图像 1.&lt;/p&gt;
&lt;p&gt;我们更进一步看看 CTC 操作，并且讨论一下它如完成的，以及它背后的公式是如此巧妙。最后，我将会指点你来找到 Python 代码以及不复杂的公式，如果你感兴趣的话。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://svtter.cn/pics/1_i2OG4hu9EjsyWcVMc4OOvA.png"
loading="lazy"
alt="img"
&gt;&lt;/p&gt;
&lt;h2 id="为什么我们使用-ctc"&gt;为什么我们使用 CTC
&lt;/h2&gt;&lt;p&gt;当然我们可以创建一个数据集，这个数据集有文本行，然后指出每列属于哪一个字符，就像图 2 中展示的那样。然后，我们可以训练一个神经网络来输出每一列的得分。而然，对于这个简单的解法，这里有两个问题。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;这个十分的耗时（以及无聊）来在字符层面上标注数据&lt;/li&gt;
&lt;li&gt;我们仅仅能够得到字符的得分，因此还需要一些操作来获取最终的文本。一个简单地字符可以跨越多个位置，比如，我们得到 “ttooo”，是因为 “o” 是一个比较宽的字符。我们已经删除了多余的 “t” and “o”，但是，如果要识别的字符是 “too”，我们应该怎么办？如果删除了多余的 “o”，将会给我们错误的答案。我们应该如何处理呢？&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;CTC 解决了几个问题&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;我们只需要告诉 CTC loss function，文本在图像中出现了，因此我们忽略位置和宽度文中在图像中。&lt;/li&gt;
&lt;li&gt;不需要更多的文本识别处理&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src="https://svtter.cn/pics/1_rfeNj9aNfUSqA-SXB_i4Bw.png"
loading="lazy"
alt="img"
&gt;&lt;/p&gt;
&lt;h2 id="ctc-如何工作的"&gt;CTC 如何工作的
&lt;/h2&gt;&lt;p&gt;就像是我们已经讨论的，我们不希望在图像的每一列标注数据（这曾经被我们成为时间步）。神经网络的训练将会被 CTC 损失函数所指引。我们只需要把数据矩阵给 CTC 函数，以及对应的真实值即可。但是它是怎么知道每一个字符出现的呢？他不知道。相对而言，它尝试了图片中所有的真实文本，以及计算了所有的加和。通过这个方式， This way, the score of a GT text is high if the sum over the alignment-scores has a high value.&lt;/p&gt;
&lt;h2 id="编码文本"&gt;编码文本
&lt;/h2&gt;&lt;p&gt;如何编码重复的文本曾经是一个问题。这个问题通过引入一个虚假字符来解决了（称为空，但是不要把它和真正的 space 混淆。）。这个特殊的字符被标记为 “-”，在下面的文本中。我们使用了一个聪明的编码策略来解决重复字符的问题。当编码一个文本的时候，我们可以随机加入许多空在任何位置中，当我们解码的时候，我们将会把的这些删除。但是，我们必须在重复字符串中加入空，例如 “he&lt;strong&gt;ll&lt;/strong&gt;o”，如此一来，重复字符就不是问题了。&lt;/p&gt;
&lt;p&gt;Let’s look at some examples:&lt;/p&gt;
&lt;p&gt;“to” → “—ttttttooo”, or “-t-o-”, or “to” “too” → “—ttttto-o”, or “-t-o-o-”, or “to-o”, but not “too”&lt;/p&gt;
&lt;p&gt;正如你所见，这些模式也允许我们简单的创建一些相同文本串的不同对取，比如 “t-o”, 以及 “too”，以及 “-to”，所有的表示都是同一个文本 “to”，但是通过对图片不同对其获得的。神经网络被训练于输出一个编码的文本（在神经网络的矩阵中编码）。&lt;/p&gt;
&lt;h2 id="损失计算"&gt;损失计算
&lt;/h2&gt;&lt;p&gt;我们需要计算每一个损失值，这个损失值是由图像核真实文本给出来训练 NN 的。你已经知道 NN 输出一个矩阵，包含一个得分，为每个文本在每个时间步上。一个小矩阵在图三中展示：有许多的时间步（t0, t1），以及三个字符（”a”, “b”, 以及 blank “-“).&lt;/p&gt;
&lt;p&gt;&lt;img src="https://svtter.cn/pics/1_BFQYgGofh6HOxnGdkJnO-w.png"
loading="lazy"
alt="img"
&gt;&lt;/p&gt;
&lt;p&gt;此外，你已经知道，loss 是通过加和所有积分来进行计算的，通过这个方式，字符出现在图片的哪个位置不重要。&lt;/p&gt;
&lt;p&gt;对于一个 alignment 的得分（或者 path；在文学中一般这么称呼）通过将相应的字符相乘。在上面的例子中，path”aa” 的得分是：0.4*0.4=0.16，”a-” 的得分是 0.4*0.6=0.24，”-a” 的得分是 0.6*0.4=0.24. 为了获得 GT 文本的得分，我们加和这个文本的所有 path 的得分。我们假设，GT 文本是 “a”，我们已经计算了所有长度为 “2” 的 path，分别是 “aa”，“a-”，“-a”，我们已经计算了这些 path 所有的得分，所以我们只需要把他们加起来，得到 0.4×0.4 + 0.4×0.6 + 0.6×0.4 = 0.64。如 GT 文本可能是 “”，我们可以看到只有一种相关的 path，那么就是 “–”，获得的得分是 0.6×0.6 =0.36.&lt;/p&gt;
&lt;p&gt;如果仔细看，你已经发现我们计算了 GT 的可能性，但是不是 loss 值，而然，loss 知识概率的负对数。这个 loss 值是反向传播算法以及 NN 的参数更新使用的，我这里没有进行详细的讨论。&lt;/p&gt;
&lt;h2 id="解码"&gt;解码
&lt;/h2&gt;&lt;p&gt;当我们训练一个 NN，我们想要使用它来识别那些之前没有看到的图像。或者更多在更多的技术术语：我们想要计算，NN 输出的矩阵最可能是什么。你已经知道一个方法来计算给出文本的得分，但是现在，我们没有被给出任何文本，事实上，它正是我们正在寻找的文本。尝试所有可能的文本，如果他们只有很少的时间步以及字符，但是对于练习用例而言，这不可行。&lt;/p&gt;
&lt;p&gt;一个简单而快速的算法，是最佳 path 解码，包含两个步骤：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;它计算了最佳 path，通过获取最可能的每一个时间步的字符&lt;/li&gt;
&lt;li&gt;首先删除重复的字符，然后删除 path 里面所有的空。这仍然表示了识别的文本。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;正如 FIG4 所展示的，字符是 “a”，“b” 以及 “-”（空），一共有 5 个时间步。让我们应用最佳 path decoder 来处理这个矩阵。在 t0，最可能的是“a”，同样应用于 t1，t2. 空字符在 t3 是最可能的。最后，“b” 是 t4 时刻最可能的。这将给出我们一个 path“aaa-b”，我们删除了重复的字符，这将会返回“a-b”，然后我们删除 path 中的空，这给我们一个“ab”，作为我们输出的识别结果。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://svtter.cn/pics/1_1_5KnLvaTkGUFoyat2jHcQ.png"
loading="lazy"
alt="img"
&gt;&lt;/p&gt;
&lt;p&gt;最佳 path 解析是，当容纳，仅仅是一个近似。构建样例容易给出错误的结果，比如用这个方法构建 FIG3，将会得到 “”，作为识别文本。但是，我们已经知道“” 结果的概率是 0.36，而 “a” 的概率是 0.64。而然，近似算法经常在练习的情景下给出比较好的结果。也有许多其他的比较好的 decoder，例如 beam-search，prefix-search 以及 token passing，这些关于语言结构的方法，都有利于提升结果。&lt;/p&gt;
&lt;h2 id="结论以及展望"&gt;结论以及展望
&lt;/h2&gt;&lt;p&gt;首先我们看得是，神经网络如何解决这个问题；然后，我们展示了 CTC 如何解决这些问题，然后，我们解释了 CTC 为啥能够工作，如何计算的 loss，以及如何解码 CTC 训练的 NN。&lt;/p&gt;
&lt;p&gt;This should give you a good understanding of what is happening behind the scenes when you e.g. call functions like ctc_loss or ctc_greedy_decoder in TensorFlow. However, when you want to implement CTC yourself, you need to know some more details, especially to make it run fast. Graves et al. &lt;/p&gt;
\[1] introduce the CTC operation, the paper also shows all the relevant math. If you are interested in how to improve&amp;nbsp;decoding,&amp;nbsp;take a look&amp;nbsp;at the articles about beam search&amp;nbsp;decoding&amp;nbsp;[2\]\[3\]&lt;p&gt;. I implemented some decoders and the loss function in Python and C++, which you can find on github &lt;/p&gt;
\[4\]\[5\]&lt;p&gt;. Finally, if you want to look at the bigger picture of how to recognize (handwritten) text, look at my article on how to build a handwritten text recognition system [6].&lt;/p&gt;</description></item></channel></rss>