GreedySearch和BeamSearch解码方式 – 潘登同学的NLP笔记
重要一点: CTC Loss是在训练OCR的时求的Loss采用的,而以下这些算法都是推理时得到预测序列采用的
GreedySearch
GreedySearch则采取贪心算法来求解路径,就是将每个时刻t内最大的概率的状态取出,实例代码如下
便于理解,最终算法的结果如下
Beam Search(束搜索)
beam search是对greedy search的一个改进算法。相对greedy search扩大了搜索空间,但远远不及穷举搜索指数级的搜索空间,是二者的一个折中方案;
基本原理是通过 t i − 1 t_{i-1} ti−1 中 b e a m S i z e beamSize beamSize个序列,每个序列分别连接 t i t_i ti 中 V V V 个节点,得到 b e a m S i z e beamSize beamSize 个新序列及对应的 s c o r e score score,然后按照 s c o r e score score从大到小的顺序选出前 b e a m S i z e beamSize beamSize个序列,依次推进即可
注意算法中有以下一句,目的是为了防止underflow
logY = np.log(y)
最终得到的概率的形式是
p
=
y
1
∗
y
2
∗
⋯
∗
y
n
p=y_1*y_2*\cdots*y_n
p=y1∗y2∗⋯∗yn,会导致概率几乎为0,而最后对
s
c
o
r
e
score
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
- 如果
b
e
a
m
S
i
z
e
beamSize
beamSize为2,那么
AAA_B
、AAAAB
会被晒掉,开始AAA_B
、AAAAB
最终去重之后得到的结果都是AB
其实对应这个答案的概率应该是0.005(0.002+0.003),但是却不如后面两个…
其中logsumexp
是用于解决数值计算下溢(underflow) 和上溢(overflow) 的问题,其实这里一开始我很不理解诶; 直接加不就行了嘛,概率相乘确实会下溢,但是不是已经取对数了嘛,但是结果又是对的,先放着,以后再说…(可能有用的logsumexp参考链接)