为何无法用Keras初始化两个不同的字符级Tokenizer?
问题:拼写纠错Seq2Seq模型中两个Tokenizer的索引为何几乎一致?
我为拼写纠错任务构建了包含LSTM和注意力机制的Seq2Seq模型,采用Keras做字符级分词。分别为错误句子和正确句子初始化了两个Tokenizer,代码如下:
typos_tokenizer = tf.keras.preprocessing.text.Tokenizer( num_words=NUM_WORDS, filters='!"#$%&()*+,-./:;<=>?@[\\]^_`{|}~\t\n', lower=True, char_level=True ) corrects_tokenizer = tf.keras.preprocessing.text.Tokenizer( num_words=NUM_WORDS, filters='!"#$%&()*+,-./:;<=>?@[\\]^_`{|}~\t\n', lower=True, char_level=True )
测试后模型输出空字符串,排查后发现分词环节可能有问题。查看两个Tokenizer的word_index,发现大部分字符的索引一致,示例如下:
# 错误句子Tokenizer的分词结果 Tokenized sentence with typo tokenizer: [[20, 17, 2, 24, 8, 1, 13, 3, 5, 24, 4, 7, 7, 3, 6, 1, 4, 12, 3, 1, 27, 2, 13, 4, 1, 25, 2, 13, 2, 13, 1, 2, 19, 3, 23, 4, 1, 3, 27, 24, 2, 5, 3, 1, 23, 21]] # 错误句子Tokenizer的词汇表 Vocabulary: {' ': 1, 'a': 2, 'e': 3, 'i': 4, 'n': 5, 'r': 6, 'l': 7, 'ı': 8, 'd': 9, 'k': 10, 't': 11, 's': 12, 'm': 13, 'u': 14, 'y': 15, 'o': 16, 'b': 17, 'ü': 18, 'ş': 19, '<': 20, '>': 21, 'g': 22, 'v': 23, 'z': 24, 'h': 25, 'p': 26, 'c': 27, 'ç': 28, 'ğ': 29, 'ö': 30, 'f': 31, '1': 32, '0': 33, '2': 34, '9': 35, 'j': 36, 'w': 37, '8': 38, '3': 39, '5': 40, '4': 41, '6': 42, '7': 43, 'x': 44, 'q': 45} # 正确句子Tokenizer的分词结果 Tokenized sentence with corrects tokenizer: [[20, 17, 2, 24, 8, 1, 13, 3, 5, 24, 4, 7, 7, 3, 6, 1, 4, 12, 3, 1, 27, 2, 13, 4, 1, 25, 2, 13, 2, 13, 1, 2, 19, 3, 23, 4, 1, 3, 27, 24, 2, 5, 3, 1, 23, 21]] # 正确句子Tokenizer的词汇表 Vocabulary: {' ': 1, 'a': 2, 'e': 3, 'i': 4, 'n': 5, 'r': 6, 'l': 7, 'ı': 8, 'd': 9, 'k': 10, 't': 11, 's': 12, 'm': 13, 'u': 14, 'y': 15, 'o': 16, 'b': 17, 'ü': 18, 'ş': 19, '<': 20, '>': 21, 'g': 22, 'v': 23, 'z': 24, 'h': 25, 'p': 26, 'c': 27, 'ç': 28, 'ğ': 29, 'ö': 30, 'f': 31, '1': 32, '0': 33, '2': 34, '9': 35, '8': 36, '3': 37, 'j': 38, '5': 39, '4': 40, '6': 41, '7': 42, 'w': 43, 'x': 44, 'q': 45}
我原本期望得到两个不同的词索引字典,请问为何无法通过该方式初始化两个不同的Tokenizer?
解答
1. 两个Tokenizer索引大部分一致的原因
Keras的Tokenizer是基于训练数据的字符频率生成词汇表的:
- 你初始化的两个Tokenizer参数完全一致,且拼写纠错任务中错误句和正确句的字符集高度重叠(仅个别字符存在错写差异),高频字符的排序几乎不会变化,因此大部分字符的索引自然一致。
- 只有当某类字符在错误句和正确句中的频率排序存在明显差异时,才会出现索引不同的情况,比如你示例中的数字'8'、'3'等。
2. 模型输出空字符串的可能原因
这和Tokenizer的索引一致性无关,更可能是以下问题导致:
- 反向映射错误:Seq2Seq解码器需要用正确句子的Tokenizer做索引转字符的反向映射,如果解码时用错了Tokenizer,或者
index_word字典未正确生成,就可能输出空串。 - 训练数据预处理缺失:未给正确句子添加
<start>和<end>特殊标记,导致解码器无法明确生成的起止位置。 - 模型结构或训练问题:注意力机制实现有误、LSTM层输出维度不匹配,或者训练轮数不足、损失函数未收敛,都可能导致模型无法生成有效内容。
3. 拼写纠错任务中Tokenizer的正确用法
拼写纠错不需要两个独立的Tokenizer,正确做法是:
- 共用一个Tokenizer:用错误句+正确句的所有字符训练同一个Tokenizer,确保输入和输出的字符索引完全对齐,避免映射错误。
- 保留必要字符:确保
filters参数没有过滤掉拼写纠错所需的字符(当前配置已排除大部分无关符号,无需调整)。 - 统一添加特殊标记:给所有正确句子添加
<start>和<end>标记,明确解码器的生成边界。
内容的提问来源于stack exchange,提问作者marisami7
相关产品推荐
相关产品推荐

