当前位置: 首页 > 知识库问答 >
问题:

在带条件的keras中实现自定义损失函数

姚烨
2023-03-14

我需要一些帮助与keras损失函数。我一直在Tensorflow后端的keras上实现自定义损失功能。

我已经在numpy中实现了自定义损失函数,但如果能将其转换为keras损失函数,那就太好了。丢失函数采用数据帧和用户id序列。如果用户id不同,则相同用户id的欧氏距离为正和负。函数返回数据帧的合计标量距离。

def custom_loss_numpy (encodings, user_id):
# user_id: a pandas series of users
# encodings: a pandas dataframe of encodings

    batch_dist = 0

    for i in range(len(user_id)):
         first_row = encodings.iloc[i,:].values
         first_user = user_id[i]

         for j in range(i+1, len(user_id)):
              second_user = user_id[j]
              second_row = encodings.iloc[j,:].values

        # compute distance: if the users are same then Euclidean distance is positive otherwise negative.
            if first_user == second_user:
                tmp_dist = np.linalg.norm(first_row - second_row)
            else:
                tmp_dist = -np.linalg.norm(first_row - second_row)

            batch_dist += tmp_dist

    return batch_dist

我试图实现到keras损失函数。我提取Numpy数组从y_true和y_pred张量对象。

def custom_loss_keras(y_true, y_pred):
    # session of my program
    sess = tf_session.TF_Session().get()

    with sess.as_default():
        array_pred = y_pred.eval()
        print(array_pred)

但是我得到了以下错误。

tensorflow.python.framework.errors_impl.InvalidArgumentError: You must feed a value for placeholder tensor 'dense_1_input' with dtype float and shape [?,102]
 [[Node: dense_1_input = Placeholder[dtype=DT_FLOAT, shape=[?,102], _device="/job:localhost/replica:0/task:0/device:CPU:0"]()]]

任何形式的帮助都将不胜感激。

共有2个答案

赵涵亮
2023-03-14

在Keras中实现参数化自定义损失函数有两个步骤。首先,编写系数/度量的方法。第二,编写一个包装器函数,按照Keras所需的方式对内容进行格式化。

