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

如何在Keras中定义与张量同形状的变量以自定义损失函数?

在Keras中自定义带可训练权重W的二元交叉熵损失函数

我来帮你解决这个问题,先梳理下你代码里的几个问题,再给你一个可行的实现方案:

你的代码里需要调整的点

  1. Keras张量不能直接用NumPy方法处理形状:bce_loss.size()这种写法不对,Keras张量是计算图中的节点,得用Keras后端的函数来获取形状,不能直接调用NumPy的方法。
  2. 可训练变量的创建时机错误:如果在损失函数内部每次计算都创建W,会导致每次都重新初始化,而且这个变量不会被加入模型的可训练参数列表,根本不会被优化器更新。
  3. 动态batch维度的处理:你的bce_loss形状是(?, 3),其中?是动态变化的batch大小,没法预先创建固定batch大小的变量——其实用Keras的广播机制就能解决,不用非要让W和bce_loss完全同形状。

正确的实现方案

我们把可训练变量W定义在损失函数的外层,这样它只会被创建一次,并且会被纳入模型的可训练参数。利用广播机制,让形状为(3,)的W自动匹配(?, 3)的bce_loss,实现元素级相乘:

import keras.backend as K
from keras.models import Model
from keras.layers import Input, Dense
import numpy as np

def custom_weighted_bce():
    # 初始化W:形状对应输出的特征维度(这里是3),用正态分布初始化
    W = K.variable(np.random.normal(0, 0.05, size=(3,)), name="loss_weight_W")
    
    def loss(y_true, y_pred):
        # 计算基础二元交叉熵
        bce_loss = K.binary_crossentropy(y_true, y_pred)
        # W会自动广播到bce_loss的形状(?, 3),实现每个位置的加权
        weighted_bce = W * bce_loss
        # 对每个样本的3个输出维度取平均
        return K.mean(weighted_bce, axis=-1)
    
    return loss

如何使用这个损失函数

你可以像普通损失函数一样在模型编译时调用:

# 构建示例模型
input_layer = Input(shape=(10,))
output_layer = Dense(3, activation="sigmoid")(input_layer)
model = Model(inputs=input_layer, outputs=output_layer)

# 编译模型时传入自定义损失
model.compile(optimizer="adam", loss=custom_weighted_bce())

# 测试训练流程
x_train = np.random.random((100, 10))
y_train = np.random.randint(2, size=(100, 3))
model.fit(x_train, y_train, epochs=2, batch_size=32)

额外说明

如果你确实需要W和bce_loss的形状完全一致(包括动态的batch维度),这种需求其实不太合理——因为batch大小是动态变化的,没法预先创建固定batch大小的可训练变量。如果是要给每个样本单独设置权重,那应该把权重作为模型的输入传入,而不是作为可训练变量。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 05:36:06