传递可训练的参数以在Keras中权重损失,同时使用生成器作为输入

时间:2019-02-25 17:21:09

标签: python parameters keras deep-learning loss

在Keras中创建自定义损失函数时,我将可训练的权重应用于其他类型的损失时遇到了一个问题。下面的代码片段显示了我同时学习三个损失的权重-c_a,c_b,c_c 的方法。我使用生成器来获取输入,这是与@DanielMöller回答的其他几个问题的主要区别。

我在主要方法custom_loss内定义了一个train_test函数,该函数包括模型生成部分。为了训练这些参数,我定义了一个输入层weight_input = keras.Input((3,))并将其添加为keras.Model的附加输入,还将weight_input作为custom_loss函数的参数。

这是我的问题:

我想将三个值weight_inputs: c_a, c_b, c_c定义为[1,1,1],并希望在训练进行时更改它们。因此,我想不必为每个数据样本都包含这些值(就像生成器函数中的其他输入:visit_input, areas_input, visit_features_input一样),但是我仍然不清楚如何将这三个值传递给在现有发电机上添加其他输入?

当前data.train_data_generatordata.test_data_generator的结果包括visit_input, areas_input, visit_features_input。那么我应该如何将这些权重传递给customer_loss函数并使其可训练?

from data import *
import keras

def train_test(self):

    def custom_loss(weight_inputs):
        def _custom_loss(y_true, y_pred):
            # Calculation part of loss_a, loss_b, loss_c are removed too.
            # Scalar value - c_a, c_b, c_c - should be an element of weight_inputs, respectively. 
            total_loss = self.c_a * loss_a + self.c_b * loss_b + self.c_c * loss_c 

            return total_loss

        return _custom_loss


    # ... Additional NN structure before logits 
    # (visit_input, areas_input, visit_features_input, weight_input were put in a proper way)

    # Final prediction layer    
    logits = keras.layers.Dense(365, activation=keras.activations.softmax)(concat)

    # weight parameter input for custom loss function
    weight_input = keras.Input((3,))

    # Define a model and compile
    self.model = keras.Model(inputs=[visit_input, areas_input, visit_features_input, weight_input], outputs=logits)
    self.model.compile(optimizer=keras.optimizers.Adam(0.001),
                       loss=custom_survival_loss(weight_input),
                       )

    # Train
    self.train_data = data.train_data_generator()
    self.test_data = data.test_data_generator()

    # Fit
    self.history = self.model.fit_generator(
        generator=self.train_data,
        steps_per_epoch=train_data_size//FLAGS.batch_size,
        epochs=FLAGS.train_epochs,
        callbacks=[TrackTestDataPerformanceCallback(data, self.test_data)]
    )

    self.result = self.model.predict_generator(
        generator=self.test_data,
        steps=1
    )

    # Evaluate function (The trained weights should be used in this method too)
    evaluate(data, self.result)

生成器的定义如下。 (在添加weight_inputs部分之前)

    def train_data_generator(self):
        def __gen__():
            while True:
                idxs = list(self.df_train.index)
                np.random.shuffle(idxs)
                for idx in idxs:
                    visit = self.train_visits.iloc[idx]
                    label = self.df_train.iloc[idx]
                    yield visit['visit_indices'], visit['area_indices'], \
                          [visit[ft] for ft in self.handcrafted_features], \
                          [label[ft] for ft in ['label', 'suppress_time']]

        gen = __gen__()

        while True:
            batch = [np.stack(x) for x in zip(*(next(gen) for _ in range(FLAGS.batch_size)))]
            yield [batch[0].reshape(-1, 1), batch[1], batch[2]], batch[-1]

加:我想在custom_loss中维护几个子损失函数,因为一些计算可以在不同的损失之间重用。

0 个答案:

没有答案