使用条件自定义keras中的损失函数
Costumizing loss function in keras with condition
我想为具有 4 个不同 类 的多分类问题设置一个 keras 模型(tensorflow 后端)。我有标记和未标记的数据。
我已经解决了只使用标记数据进行训练的情况,我的模型看起来像这样:
# create model
inputs = keras.Input(shape=(len(config.variables), ))
X = layers.Dense(units=200, activation="relu")(inputs)
output = layers.Dense(units=4, activation="softmax", name="output")(X)
model = keras.Model(inputs=inputs, outputs=output)
model.compile(optimizer=optimizers.Adam(1e-4), loss=loss_function, metrics=["accuracy"])
# train model
model.fit(
x=train_data,
y=train_class_labels,
batch_size=200,
epochs=200,
verbose=2,
validation_split=0.2,
sample_weight = class_weights
)
我有不同损失的功能模型,即 categorical_crossentropy
和 sparse_categorical_crossentropy
,并且根据损失函数,我的 train_class_labels
在单热表示中(例如 [ [0, 1,0,0], [0,0,0,1], ...]) 或整数表示(例如 [0,0,2,1,0,3, ...]),一切正常美好的。 class_weights
是一些权重向量 ([0.78, 1,34, ...])
现在为了我的进一步计划,我需要在训练过程中包含未标记的数据,但我需要它被损失函数忽略。
我尝试过的:
- 当使用
categorical_crossentropy
作为损失时,将未标记数据的标签设置为 [0,0,0,0],因为我认为我的未标记数据会被损失函数忽略。这不知何故改变了训练后的预测。
- 我也尝试将未标记数据的权重设置为 0,但这确实有影响
我得出结论,我需要以某种方式标记我未标记的数据并自定义我的损失函数,以便它可以被告知忽略这些样本。像
def custom_loss(y_true, y_pred):
if y_true == labeled data:
return normal loss function
if y_true == unlabeled data:
return 0
这些是我找到的一些片段,但它们似乎不起作用:
def custom_loss(y_true, y_pred):
loss = losses.sparse_categorical_crossentropy(y_true, y_pred)
return K.switch(K.flatten(K.equal(y_true, -1)), K.zeros_like(loss), loss)
def custom_loss2(y_true, y_pred):
idx = tf.not_equal(y_true, -1)
y_true = tf.boolean_mask(y_true, idx)
y_pred = tf.boolean_mask(y_pred, idx)
return losses.sparse_categorical_crossentropy(y_true, y_pred)
在这些示例中,我将未标记数据的标签设置为 -1,因此 train_class_labels
看起来像这样:[0,-1,2,0,3, ...]
但是当使用第一个损失函数时我得到了 Nans 而当使用第二个损失函数时我得到了以下错误:
Invalid argument: logits and labels must have the same first dimension, got logits shape [1,5000] and labels shape [5000]
我认为将标签设置为 [0,0,0,0] 就可以了。因为损失是根据每个 class 实例的对数损失总和计算的(在您的情况下,对于没有标签的实例,损失将为 0)。
我不明白你为什么要在监督设置中的训练中插入非标记数据。
我认为您获得的差异是由于批量大小和梯度步长造成的。如果有对梯度下降没有贡献的实例,计算出的损失会和之前不同,然后你得到预测的差异。
基本上每个批次的实例信息较少。
如果您使用所有数据集的大小作为批量大小,则与之前没有未标记实例的训练没有区别(但始终使用批量大小 = 数据集大小的训练)
我想为具有 4 个不同 类 的多分类问题设置一个 keras 模型(tensorflow 后端)。我有标记和未标记的数据。
我已经解决了只使用标记数据进行训练的情况,我的模型看起来像这样:
# create model
inputs = keras.Input(shape=(len(config.variables), ))
X = layers.Dense(units=200, activation="relu")(inputs)
output = layers.Dense(units=4, activation="softmax", name="output")(X)
model = keras.Model(inputs=inputs, outputs=output)
model.compile(optimizer=optimizers.Adam(1e-4), loss=loss_function, metrics=["accuracy"])
# train model
model.fit(
x=train_data,
y=train_class_labels,
batch_size=200,
epochs=200,
verbose=2,
validation_split=0.2,
sample_weight = class_weights
)
我有不同损失的功能模型,即 categorical_crossentropy
和 sparse_categorical_crossentropy
,并且根据损失函数,我的 train_class_labels
在单热表示中(例如 [ [0, 1,0,0], [0,0,0,1], ...]) 或整数表示(例如 [0,0,2,1,0,3, ...]),一切正常美好的。 class_weights
是一些权重向量 ([0.78, 1,34, ...])
现在为了我的进一步计划,我需要在训练过程中包含未标记的数据,但我需要它被损失函数忽略。
我尝试过的:
- 当使用
categorical_crossentropy
作为损失时,将未标记数据的标签设置为 [0,0,0,0],因为我认为我的未标记数据会被损失函数忽略。这不知何故改变了训练后的预测。 - 我也尝试将未标记数据的权重设置为 0,但这确实有影响
我得出结论,我需要以某种方式标记我未标记的数据并自定义我的损失函数,以便它可以被告知忽略这些样本。像
def custom_loss(y_true, y_pred):
if y_true == labeled data:
return normal loss function
if y_true == unlabeled data:
return 0
这些是我找到的一些片段,但它们似乎不起作用:
def custom_loss(y_true, y_pred):
loss = losses.sparse_categorical_crossentropy(y_true, y_pred)
return K.switch(K.flatten(K.equal(y_true, -1)), K.zeros_like(loss), loss)
def custom_loss2(y_true, y_pred):
idx = tf.not_equal(y_true, -1)
y_true = tf.boolean_mask(y_true, idx)
y_pred = tf.boolean_mask(y_pred, idx)
return losses.sparse_categorical_crossentropy(y_true, y_pred)
在这些示例中,我将未标记数据的标签设置为 -1,因此 train_class_labels
看起来像这样:[0,-1,2,0,3, ...]
但是当使用第一个损失函数时我得到了 Nans 而当使用第二个损失函数时我得到了以下错误:
Invalid argument: logits and labels must have the same first dimension, got logits shape [1,5000] and labels shape [5000]
我认为将标签设置为 [0,0,0,0] 就可以了。因为损失是根据每个 class 实例的对数损失总和计算的(在您的情况下,对于没有标签的实例,损失将为 0)。
我不明白你为什么要在监督设置中的训练中插入非标记数据。
我认为您获得的差异是由于批量大小和梯度步长造成的。如果有对梯度下降没有贡献的实例,计算出的损失会和之前不同,然后你得到预测的差异。
基本上每个批次的实例信息较少。
如果您使用所有数据集的大小作为批量大小,则与之前没有未标记实例的训练没有区别(但始终使用批量大小 = 数据集大小的训练)