改进集束搜索(Refinements to Beam Search)

来源:Coursera吴恩达深度学习课程

上篇文章介绍了基本的集束搜索(Beam Search),这篇文章我们进一步学习一些技巧,能够使算法运行的更好。

如上图,长度归一化(Length normalization)就是对束搜索算法稍作调整的一种方式,帮助你得到更好的结果,下面介绍一下它。

束搜索就是最大化这个概率:

这个乘积也可以表示为如下形式:

这就是乘积概率(the product probabilities)这些概率值通常远小于1。很多小于1的数乘起来,会得到很小很小的数字,会造成数值下溢(numerical underflow)。数值下溢就是数值太小了,导致电脑的浮点表示不能精确地储存,因此实践中在选择最可能的句子y时,我们不会最大化这个乘积,而是取log值,最大化这个log求和的概率值,将得到同样的结果。通过取log,我们会得到一个数值上更稳定的(stable)算法,不容易出现四舍五入的误差,数值的舍入误差(rounding errors)或者说数值下溢(numerical underflow)。最大化P(y)时,因为对数函数(例如log函数)是严格单调递增的函数(a strictly monotonically increasing function),所以最大化logP(y|x)和最大化P(y|x)结果一样。如果一个y值能够使前者最大,就肯定能使后者也取最大。因此在实际工作中,我们总是记录概率的对数和(the sum of logs of the probabilities),而不是概率的乘积(the production of probabilities)。

对于目标函数(this objective function),也可以做一些改变,可以使得机器翻译表现的更好。之前的目标函数(this original objective),如果有一个很长的句子,那么这个句子的概率会很低,因为乘了很多项小于1的数字来估计句子的概率。很多小于1的数字相乘就会得到一个更小的概率值,所以这个目标函数有一个缺点,它可能不自然地倾向于简短的翻译结果,它更偏向短的输出。同时,这里也有同样的问题,概率的log值通常小于等于1,实际上在log的这个范围内,所以加起来的项越多,得到的结果越负,所以对这个算法另一个改变也可以使它表现的更好,我们可以把原目标函数归一化通过除以翻译结果的单词数量(normalize this by the number of words in your translation),即取每个单词的概率对数值的平均,这样做很明显地减少了对输出长的结果的惩罚(this significantly reduces the penalty for outputting longer translations)

在实践中,相比于直接除T_y(输出句子的单词总数),我们有时会用一个更柔和的方法(a softer approach),在T_y上加上指数α,α可以等于0.7。如果α等于1,就相当于完全用长度来归一化,如果α等于0,T_y的0次幂就是1,就相当于完全没有归一化,这就是在完全归一化(full normalization)和没有归一化(no normalization)之间。α就是算法另一个超参数(hyper parameter),需要调整大小来得到最好的结果。不得不承认,这样用α实际上是试探性的,它并没有理论验证。但是大家都发现实践中效果不错,所以很多人都会这么做。我们也可以尝试不同的α值,看看哪一个能够得到最好的结果。

总结一下如何运行束搜索算法。当我们运行束搜索时,会看到很多长度等于1的句子,很多长度等于2的句子,很多长度等于3的句子,等等。可能运行束搜索30步,考虑输出的句子可能达到,比如长度30。因为束宽为3,你会记录所有这些可能的句子长度,长度为1、2、3、4 等等一直到30的三个最可能的选择。然后针对这些所有的可能的输出句子,用这个式子(上图红色方框)给它们打分,取概率最大的几个句子,然后对这些束搜索得到的句子,计算这个目标函数。最后从经过评估的这些句子中,挑选出在归一化的log概率目标函数上得分最高的一个(you pick the one that achieves the highest value on this normalized log probability objective),有时这个也叫作归一化的对数似然目标函数(a normalized log likelihood objective)。这就是最终输出的翻译结果,这就是如何实现束搜索。

最后还有一些实现的细节,如何选择束宽BB越大,我们需要考虑的选择越多,得到的句子可能越好,但是B越大,算法的计算代价越大,因为很多的可能选择要保存起来。如上图所示,我们总结一下关于如何选择束宽B的一些想法。

不同取值的B有各自的优缺点(cons)。(1)如果束宽很大,我们会考虑很多的可能,倾向于得到一个更好的结果,但是算法会运行的慢一些,内存占用也会增大,计算起来会慢一点。(2)如果用小的束宽,结果会没那么好,因为在算法运行中,保存的选择更少,但是算法运行的更快,内存占用也小。在前面的例子中我们用了束宽为3,所以会保存3个可能选择,在实践中这个值有点偏小。在产品中,经常可以看到把束宽设到10,Andrew认为束宽为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),束搜索运行的更快,但是不能保证一定能找到目标函数准确的最大值。这就是束搜索和其他算法的关系。如果你没听说过广度优先搜索和深度优先搜索,也不用担心,这些对于我们的目标也不重要。

以上就是束搜索的改进方法。束搜索算法广泛应用在多产品系统或者许多商业系统上,在深度学习系列课程中的第三门课中,我们讨论了很多关于误差分析(error analysis)的问题。事实上在束搜索上做误差分析是Andrew发现的最有用的工具之一。有时你想知道是否应该增大束宽,束宽是否足够好,你可以计算一些简单的东西来指导你需要做什么,来改进你的搜索算法,具体情况将在之后介绍。

说明:记录学习笔记,如果错误欢迎指正!转载请联系我。

猜你喜欢

转载自blog.csdn.net/csdn_xmj/article/details/119256468