迭代 Keras 自定义损失函数

数据挖掘 喀拉斯 损失函数
2022-03-08 16:42:37

我知道最好避免Keras自定义损失函数中的循环,但我认为我必须这样做。问题如下:我正在尝试实现一个损失函数,该函数计算多组数据的损失值,然后将这些值聚合为一个唯一值。

例如,我有 6 个数据条目,所以在我的Keras损失中,我将有 6y_true和 6 y_pred我想计算 2 个损失值:一个用于前 3 个元素,一个用于最后 3 个元素。

假设代码示例:

def custom_loss(y_true, y_pred): 
    start_range = 0
    losses = []
    for index in range(0,2):
        end_range = start_range + 3
        y_true_bunch = y_true[start_range:end_range]
        y_pred_bunch = y_pred[start_range:end_range]
        loss_value = ...some processing on bunches...
        losses.append(loss_value)
        start_range = end_range
    final_loss = ...aggregate loss_value...
    return final_loss

有可能实现这样的目标吗?我需要处理整个数据集并计算多个束的损失,然后将所有束值聚合为一个值。

1个回答

假设从那以后有 2 个分区,for index in range(0,2)并且从那以后固定的束大小为 3,start_range + 3

你的 y_true 的形状应该是(nb_samples, 2),其中第 2 维的第一个向量是 the ground_truth,另一个是partition_index

import numpy as np
import tensorflow as tf
import tensorflow.keras.backend as K
from tensorflow.keras.losses import mean_squared_error

y_true = tf.Variable(np.array([[1.5, 0],[1.2, 0],[1.3, 0],[1.6, 1],[3.0, 1],[2.25, 1]]), dtype=tf.float32)
y_pred = tf.Variable(np.array([[1.35],[1.24],[1.69],[1.55],[1.24],[1.69]]), dtype=tf.float32)

def get_two_splits(y_true):
    child_y = y_true[:, 1]
    child_y = tf.expand_dims(child_y, 1)
    y_true = y_true[:, 0]
    y_true = tf.expand_dims(y_true, 1)
    return y_true, child_y

def some_processing_on_bunches(y_all):
    y_true, y_pred = get_two_splits(y_all)
    return mean_squared_error(y_true, y_pred)

def custom_loss(y_true, y_pred):
    n = K.shape(y_true)[0]
    y_true, partitions = get_two_splits(y_true)
    partitions = tf.reshape(partitions ,[n, ])
    partitions = tf.cast(partitions, tf.int32)

    y_elements = tf.dynamic_partition(tf.concat([y_true, y_pred], 1), partitions, 2)
    losses = tf.vectorized_map(some_processing_on_bunches, tf.stack(y_elements))
    return tf.reduce_mean(losses, axis=1)

K.eval(custom_loss(y_true, y_pred))
>>>array([0.05873336, 1.1379    ], dtype=float32)