Keras构建LSTM模型时Initializer初始化报错求助
问题背景
你正在用Keras构建一个带Masking的多层LSTM模型,模型代码如下:
def LSTM_model_1(X_train,Y_train,Dropout,hidden_units): model = Sequential() model.add(Masking(mask_value=666, input_shape=(X_train.shape[1],X_train.shape[2]))) model.add(LSTM(hidden_units, activation='tanh', return_sequences=True, dropout=Dropout)) model.add(LSTM(hidden_units, return_sequences=True)) model.add(LSTM(hidden_units, return_sequences=True)) model.add(Dense(Y_train.shape[-1], activation='softmax')) model.compile(loss='mean_squared_error', optimizer='adam', metrics=['categorical_accuracy']) # 修正了原代码中metrics参数的语法错误 return model
你的输入数据形状为:
X_train.shape=(77,100,34)Y_train.shape=(77,100,7)(独热编码,填充值为0)
当前设置dropout=0、hidden_units=2,但在初始化第一个LSTM层时遇到了如下错误:
ValueError: Initializer for variable lstm_58/kernel/ is from inside a control-flow construct, such as a loop or conditional. When creating a variable inside a loop or conditional, use a lambda as the initializer.
堆栈跟踪信息如下:
File "C:\Users\310122653\Documents\GitHub\DNN\build_model.py", line 44, in LSTM_model_1 model.add(LSTM(hidden_units, activation='tanh', return_sequences=True, dropout=Dropout))
File "C:\ProgramData\Anaconda3\lib\site-packages\keras\models.py", line 492, in add output_tensor = layer(self.outputs[0])
File "C:\ProgramData\Anaconda3\lib\site-packages\keras\layers\recurrent.py", line 499, in call return super(RNN, self).call(inputs, **kwargs)
File "C:\ProgramData\Anaconda3\lib\site-packages\keras\engine\topology.py", line 592, in call self.build(input_shapes[0])
File "C:\ProgramData\Anaconda3\lib\site-packages\keras\layers\recurrent.py", line 461, in build self.cell.build(step_input_shape)
File "C:\ProgramData\Anaconda3\lib\site-packages\keras\layers\recurrent.py", line 1838, in build constraint=self.kernel_constraint)
File "C:\ProgramData\Anaconda3\lib\site-packages\keras\legacy\interfaces.py", line 91, in wrapper return func(*args, **kwargs)
File "C:\ProgramData\Anaconda3\lib\site-packages\keras\engine\topology.py", line 416, in add_weight constraint=constraint)
File "C:\ProgramData\Anaconda3\lib\site-packages\keras\backend\tensorflow_backend.py", line 395, in variable v = tf.Variable(value, dtype=tf.as_dtype(dtype), name=name)
File "C:\ProgramData\Anaconda3\lib\site-packages\tensorflow\python\ops\variables.py", line 235, in init constraint=constraint)
File "C:\ProgramData\Anaconda3\lib\site-packages\tensorflow\python\ops\variables.py", line 356, in _init_from_args "initializer." % name)
错误原因分析
这个错误本质是TensorFlow在控制流上下文(比如循环、条件分支)内创建变量时,无法直接使用常规的初始化器对象。虽然你没有显式写循环/条件,但Keras的LSTM层内部构建时,可能因为Masking层的动态形状处理逻辑,触发了控制流上下文,导致初始化器的张量转换出现异常(也就是你提到的convert_to_tensor后返回None的问题)。
常规的初始化器(比如默认的glorot_uniform)是一个对象,当在控制流内创建变量时,TensorFlow无法正确追踪它的初始化逻辑,所以要求你用lambda包装初始化器,延迟初始化逻辑的执行,确保变量创建时能正确获取到有效的张量。
解决方案:使用Lambda包装初始化器
你需要给LSTM层的kernel_initializer、recurrent_initializer、bias_initializer这些参数传递lambda函数,让lambda返回初始化器的调用结果。这样TensorFlow就能在正确的上下文里执行初始化逻辑。
修改后的模型代码
from keras.initializers import glorot_uniform, zeros # 导入Keras默认的初始化器 def LSTM_model_1(X_train,Y_train,Dropout,hidden_units): model = Sequential() model.add(Masking(mask_value=666, input_shape=(X_train.shape[1],X_train.shape[2]))) # 用lambda包装初始化器,延迟初始化逻辑执行 model.add(LSTM( hidden_units, activation='tanh', return_sequences=True, dropout=Dropout, kernel_initializer=lambda: glorot_uniform()(shape=None), recurrent_initializer=lambda: glorot_uniform()(shape=None), bias_initializer=lambda: zeros()(shape=None) )) # 后续所有LSTM层都需要添加同样的初始化器配置 model.add(LSTM( hidden_units, return_sequences=True, kernel_initializer=lambda: glorot_uniform()(shape=None), recurrent_initializer=lambda: glorot_uniform()(shape=None), bias_initializer=lambda: zeros()(shape=None) )) model.add(LSTM( hidden_units, return_sequences=True, kernel_initializer=lambda: glorot_uniform()(shape=None), recurrent_initializer=lambda: glorot_uniform()(shape=None), bias_initializer=lambda: zeros()(shape=None) )) model.add(Dense(Y_train.shape[-1], activation='softmax')) model.compile(loss='mean_squared_error', optimizer='adam', metrics=['categorical_accuracy']) return model
关键说明
- 这里我们用Keras默认的
glorot_uniform作为权重初始化器,zeros作为偏置初始化器,你可以根据需求换成其他初始化器(比如he_uniform)。 - lambda函数里调用初始化器时传递
shape=None,因为Keras会在构建层时自动传入正确的形状,我们只需要延迟初始化逻辑的执行即可。 - 所有的LSTM层都需要添加这些lambda包装的初始化器参数,避免后续层出现同样的错误。
另外,我注意到你原来的compile方法里metrics参数少了个等号(写成了metrics['categorical_accuracy'],应该是metrics=['categorical_accuracy']),已经在代码里修正了,这个小错误也可能导致后续的问题。
内容的提问来源于stack exchange,提问作者Florida Man

