【问题标题】:custom loss function in Keras with masking array as inputKeras 中的自定义损失函数,以掩码数组作为输入
【发布时间】:2021-10-16 06:07:19
【问题描述】:

我正在尝试使用如下所示的自定义损失函数来训练自动编码器。输入 missing_matrix 是一个 n x m 的 1 和 0 数组,对应于 n x m 特征数组。我需要对missing_array 与y_pred 进行逐个元素的乘法运算,这应该是输入特征的重建,以便我可以掩盖那些乘以0 的那些,以忽略它们在成本函数中的贡献。我以前从未编写过自定义损失函数,下面的那个根本不起作用。我试图搜索类似的自定义成本函数,但无法找到一个能引入这样的输入数组的函数。我会很感激你的帮助或正确方向的一点。

def custom_loss(missing_array):
    
    def missing_mse(y_true, y_pred):
        mse = MeanSquaredError()
        y_pred_masked = tf.math.multiply(y_pred, missing_array)
        return mse(y_true = y_true, y_pred = y_pred_masked)

    return missing_mse

编辑:更进一步

from keras.losses import MeanSquaredError
import tensorflow as tf

def custom_loss(missing_matrix):
    
    def missing_mse(y_true, y_pred):
        mse = MeanSquaredError()
        y_pred_masked = tf.math.multiply(y_pred, tf.convert_to_tensor(missing_matrix, dtype=tf.float32))
        return mse(y_true = y_true, y_pred = y_pred_masked)

    return missing_mse

有错误

InvalidArgumentError:  Incompatible shapes: [64,1455] vs. [13580,1455]
     [[node gradient_tape/missing_mse/BroadcastGradientArgs (defined at <ipython-input-454-b60d74568bf2>:64) ]] [Op:__inference_train_function_25950]

Function call stack:
train_function

64 让我觉得是批次。可能我需要批量提取 64 个缺失的矩阵?

Edit2:这很有趣!所以我验证了如果我做类似的事情,自定义损失函数会训练

def train(self, model, X_train):
        """
        Model training
        """
        #model.fit(X_train, X_train, epochs = 10, batch_size = 64, validation_split = 0.10)
        for batch_idx in range(0, len(X_train), 70):
            self.batch_start = batch_idx
            self.batch_end = batch_idx + 70
            model.train_on_batch(X_train[self.batch_start:self.batch_end,:], X_train[self.batch_start:self.batch_end,:])
        return model

并修改我的自定义损失

def custom_loss2(self, missing_matrix):
    
        def missing_mse(y_true, y_pred):
            mse = MeanSquaredError()
            y_pred_masked = tf.math.multiply(y_pred, tf.convert_to_tensor(missing_matrix[self.batch_start:self.batch_end,:], dtype=tf.float32))
            return mse(y_true = y_true[self.batch_start:self.batch_end,:], y_pred = y_pred_masked[self.batch_start:self.batch_end,:])

        return missing_mse

那么现在我怎样才能获得 epoch 并打印出验证损失等...?或者更确切地说,这样做的更好方法是什么?今晚对我来说就是这样。晚安!

【问题讨论】:

    标签: python tensorflow machine-learning keras deep-learning


    【解决方案1】:

    问题是 y_truey_pred 是分批的,而掩码是一次性通过的。 一种自动将数据分成相等批次的简单解决方案是使用model.add_loss()

    下面我复制了一个带有自动编码器和自定义掩码损失的虚拟示例。掩码作为模型输入传递,这是使其工作所需的简单技巧。

    也使用mean_squared_error 而不是MeanSquaredError

    def missing_mse(y_true, y_pred, missing_array):
        
        y_pred_masked = tf.math.multiply(y_pred, missing_array)
        
        mse = tf.keras.losses.mean_squared_error(y_true = y_true, y_pred = y_pred_masked)
        
        return mse
    
    inp = Input((100,))
    x = Dense(20)(inp)
    out = Dense(100)(x)
    
    inp_mask = Input((100,))
    
    model = Model([inp, inp_mask], out)
    model.add_loss(missing_mse(inp, out, inp_mask))
    model.compile('adam', loss=None)
    
    X = np.random.uniform(0,1, (300,100))
    mask = np.random.randint(0,2, (300,100))
    
    model.fit(x=[X,mask], y=None, epochs=10, batch_size=64)
    
    # at inference time you can remove the mask input in this way
    new_model = Model(model.input[0], model.output)
    new_model.predict(X).shape
    

    【讨论】:

    • 谢谢!这就像一种魅力,更重要的是我学到了一些新东西。标记为已接受并已投票。
    猜你喜欢
    • 1970-01-01
    • 2019-01-11
    • 2019-08-22
    • 2021-05-23
    • 1970-01-01
    • 2020-12-19
    • 2017-12-18
    • 2020-03-27
    • 1970-01-01
    相关资源
    最近更新 更多