GreedySearch和BeamSearch解码方式 -- 潘登同学的NLP笔记
重要一点: CTC Loss是在训练OCR的时求的Loss采用的,而以下这些算法都是推理时得到预测序列采用的
GreedySearch
GreedySearch则采取贪心算法来求解路径,就是将每个时刻t内最大的概率的状态取出,实例代码如下
便于理解,最终算法的结果如下
Beam Search(束搜索)
beam search是对greedy search的一个改进算法。相对greedy search扩大了搜索空间,但远远不及穷举搜索指数级的搜索空间,是二者的一个折中方案;
基本原理是通过 $t_{i-1}$ 中 $beamSize$个序列,每个序列分别连接 $t_i$ 中 $V$ 个节点,得到 $beamSize$ 个新序列及对应的$score$,然后按照$score$从大到小的顺序选出前$beamSize$个序列,依次推进即可
注意算法中有以下一句,目的是为了防止underflow
logY = np.log(y)
最终得到的概率的形式是$p=y_1y_2\cdots*y_n$,会导致概率几乎为0,而最后对$score$取一个exp即可
prefix beam search
代码基本脉络与beam search一致,最主要的一方面是基于如下的考虑:
有许多不同的路径在many-to-one map的过程中是相同的,但beam search却会将一部分舍去,这导致了很多有用的信息被舍弃了
举个例子
- 有这样四条路径
AAA_B
、AAAAB
、AAB_B
、AB_BB
,其分数分别为0.003
、0.002
、0.0035
、0.004
- 如果$beamSize$为2,那么
AAA_B
、AAAAB
会被晒掉,开始AAA_B
、AAAAB
最终去重之后得到的结果都是AB
其实对应这个答案的概率应该是0.005(0.002+0.003),但是却不如后面两个..
其中logsumexp
是用于解决数值计算下溢(underflow) 和上溢(overflow) 的问题,其实这里一开始我很不理解诶; 直接加不就行了嘛,概率相乘确实会下溢,但是不是已经取对数了嘛,但是结果又是对的,先放着,以后再说...(可能有用的logsumexp参考链接)