You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Keras中Embedding层输入形状不兼容问题求助

问题分析与解决

首先,你的代码存在两个核心问题:

  1. Tokenizer未拟合文本:你创建了Tokenizer但没有调用tokenizer.fit_on_texts(X)来学习词汇表,导致texts_to_sequences无法正确转换文本为有效数字序列。
  2. 输入输出形状不匹配:你把形状为(样本数, 20)的序列作为输入,同时把该序列的独热编码(形状变为(样本数, 20, 1000))作为输出,但模型最后一层Dense的输出形状是(样本数, 1000),两者维度完全不兼容,这就是报错Shapes (None, 20) and (None, 1000) are incompatible的直接原因。

文本生成/聊天机器人模型的核心逻辑是输入一段文本序列,预测下一个词(或对应回复),因此需要重新构建训练数据格式:将输入序列拆分为「前缀序列」和「目标词」,确保输入与输出的形状匹配模型结构。

以下是修正后的完整代码:

import numpy as np
from keras.layers import Dense, LSTM, Embedding
from keras.models import Sequential
from keras.preprocessing.text import Tokenizer
from keras.utils import pad_sequences, to_categorical

# 输入文本(如果是聊天机器人,建议使用一问一答的配对语料)
X = ["Hello!", "Greetings!"]

# 1. 先让Tokenizer学习词汇表
tokenizer = Tokenizer(num_words=1000)
tokenizer.fit_on_texts(X)
total_words = len(tokenizer.word_index) + 1  # 加1适配Embedding层的0索引

# 2. 构建训练用的输入-目标对
input_sequences = []
for line in X:
    token_list = tokenizer.texts_to_sequences([line])[0]
    # 生成n-gram序列:针对单词文本,生成输入序列对应目标词的结构
    for i in range(1, len(token_list)+1):
        n_gram_sequence = token_list[:i]
        input_sequences.append(n_gram_sequence)

# 3. 填充序列到统一长度
max_sequence_len = 20
input_sequences = pad_sequences(input_sequences, maxlen=max_sequence_len, padding='pre')

# 4. 拆分输入X和目标y:X是前缀序列,y是最后一个词的独热编码
X_train, y_train = input_sequences[:, :-1], input_sequences[:, -1]
y_train = to_categorical(y_train, num_classes=total_words)

# 5. 构建模型:输入长度为max_sequence_len-1(去掉目标词的位置)
model = Sequential()
model.add(Embedding(total_words, 100, input_length=max_sequence_len-1))
model.add(LSTM(100))
model.add(Dense(total_words, activation='softmax'))

model.summary()

model.compile(loss='categorical_crossentropy', metrics=['accuracy'])

# 训练:样本量极少,batch_size设为1避免报错
history = model.fit(X_train, y_train, epochs=50, batch_size=1)

# 预测示例
test_text = "Greetings!"
token_list = tokenizer.texts_to_sequences([test_text])[0]
token_list = pad_sequences([token_list], maxlen=max_sequence_len-1, padding='pre')
predicted = np.argmax(model.predict(token_list, verbose=0), axis=-1)
for word, index in tokenizer.word_index.items():
    if index == predicted:
        print(f"预测输出: {word}")

关键修正点说明:

  • Tokenizer必须拟合文本:调用fit_on_texts让Tokenizer学习输入文本的词汇表,否则无法将文本转换为有效数字序列。
  • 重构训练数据格式:将输入序列拆分为「前缀序列」和「目标词」,确保输入形状(样本数, max_sequence_len-1)与模型输入匹配,目标输出(样本数, total_words)与最后一层Dense的输出形状一致,彻底解决维度不兼容问题。
  • 适配小样本训练:你的输入样本量极少,训练时batch_size需设为1,避免因样本数不足抛出错误。

如果要构建真正可用的聊天机器人,建议使用一问一答的配对对话语料库,而非单句自学习,这样模型才能学习到对话的上下文关联逻辑。

内容的提问来源于stack exchange,提问作者Avusar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 06:20:41