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

TF2.6下Keras用GradientTape实现自定义损失函数报错如何解决

问题解决方法

报错根因

报错的核心原因是Keras模型编译阶段,model.input是静态的KerasTensor占位符对象,不是模型运行时实际喂入的tf.Tensor类型输入,无法直接通过tf.convert_to_tensor转换;同时在损失函数内部调用model(x_tensor)会重复构建前向计算逻辑,引发计算图嵌套冲突。

推荐解决方案:使用自定义训练循环

你要实现的物理信息神经网络(PINN)损失逻辑(需要计算输出对输入的导数)最适合用自定义训练循环实现,自由度更高也不会触发静态图占位符冲突,修改后的可运行代码如下:

from numpy import loadtxt
from keras.models import Sequential
from keras.layers import Dense
import tensorflow as tf #tf.__version__ = '2.6.0'
# 加载数据集
dataset = loadtxt('pima-indians-diabetes.csv', delimiter=',')
# 拆分输入输出
X = dataset[:,0:8] 
y = dataset[:,8]
X = tf.convert_to_tensor(X, dtype=tf.float32)
y = tf.convert_to_tensor(y, dtype=tf.float32)
# 构建模型
model = Sequential()
model.add(Dense(12, input_dim=8, activation='relu'))
model.add(Dense(12, activation='relu'))
model.add(Dense(12, activation='relu'))
model.add(Dense(1, activation='sigmoid'))
# 定义优化器和指标
optimizer = tf.keras.optimizers.Adam()
loss_metric = tf.keras.metrics.Mean(name='loss')
acc_metric = tf.keras.metrics.BinaryAccuracy(name='accuracy')
# 自定义训练步
@tf.function
def train_step(x, y_true):
    with tf.GradientTape(persistent=True) as t:
        t.watch(x)
        y_pred = model(x, training=True)
        # 计算PDE残差损失
        DyDX = t.gradient(y_pred, x)
        dy_t = DyDX[:, 5:6]
        loss_PDE = tf.reduce_mean(tf.square(dy_t))
        # 需添加数据损失可在此处写逻辑
        # loss_data = tf.reduce_mean(tf.square(y_true - y_pred))
        total_loss = loss_PDE
    # 计算梯度更新参数
    grads = t.gradient(total_loss, model.trainable_variables)
    optimizer.apply_gradients(zip(grads, model.trainable_variables))
    # 更新训练指标
    loss_metric.update_state(total_loss)
    acc_metric.update_state(y_true, y_pred)
    return {
        'loss': loss_metric.result(),
        'accuracy': acc_metric.result()
    }
# 训练循环
EPOCHS = 15
for epoch in range(EPOCHS):
    # 重置每轮指标
    loss_metric.reset_states()
    acc_metric.reset_states()
    
    # 执行训练步,大数据集可自行修改为按batch迭代
    metrics = train_step(X, y)
    
    print(f'Epoch {epoch+1}/{EPOCHS}, loss: {metrics["loss"].numpy():.4f}, accuracy: {metrics["accuracy"].numpy():.4f}')

替代方案:使用add_loss适配fit模式

如果你不想完全改写训练逻辑,也可以通过add_loss接口将输入张量传入损失计算逻辑,修改如下:

from numpy import loadtxt
from keras.layers import Dense, Input
import tensorflow as tf

dataset = loadtxt('pima-indians-diabetes.csv', delimiter=',')
X = dataset[:,0:8] 
y = dataset[:,8]
X = tf.convert_to_tensor(X, dtype=tf.float32)
y = tf.convert_to_tensor(y, dtype=tf.float32)
# 显式定义输入层
inputs = Input(shape=(8,))
x = Dense(12, activation='relu')(inputs)
x = Dense(12, activation='relu')(x)
x = Dense(12, activation='relu')(x)
outputs = Dense(1, activation='sigmoid')(x)
model = tf.keras.Model(inputs=inputs, outputs=outputs)
# 计算PDE损失并添加到模型
with tf.GradientTape() as t:
    t.watch(inputs)
    pred = model(inputs)
DyDX = t.gradient(pred, inputs)
dy_t = DyDX[:,5:6]
pde_loss = tf.reduce_mean(tf.square(dy_t))
model.add_loss(pde_loss)
# 编译训练,此处loss填None即可,损失已通过add_loss添加
model.compile(optimizer='adam', metrics=['accuracy'])
model.fit(X, y, epochs=15)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 15:48:04