构建维特比表时更新字典值内列表元素全为零问题咨询
问题原因分析
- 核心错误是q字典的初始化位置错误:你把
q[pos] = [0 for x in range(len(word_list[i]))]放在了j的循环体内部,每处理句子的第j个单词,都会把所有词性对应的概率列表全部重置为全0,之前j-1及更早位置写入的似然值会被直接清空,最终几乎所有位置都会被后续的j循环覆盖为0。 - 次要问题:大量无日志的
except KeyError: pass会吞掉所有字典查询缺失的异常,比如Transition转移矩阵、pos_dict发射概率字典缺对应key的情况,就算计算似然值的逻辑触发了异常你也无法感知,进一步提高了全零的概率。 - 逻辑偏差(如果是实现维特比解码的话):非句首位置的转移概率你直接取了标注语料里的前一个词的标注词性,维特比解码需要基于前一个位置所有可能词性的最大累积概率计算,当前的逻辑不符合维特比算法的要求。
修复方案
首先把q的初始化移到j循环的外层,每个句子只初始化一次:
for i in range(2): # 每个句子初始化一次q即可,不要放到j循环里 q = {} sentence_len = len(word_list[i]) for pos in pos_list: q[pos] = [0 for _ in range(sentence_len)] for j in range(sentence_len): try: word = word_list[i][j].split("\t")[0] for possible_pos in word_dict[word].keys(): try: if j == 0: TP = Transition['Begin_Sent'][possible_pos] EP = pos_dict[possible_pos][word] elif word_list[i][j + 1] == ".\t.": TP = Transition['End_Sent'][possible_pos] EP = 1 else: # 若仅计算标注序列似然则保留这段,实现维特比解码需要替换为前序位置最大累积概率计算逻辑 prev_pos = word_list[i][j - 1].split("\t")[1] TP = Transition[prev_pos][possible_pos] EP = pos_dict[possible_pos][word] likelihood = EP * TP q[possible_pos][j] = likelihood # 调试阶段先打印异常确认是否有key缺失 except KeyError as e: print(f"缺失key: {e},位置j={j},词性={possible_pos},词={word}") except IndexError as e: print(f"索引错误: {e},i={i}, j={j}") df = pd.DataFrame.from_dict(q, orient='index') print(df)
额外调试建议
- 先打印
likelihood的值,确认计算结果本身不是0,排除概率统计时的计数错误 - 确认
word_dict[word]能取到对应的候选词性列表,不会因为key缺失直接跳过内层赋值循环 - 确认Transition和pos_dict里存储的是归一化后的浮点型概率值,不是未归一化的整数计数
内容的提问来源于stack exchange,提问作者bloomsdayforever
相关产品推荐
相关产品推荐

