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

Keras自定义损失函数报错:无法遍历tf.Tensor,求解决方案

解决TensorFlow自定义损失函数的OperatorNotAllowedInGraphError错误

你遇到的OperatorNotAllowedInGraphError确实是因为在TensorFlow图模式下,不能用Python列表推导式遍历tf.Tensor对象——AutoGraph会将损失函数转换为计算图,而Python的迭代逻辑无法被正确转换为图兼容的操作。

解决方案:用TensorFlow原生张量操作替代列表推导式

你的张量形状为(None, 7, 3),最后一个维度对应需要拆分的3个部分,直接通过张量索引或tf.split即可完成拆分,这两种操作都是图兼容的:

方法1:直接张量索引(推荐,更简洁)

直接通过维度索引提取最后一维的三个分量,保持张量形状为(None, 7):

# 替换原来的列表推导式部分
upper_b_true = y_true[:, :, 0]
y_med_true = y_true[:, :, 1]
lower_b_true = y_true[:, :, 2]

upper_b_pred = y_pred[:, :, 0]
y_med_pred = y_pred[:, :, 1]
lower_b_pred = y_pred[:, :, 2]

方法2:使用tf.split拆分

如果需要更灵活的维度拆分,可以用tf.split,之后用tf.squeeze去掉多余的单维度:

# 按最后一维拆分为3个张量,每个形状为(None,7,1)
upper_b_true, y_med_true, lower_b_true = tf.split(y_true, 3, axis=-1)
# 去掉最后一维,变为(None,7)
upper_b_true = tf.squeeze(upper_b_true, axis=-1)
y_med_true = tf.squeeze(y_med_true, axis=-1)
lower_b_true = tf.squeeze(lower_b_true, axis=-1)

# 对y_pred执行同样操作
upper_b_pred, y_med_pred, lower_b_pred = tf.split(y_pred, 3, axis=-1)
upper_b_pred = tf.squeeze(upper_b_pred, axis=-1)
y_med_pred = tf.squeeze(y_med_pred, axis=-1)
lower_b_pred = tf.squeeze(lower_b_pred, axis=-1)

修改后的完整损失函数代码

class new_loss(tf.keras.losses.Loss):
    def __init__(self, tr1, tr2):
        super(new_loss, self).__init__()
        self.tr1 = tr1
        self.tr2 = tr2

    def call(self, y_true, y_pred):
        #pre-determined value
        tr1 = tf.constant(self.tr1)
        tr2 = tf.constant(self.tr2)
        
        # 改用张量索引拆分,替代列表推导式
        upper_b_true = y_true[:, :, 0]
        y_med_true = y_true[:, :, 1]
        lower_b_true = y_true[:, :, 2]
        
        upper_b_pred = y_pred[:, :, 0]
        y_med_pred = y_pred[:, :, 1]
        lower_b_pred = y_pred[:, :, 2]
        
        #MSE part
        err = y_med_true - y_med_pred
        mse_loss = tf.math.reduce_mean(tf.math.square(err))
        
        #Narrow bound
        bound_dif = upper_b_pred - lower_b_pred
        bound_loss = tf.math.reduce_mean(bound_dif)
        
        #Prob metric
        in_upper = y_med_pred <= upper_b_pred
        in_lower = y_med_pred >= lower_b_pred
        prob = tf.logical_and(in_upper,in_lower)
        prob = tf.math.reduce_mean(tf.where(prob,1.0,0.0))
        
        return mse_loss + tf.multiply(tr1, bound_loss) + tf.multiply(tr2, prob)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 22:45:34