实现BeamSearch后RNN仅预测EOS的问题排查求助
RNN解码器BeamSearch立即预测EOS Token问题排查
以下是针对该问题的核心排查方向:
EOS Token初始概率异常
打印解码第一步的decoder_output(LogSoftmax输出),查看EOS对应的log概率是否远高于其他token。如果是,说明模型训练时可能过度拟合EOS触发条件,或是EOS的标签权重设置过高。BeamNode初始化与状态维护错误
检查BeamNode的实现:- 是否误将初始路径的EOS标记设为
True? - 累计概率与长度归一化的计算是否正确?比如归一化是否使用路径总log概率除以路径长度,而非单步概率除以长度?
- 是否误将初始路径的EOS标记设为
长度归一化的逻辑漏洞
确认归一化的时机:- 是否每一步扩展beam时,都对路径的累计log概率做了长度归一化后再排序?
- 预测EOS后,路径是否停止长度增长,且后续不再参与错误的归一化计算?
RNN上下文状态传递错误
检查beam扩展时,每条路径对应的hidden state是否正确复制和传递。若某条beam的hidden state异常(如初始hidden与输入不匹配),模型可能直接输出EOS终止错误路径。训练与解码的一致性问题
- 训练时用teacher forcing,解码时用自回归输入,若模型对输入分布变化敏感,可能触发EOS。可尝试在训练中加入部分自回归训练缓解。
- 确认
LogSoftmax是否在token维度上计算,避免因维度错误导致概率分布异常。
代码检查关键点示例
# 检查BeamNode的归一化逻辑 class BeamNode: def __init__(self, hidden_state, prev_node, token_id, total_log_prob, length): self.hidden_state = hidden_state self.prev_node = prev_node self.token_id = token_id self.total_log_prob = total_log_prob # 路径累计log概率 self.length = length # 正确的长度归一化:累计概率除以路径长度 self.normalized_prob = self.total_log_prob / self.length # 检查BeamSearch的beam选择逻辑 def update_beam(self): # 收集所有候选节点 all_candidates = [] for node in self.current_beams: if node.token_id == EOS_TOKEN: all_candidates.append(node) continue # 单步输出转候选节点 log_probs, tokens = self.decoder_output.topk(self.beam_size) for prob, token in zip(log_probs[0], tokens[0]): new_total_prob = node.total_log_prob + prob new_length = node.length + 1 all_candidates.append(BeamNode(node.hidden_state, node, token, new_total_prob, new_length)) # 按归一化概率排序取top beam_size all_candidates.sort(key=lambda x: x.normalized_prob, reverse=True) self.current_beams = all_candidates[:self.beam_size]
内容的提问来源于stack exchange,提问作者DustyAvocado
相关产品推荐
相关产品推荐

