Keras Lambda层调用backend gradients出现NoneType无dtype属性报错求解
问题根源与修复方案
报错的两个核心原因
- 梯度计算的两个张量不存在计算图依赖
你要计算dense_2相对于inputs_2的梯度,但dense_2的前向计算链路完全从inputs_1传递而来,全程没有用到inputs_2的任何值,二者在TensorFlow的计算图中没有关联,k.gradients(x[0], x[1])直接返回None,后续访问None的dtype属性就触发了报错。 k.gradients返回值未做提取k.gradients的返回值是梯度张量组成的列表,就算两个张量存在依赖,返回结果也是[梯度张量]的结构,你直接将列表作为Lambda层的输出,会导致输出结构异常,也就是你在模型摘要里看到的multiple输出形状,后续损失计算也会出错。
修复方案
首先需要把inputs_2接入前向计算链路,保证dense_2和inputs_2存在计算依赖,然后提取梯度列表的第一个元素作为Lambda层输出即可,修复后的示例代码如下:
import numpy as np import keras from keras.models import * from keras.layers import Input, Dense, Lambda, Flatten, Concatenate from tensorflow.keras.optimizers import Adam from keras import backend as k coords = np.random.rand(1000,5,3) forces = np.random.rand(1000,5,3) input_feat = np.random.rand(1000,17) # 避免和Python内置函数input重名 inputs_1 = Input((input_feat.shape[1],)) inputs_2 = Input((coords.shape[1], coords.shape[2])) initializer = 'normal' # 把坐标压平后和输入特征拼接,建立计算依赖 coords_flat = Flatten()(inputs_2) concat_feat = Concatenate(axis=1)([inputs_1, coords_flat]) dense_1 = Dense(1000, kernel_initializer=initializer, activation='relu')(concat_feat) dense_2 = Dense(1, kernel_initializer=initializer, activation="relu")(dense_1) # 提取梯度列表的第一个元素作为输出 out = Lambda(lambda x: k.gradients(x[0], x[1])[0], output_shape=(5,3))([dense_2, inputs_2]) model = Model(inputs=[inputs_1, inputs_2], outputs=out) model.compile(optimizer=Adam(learning_rate=0.0001), loss=keras.losses.mean_absolute_error) model.summary() history = model.fit([input_feat, coords], forces, batch_size=1, epochs=100, verbose=2, validation_split=0.1)
注意:如果你的业务逻辑本身不需要
inputs_2参与dense_2的计算,那二者之间天然不存在梯度关联,这个梯度计算的需求本身就不成立,需要先调整网络结构让坐标参数参与到预测值的计算中。
内容的提问来源于stack exchange,提问作者enga
相关产品推荐
相关产品推荐

