Closed tyistyler closed 3 years ago
start字符和end字符的分数是单独通过start_scores和end_scores来计算的,因为在include_start_end_trans参数为False的时候,我们不考虑start和end字符,如果采用您说的这种方式,实现这个比较麻烦。所以我们就把start和end的分数计算从trans_scores中单独分离出来了。
谢谢您的回复。
可能是我没有表述清楚问题,
在score = trans_score + emit_score[:seq_len - 1, :]
中
trans_score[0][0]代表第0个句子的第0个字符到第1个字符的转移得分
emit_score[0][0] 代表第0个句子的第0个字符的发射得分
二者相加时,我感觉十分困惑,因为trans_score[0][0]我理解的是第1个字符的转移得分(从位置为0的字符转移到位置为1的字符),将二者相加时,感觉错位了,将0号字符的发射得分与1号字符的转移得分进行了相加,但是第264行的score.sum(0)加法缓解了这个问题。
我个人的看法是,将263和264行的
score = trans_score + emit_score[:seq_len - 1, :]
score = score.sum(0) + emit_score[-1].masked_fill(flip_mask[-1], 0)
替换为
score_new = trans_score + emit_score[1:, :]
score_new = score1.sum(0) + emit_score[0]
是否更好理解?(二者的结果,我用两个例子验证了一下,是相同的)
感觉没有错位。这里应该是由于有两种不同的视角造成的,第一个视角是(我们的实现):[第i个字符的发射分数+第i个字符转移到第1个字符的分数]来得到第i个字符的分数,然后sum所有的i,这种做法会在最后一个时刻无法计算,因为最后一个时刻不再有i+1的跳转分数。第二个视角是(您的做法),就是[第i个字符的发射分数+(第i+1个字符的分数+第i个字符跳转到第i+1个字符的分数)],但实作的时候是通过把第0个单独拿出来(也就是您做法里面的emit_score[0]),然后sum所有的第i+1个字符的分数+第i个字符跳转到第i+1个字符的分数。这两种应该是等价的。
补充一下 @yhcc 的回答。对于一个长度为N的序列,有 N 个发射分数和 N-1 个转移分数 (N个点和中间N-1条边)。而我们求的 score 其实就是这些分数求和。因为是求和,所以先加谁后加谁都是可以的。您这里使用另一种方式实现了这个求和,理论上可以有很多种实现方式,都是等价的。
感谢您的解答
您好,我发现在decoder的crf.py的代码中,第263行是这样写的
score = trans_score + emit_score[:seq_len - 1, :]
其中的trans_score大小为[seq_len-1, batch_size],trans_score[0][0]代表第0个句子的第0个字符到第1个字符的转移得分; 而emit_score[:seq_len - 1, :]的大小为[seq_len-1, batch_size],emit_score[0, 0]代表第0个句子第0个字符的发射得分; 但是第0个句子第0个字符的转移得分不应该是start字符到第0个字符的score么?请问这里为什么不写成score = trans_score + emit_score[1:, :]
呢 感谢您的解答~