集束搜索(beam search)

基本的集束搜索算法

解决的问题

寻找一个最接近原意的结果

过程

第一步,找到第一个输出y的概率值。其中考虑一个概念--集束宽(beam width,简称bw),表示在每一步中有多少选择。

执行过程是,将法语句子输入到编码网络,然后解码网络,softmax层会输出10,000个输出概率值,然后 取bw个单词保存起来。(即保存前bw个值)。

第二步,在第一步选出的单词作为第一个,然后考虑第二个单词是什么,这个时候需要将第一个输出重新输入进来,然后考虑最可能的第一个和第二个单词对,不仅仅是第二个单词有最大的概率,而是第一个、第二个单词对有最大的概率。假设集束宽为 3,并且词汇表里有 10,000 个单词,那么最终我们会有 3 乘以 10,000 也就是 30,000 个可能的结果。

按条件概率准则,表示成第一个单词的概率乘以第二个单词的概率。

如果集束搜索找到了第一个和第二个单词对最可能的三个选择是“inSeptember”或者“jane is”或者“jane visits”, 这就意味着我们去掉了 september 作为英语翻译结果的第一个单词的选择,所以我们的第一个单词现在减少到了两个可能结果。根据y1,y2的对待选择前三个最大的概率值,来考虑第三步的选择。依次下去,直到终止句尾符号。

如果集束宽等于 1,只考虑 1 种可能结果,这实际上就变成了贪婪搜索算法。

改进的集束搜索算法

长度归一化(Length normalization)

之前的束搜索算法就是最大化这个概率P\left(y^{<1>} \ldots y^{<T_{y}> } | X\right)= P\left(y^{<1>} | X\right) P\left(y^{<2>} | X, y^{<1>}\right) P\left(y^{<3>} | X, y^{<1>}, y^{<2}\right) \ldots P\left(y^{<T_{y}>} | X, y^{<1>}, y^{<2>} \ldots y^{<T_{y}-1>}\right)

但是,这些概率值都是远小于1的,乘起来会更小,造成数值下溢(数值太小,电脑的浮点数字不能精确储存)。所以实际中,不会取这个乘积最大值,二是加上log,取最大和,会得到一个数值上更稳定的数。

目标函数的缺点

由于概率值小于1,乘起来会得到更小的值,所以会倾向于更短的翻译结果。概率的log值通常小于等于1,在log范围内,加起来项越多,结果越负。

改进方法

归一化,除以翻译结果的单词数,即取每个单词的概率对数值的平均,减少了对输出长的结果的惩罚。

实际使用的方法,在输出句子的单词总数上加上指数a,a = 1,相当于完全长度归一化。a = 0,相当于没有归一化。这里的指数a是一个超参数。

运行步骤

运行束搜索时,会看到很多长度等于 1 的句子,很多长度等于 2 的句子,很多长度等于 3 的句子,等等。可能运行束搜索 30 步,考虑输出的句子可能达到,比如长度 30。因为束宽为 3,你会记录所有这些可能的句子长度,长度为1、 2、 3、 4 等等一直到 30 的三个最可能的选择。

然后针对这些所有的可能的输出句子,用下面的式子给它们打分,取概率最大的几个句子,然后对这些束搜索得到的句子,计算这个目标函数。最后从经过评估的这些句子中,挑选出在归一化的log概率在目标函数上得分最高的一个。

有时也称归一化的对数似然目标函数。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
集束搜索是一种启发式搜索算法,用于在大规模搜索空间中快速找到最优解。它通过保留一定数量的最有希望的候选解,来减少搜索空间。下面是一个用Python实现集束搜索的示例代码: ```python import heapq class BeamSearch: def __init__(self, beam_width): self.beam_width = beam_width self.heap = [] def search(self, start_state, goal_fn, successor_fn, heuristic_fn): # Add the start state to the heap with a priority of 0 heapq.heappush(self.heap, (0, [start_state])) while self.heap: # Pop the state with the lowest priority from the heap priority, path = heapq.heappop(self.heap) current_state = path[-1] # Check if the current state is the goal state if goal_fn(current_state): return path # Generate successor states and add them to the heap successor_states = successor_fn(current_state) for successor_state in successor_states: successor_path = path + [successor_state] successor_priority = priority + heuristic_fn(successor_state) heapq.heappush(self.heap, (successor_priority, successor_path)) # Keep only the top beam_width paths in the heap self.heap = heapq.nsmallest(self.beam_width, self.heap) # If the heap is empty, no solution was found return None ``` 这个实现使用了一个最小堆来存储候选解,每次从堆中取出当前最优路径进行扩展。在每次扩展时,生成后继状态,并计算他们的启发式值,然后将它们加入堆中。最后,保留堆中最优的 beam_width 条路径,并继续迭代,直到找到目标状态或者堆为空。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值