在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_generator
和data.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
中维护几个子损失函数,因为一些计算可以在不同的损失之间重用。