使用Keras Sequential API构建含Embedding层的SimpleRNN模型遇异常
Keras Sequential API输出形状为?、可训练参数为0的问题排查与解决
问题原因
你遇到的问题本质是Sequential模型未完成构建(unbuilt):
- 使用Functional API时,
Input(shape=(100,))直接定义了输入维度,后续每一层都会基于前一层的输出形状自动计算自身参数,模型初始化后就完成了构建,所以summary()能正常显示输出形状和可训练参数。 - 而Sequential模型通过列表传入层初始化时,Keras不会自动触发模型构建——虽然Embedding层指定了
input_length=100,但这个参数只是层的配置,没有直接传递给模型作为整体输入形状的约束,导致模型处于未初始化状态,无法计算参数和输出形状。
解决方法
有三种简单的方式可以触发Sequential模型的构建:
方法1:显式调用build()指定输入形状
在compile()前添加model.build(),明确告诉模型输入的形状(第一个维度是批量大小,设为None表示支持可变批量):
from keras.models import Sequential from keras.layers import Embedding, SimpleRNN, Dense model = Sequential([ Embedding(input_dim=10000, output_dim=50, input_length=100), SimpleRNN(32), Dense(1, activation='sigmoid') ]) # 显式构建模型,指定输入形状 model.build(input_shape=(None, 100)) model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy']) model.summary()
方法2:用一批测试数据触发构建
传入任意符合输入形状的张量(比如全零张量)调用模型,会自动触发构建:
import numpy as np from keras.models import Sequential from keras.layers import Embedding, SimpleRNN, Dense model = Sequential([ Embedding(input_dim=10000, output_dim=50, input_length=100), SimpleRNN(32), Dense(1, activation='sigmoid') ]) # 用一批测试数据触发模型构建 model.predict(np.zeros((1, 100))) model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy']) model.summary()
方法3:改用add()方法逐层添加层
逐层添加层时,若第一层指定了input_shape或input_length,Keras会自动推断模型输入形状并完成构建:
from keras.models import Sequential from keras.layers import Embedding, SimpleRNN, Dense model = Sequential() model.add(Embedding(input_dim=10000, output_dim=50, input_length=100)) model.add(SimpleRNN(32)) model.add(Dense(1, activation='sigmoid')) model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy']) model.summary()
验证效果
采用上述任意一种方法后,model.summary()会输出和Functional API一致的结果:
- 各层输出形状会正确显示(比如
(None, 50)、(None, 32)、(None, 1)) - 可训练参数会正确计算(Embedding层500000 + SimpleRNN层2624 + Dense层33,总计502657)
内容的提问来源于stack exchange,提问作者Arjun Kumar
相关产品推荐
相关产品推荐

