3.4 改进集束搜索-深度学习第五课《序列模型》-Stanford吴恩达教授
改进集束搜索 (Refinements to Beam Search)
上个视频中, 你已经学到了基本的束搜索算法(the basic beam search algorithm),这个视频里,我们会学到一些技巧, 能够使算法运行的更好。长度归一化(Length normalization)就是对束搜索算法稍作调整的一种方式,帮助你得到更好的结果,下面介绍一下它。
前面讲到束搜索就是最大化这个概率,这个乘积就是 ,可以表示成:
这些符号看起来可能比实际上吓人,但这就是我们之前见到的乘积概率(the product probabilities)。如果计算这些,其实这些概率值都是小于1的,通常远小于1。很多小于1的数乘起来,会得到很小很小的数字,会造成数值下溢(numerical underflow)。数值下溢就是数值太小了,导致电脑的浮点表示不能精确地储存,因此在实践中,我们不会最大化这个乘积,而是取 值。如果在这加上一个 ,最大化这个 求和的概率值,在选择最可能的句子 时,你会得到同样的结果。所以通过取 ,我们会得到一个数值上更稳定的算法,不容易出现四舍五入的误差,数值的舍入误差(rounding errors)或者说数值下溢(numerical underflow)。因为 函数它是严格单调递增的函数,最大化 ,因为对数函数,这就是 函数,是严格单调递增的函数,所以最大化 和最大化 结果一样。如果一个 值能够使前者最大,就肯定能使后者也取最大。所以实际工作中,我们总是记录概率的对数和(the sum of logs of the probabilities),而不是概率的乘积(the production of probabilities)。
对于目标函数(this objective function),还可以做一些改变,可以使得机器翻译表现的更好。如果参照原来的目标函数(this original objective),如果有一个很长的句子,那么这个句子的概率会很低,因为乘了很多项小于1的数字来估计句子的概率。所以如果乘起来很多小于1的数字,那么就会得到一个更小的概率值,所以这个目标函数有一个缺点,它可能不自然地倾向于简短的翻译结果,它更偏向短的输出,因为短句子的概率是由更少数量的小于1的数字乘积得到的,所以这个乘积不会那么小。顺便说一下,这里也有同样的问题,概率的 值通常小于等于1,实际上在 的这个范围内,所以加起来的项越多,得到的结果越负,所以对这个算法另一个改变也可以使它表现的更好,也就是我们不再最大化这个目标函数了,我们可以把它归一化,通过除以翻译结果的单词数量(normalize this by the number of words in your translation)。这样就是取每个单词的概率对数值的平均了,这样很明显地减少了对输出长的结果的惩罚(this significantly reduces the penalty for outputting longer translations.)。
在实践中,有个探索性的方法,相比于直接除 ,也就是输出句子的单词总数,我们有时会用一个更柔和的方法(a softer approach),在 上加上指数 , 可以等于0.7。如果 等于1,就相当于完全用长度来归一化,如果 等于0, 的0次幂就是1,就相当于完全没有归一化,这就是在完全归一化和没有归一化之间。 就是算法另一个超参数(hyper parameter),需要调整大小来得到最好的结果。不得不承认,这样用 实际上是试探性的,它并没有理论验证。但是大家都发现效果很好,大家都发现实践中效果不错,所以很多人都会这么做。你可以尝试不同的 值,看看哪一个能够得到最好的结果。
总结一下如何运行束搜索算法。当你运行束搜索时,你会看到很多长度等于1的句子,很多长度等于2的句子,很多长度等于3的句子,等等。可能运行束搜索30步,考虑输出的句子可能达到,比如长度30。因为束宽为3,你会记录所有这些可能的句子长度,长度为1、2、 3、 4 等等一直到30的三个最可能的选择。然后针对这些所有的可能的输出句子,用这个式子(上图编号1所示)给它们打分,取概率最大的几个句子,然后对这些束搜索得到的句子,计算这个目标函数。最后从经过评估的这些句子中,挑选出在归一化的 概率目标函数上得分最高的一个(you pick the one that achieves the highest value on this normalized log probability objective.),有时这个也叫作归一化的对数似然目标函数(a normalized log likelihood objective)。这就是最终输出的翻译结果,这就是如何实现束搜索。这周的练习中你会自己实现这个算法。
最后还有一些实现的细节,如何选择束宽B。B越大,你考虑的选择越多,你找到的句子可能越好,但是B越大,你的算法的计算代价越大,因为你要把很多的可能选择保存起来。最后我们总结一下关于如何选择束宽B的一些想法。接下来是针对或大或小的B各自的优缺点。如果束宽很大,你会考虑很多的可能,你会得到一个更好的结果,因为你要考虑很多的选择,但是算法会运行的慢一些,内存占用也会增大,计算起来会慢一点。而如果你用小的束宽,结果会没那么好,因为你在算法运行中,保存的选择更少,但是你的算法运行的更快,内存占用也小。在前面视频里,我们例子中用了束宽为3,所以会保存3个可能选择,在实践中这个值有点偏小。在产品中,经常可以看到把束宽设到10,我认为束宽为100对于产品系统来说有点大了,这也取决于不同应用。但是对科研而言,人们想压榨出全部性能,这样有个最好的结果用来发论文,也经常看到大家用束宽为1000或者3000,这也是取决于特定的应用和特定的领域。在你实现你的应用时,尝试不同的束宽的值,当B很大的时候,性能提高会越来越少。对于很多应用来说,从束宽1,也就是贪心算法,到束宽为3、到10,你会看到一个很大的改善。但是当束宽从1000增加到3000时,效果就没那么明显了。对于之前上过计算机科学课程的同学来说,如果你熟悉计算机科学里的搜索算法(computer science search algorithms), 比如广度优先搜索(BFS, Breadth First Search algorithms),或者深度优先搜索(DFS, Depth First Search),你可以这样想束搜索,不像其他你在计算机科学算法课程中学到的算法一样。如果你没听说过这些算法也不要紧,但是如果你听说过广度优先搜索和深度优先搜索,不同于这些算法,这些都是精确的搜索算法(exact search algorithms),束搜索运行的更快,但是不能保证一定能找到argmax的准确的最大值。如果你没听说过广度优先搜索和深度优先搜索,也不用担心,这些对于我们的目标也不重要,如果你听说过,这就是束搜索和其他算法的关系。
好,这就是束搜索。这个算法广泛应用在多产品系统或者许多商业系统上,在深度学习系列课程中的第三门课中,我们讨论了很多关于误差分析(error analysis)的问题。事实上在束搜索上做误差分析是我发现的最有用的工具之一。有时你想知道是否应该增大束宽,我的束宽是否足够好,你可以计算一些简单的东西来指导你需要做什么,来改进你的搜索算法。我们在下个视频里进一步讨论。