>

  • 实际上,对于像DICE这样的简单自定义损失函数,使用Keras后端而不直接使用tenstorflow会更干净。下面是这样实现的系数的一个例子:

    import keras.backend as K
    def dice_coef(y_true, y_pred, smooth, thresh):
        y_pred = y_pred > thresh
        y_true_f = K.flatten(y_true)
        y_pred_f = K.flatten(y_pred)
        intersection = K.sum(y_true_f * y_pred_f)
        return (2. * intersection + smooth) / (K.sum(y_true_f) + K.sum(y_pred_f) + smooth)
    

    现在是棘手的部分。Keras损失函数只能将(y\u true,y\u pred)作为参数。所以我们需要一个单独的函数来返回另一个函数:

    def dice_loss(smooth, thresh):
        def dice(y_true, y_pred)
            return -dice_coef(y_true, y_pred, smooth, thresh)
        return dice
    

    最后,您可以在Kerascompile中使用它,如下所示:

    # build model 
    model = my_model()
    # get the loss function
    model_dice = dice_loss(smooth=1e-5, thresh=0.5)
    # compile model
    model.compile(loss=model_dice)
    

  • 司徒泰
    2023-03-14

    首先,在Keras损失函数中不能“从y_truey_pred中提取Numpy数组”。您必须使用Keras后端函数(或TF函数)操作张量来计算损失。

    换句话说,最好考虑一种“矢量化”的方法来计算损耗,而不使用if-else和循环。

    可以通过以下步骤计算损失函数:

    1. 编码中的所有向量对之间生成成对欧氏距离矩阵。
    2. 生成一个矩阵I,其元素I_ij为1 ifuser_i==user_j,-1 ifuser_i!=user_j.
    3. 以元素的方式将两个矩阵相乘,并将元素相加得到最终损失。

    下面是一个实现:

    def custom_loss_keras(user_id, encodings):
        # calculate pairwise Euclidean distance matrix
        pairwise_diff = K.expand_dims(encodings, 0) - K.expand_dims(encodings, 1)
        pairwise_squared_distance = K.sum(K.square(pairwise_diff), axis=-1)
    
        # add a small number before taking K.sqrt for numerical safety
        # (K.sqrt(0) sometimes becomes nan)
        pairwise_distance = K.sqrt(pairwise_squared_distance + K.epsilon())
    
        # this will be a pairwise matrix of True and False, with shape (batch_size, batch_size)
        pairwise_equal = K.equal(K.expand_dims(user_id, 0), K.expand_dims(user_id, 1))
    
        # convert True and False to 1 and -1
        pos_neg = K.cast(pairwise_equal, K.floatx()) * 2 - 1
    
        # divide by 2 to match the output of `custom_loss_numpy`, but it's not really necessary
        return K.sum(pairwise_distance * pos_neg, axis=-1) / 2
    

    我假设user\u id是上面代码中的整数。这里的技巧是使用K.expand_dims实现成对操作。乍一看可能有点难理解,但它非常有用。

    它应该给出与custom\u loss\u numpy大致相同的损耗值(由于K.epsilon(),会有一点不同):

    encodings = np.random.rand(32, 10)
    user_id = np.random.randint(10, size=32)
    
    print(K.eval(custom_loss_keras(K.variable(user_id), K.variable(encodings))).sum())
    -478.4245
    
    print(custom_loss_numpy(pd.DataFrame(encodings), pd.Series(user_id)))
    -478.42953553795815
    

    我在损失函数中犯了一个错误。

    在训练中使用此函数时,由于Keras会自动将y\u true更改为至少2D,因此参数user\u id不再是1D张量。它的形状将是(批量大小,1)

    要使用此功能,必须拆下额外的轴:

    def custom_loss_keras(user_id, encodings):
        pairwise_diff = K.expand_dims(encodings, 0) - K.expand_dims(encodings, 1)
        pairwise_squared_distance = K.sum(K.square(pairwise_diff), axis=-1)
        pairwise_distance = K.sqrt(pairwise_squared_distance + K.epsilon())
    
        user_id = K.squeeze(user_id, axis=1)  # remove the axis added by Keras
        pairwise_equal = K.equal(K.expand_dims(user_id, 0), K.expand_dims(user_id, 1))
    
        pos_neg = K.cast(pairwise_equal, K.floatx()) * 2 - 1
        return K.sum(pairwise_distance * pos_neg, axis=-1) / 2
    
     类似资料:
    • 嗨,我一直试图使一个自定义损失函数在kerasdice_error_coefficient。它有它的实现在张量板和我尝试使用相同的函数在keras与张量流但它不断返回一个NoneType当我使用model.train_on_batch或model.fit在那里,因为它给适当的值时,使用在模型中的指标...能不能请人帮帮我我该怎么办?我尝试过跟随像Keras-FCN这样的库,在那里他使用了自定义损失

    • 我手头有一个问题,它优化了一个损失函数,而不是y_pred和y_true的函数。通过Keras留档后,我发现所有自定义损失函数必须是y_pred和y_true的函数。 在Keras中是否有其他方法实现我的损失函数?

    • 我在Tensorflow后端使用Keras。我想创建一个自定义损失函数,它将获得两个直方图之间的欧几里德距离,但我得到了以下错误: TypeError:“Mul”Op的输入“y”的类型float32与参数“x”的类型int32不匹配。 因此,我不知道如何定义我的损失函数。 我试图修改代码,但我得到另一个错误。“h_true=tf.cast(h_true,dtype=tf.dtypes.float3

    • 我正在尝试使用Keras创建自定义损失函数。我想根据输入计算损失函数并预测神经网络的输出。 我尝试在Keras中使用自定义loss函数。我认为y_true是我们为训练提供的输出,y_pred是神经网络的预测输出。下面的损失函数与 Keras 中的“mean_squared_error”损失相同。 我想使用神经网络的输入也计算自定义损失函数除了mean_squared_error损失。有没有办法将输

    • 我有一个NN,它有两个相同的CNN(类似于暹罗网络),然后合并输出,并打算在合并的输出上应用自定义损失函数,如下所示: 在我的自定义损失函数中,我需要将y垂直分解为两块,然后对每一块应用分类交叉熵损失。但是,我不断从我的损失函数得到dtype错误,例如: ()中的ValueError回溯(最近一次调用)---- /usr/local/lib/python3。5/地区包/KERA/发动机/培训。编译

    • 我试图在Keras中构造一个自定义损失函数-这是用于生存分析中的删失数据。 这种损失函数本质上是二元交叉熵,即多标签分类,但是损失函数中的求和项需要根据Y_true标签的可用性而变化。见下面的例子: 示例1:Y_可用的所有标签均为True Y_true=[0,0,0,1,1] Y_pred=[0.1,0.2,0.2,0.8,0.7] 损失=-1/5(log(0.9)log(0.8)log(0.8)