Bidirectional层输入维度不兼容:期望3维输入却得到2维求助
问题根源分析
你遇到的错误expected ndim=3, found ndim=2. Full shape received: (None, 32),本质是双向LSTM层收到了2维输入,但它需要3维输入(格式为(batch_size, sequence_length, feature_dim))。结合你的代码,最可能的原因有两个:
- 文本向量化后的张量维度不符合预期,导致Embedding层输出异常;
- 错误地对输入张量做了维度扩展,打乱了Embedding层的输出结构。
分步解决方案
1. 确认文本向量化的输出维度
首先检查vectorized_text的形状,确保它是2维张量(样本数 × 序列长度):
print("Vectorized text shape:", vectorized_text.shape)
正常输出应该类似(num_samples, 1800),其中1800是你设置的output_sequence_length。如果输出是(num_samples,)或者其他非2维格式,说明TextVectorization没有正确处理输入文本:
- 检查
X.values是否为字符串数组(每个元素对应一个文本样本); - 确认
output_sequence_length参数设置正确,没有被误修改。
2. 移除错误的维度扩展操作
你尝试的train = train.map(lambda x, y: (tf.expand_dims(x, axis=-1), y))是错误的——Embedding层期望输入是2维的(batch_size, sequence_length),扩展维度后会变成3维(batch_size, sequence_length, 1),导致Embedding层输出4维张量,反而让后续的LSTM层无法处理。直接删除这行代码即可。
3. 验证数据集的batch维度
检查训练集的batch输入形状,确保符合模型要求:
for x_batch, y_batch in train.take(1): print("Train batch x shape:", x_batch.shape) print("Train batch y shape:", y_batch.shape)
正常输出应该是(16, 1800)(batch_size=16,序列长度=1800)和对应标签的形状(比如多标签分类的(16, 6))。
4. 修正测试输入的维度
你最后测试用的input_text是1维张量,输入模型前需要扩展为2维(添加batch维度):
input_text = vectorizer('You freaking suck! I am going to hit you.') input_text = tf.expand_dims(input_text, axis=0) # 形状变为(1, 1800) prediction = model.predict(input_text)
完整修正后的代码片段
vectorizer = TextVectorization(max_tokens=MAX_FEATURES, output_sequence_length=1800, output_mode='int') vectorizer.adapt(X.values) vectorized_text = vectorizer(X.values) # 确认向量化后的维度 print("Vectorized text shape:", vectorized_text.shape) dataset = tf.data.Dataset.from_tensor_slices((vectorized_text, y)) dataset = dataset.cache() dataset = dataset.shuffle(160000) dataset = dataset.batch(16) dataset = dataset.prefetch(8) train = dataset.take(int(len(dataset)*.7)) val = dataset.skip(int(len(dataset)*.7)).take(int(len(dataset)*.2)) test = dataset.skip(int(len(dataset)*.9)).take(int(len(dataset)*.1)) # 验证训练集batch维度 for x_batch, y_batch in train.take(1): print("Train batch x shape:", x_batch.shape) model = Sequential() model.add(Embedding(MAX_FEATURES+1, 32)) model.add(Bidirectional(LSTM(32, activation='tanh'))) model.add(Dense(128, activation='relu')) model.add(Dense(256, activation='relu')) model.add(Dense(128, activation='relu')) model.add(Dense(6, activation='sigmoid')) model.compile(loss='BinaryCrossentropy', optimizer='Adam') model.summary() history = model.fit(train, epochs=1, validation_data=val) # 修正测试输入 input_text = vectorizer('You freaking suck! I am going to hit you.') input_text = tf.expand_dims(input_text, axis=0) prediction = model.predict(input_text)
内容的提问来源于stack exchange,提问作者moosecles

