LSTM下一词预测中to_categorical报IndexError的解决求助
问题分析与解决方案
核心问题原因
Keras的Tokenizer默认从1开始为词汇分配索引,0是预留的未登录词(OOV)位置。你的代码存在两个关键矛盾:
- 计算
vocabulary_size时仅取实际词汇数量(len(tokenizer.word_counts)),但最大词索引等于该数值(比如报错中的2718)。 - 调用
to_categorical时,num_classes设为原词汇数量,导致索引范围(0~2717)无法容纳最大词索引(2718),触发越界错误。 - 尝试给
y减1时,仅修改了标签,但输入序列X的词索引仍保留1~2718,而Embedding层输入维度还是原词汇数量,索引范围不匹配,再次报错。
修复步骤
方法1:贴合Tokenizer默认行为(推荐)
保留Tokenizer的索引规则,修正词汇量计算和对应层参数:
- 修正词汇量计算:
vocabulary_size = len(tokenizer.word_counts) + 1 # +1 包含预留的0索引 - 修正to_categorical参数:
y = to_categorical(y, num_classes=vocabulary_size) - Embedding层自动适配:修正后的
vocabulary_size已包含0索引,Embedding层会覆盖0~2718的索引范围,匹配输入序列的索引。
方法2:统一转为0起始索引
如果想使用0起始的索引体系,需同时修改输入序列和标签:
- 所有序列索引减1:
sequences = np.array(sequences) - 1 # 把1~2718转为0~2717 vocabulary_size = len(tokenizer.word_counts) # 此时词汇量等于最大索引+1 - 保持后续参数一致:
y = to_categorical(y, num_classes=vocabulary_size) # Embedding层参数无需额外修改,vocabulary_size对应0~2717的范围 model.add(Embedding(vocabulary_size, 25, input_length=seq_len))
完整修复后的代码片段(方法1)
关键修改后的代码如下:
# ... 前面的文本处理代码不变 ... sequences = np.array(sequences) # 修正词汇量计算 vocabulary_size = len(tokenizer.word_counts) + 1 def create_model(vocabulary_size, seq_len): model = Sequential() # Embedding层使用修正后的vocabulary_size model.add(Embedding(vocabulary_size, 25, input_length=seq_len)) model.add(LSTM(100,return_sequences=True)) model.add(LSTM(100)) model.add(Dense(100,activation='relu')) # 输出层维度同步使用修正后的vocabulary_size model.add(Dense(vocabulary_size, activation='softmax')) model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy']) model.summary() return model X = sequences[:,:-1] y = sequences[:,-1] # to_categorical使用修正后的num_classes y = to_categorical(y, num_classes=vocabulary_size)
内容的提问来源于stack exchange,提问作者SShaurya
相关产品推荐
相关产品推荐

