在Keras中为验证集使用不同的损失函数

7

我有一个不平衡的训练数据集,这就是我构建自定义加权分类交叉熵损失函数的原因。但问题是我的验证集是平衡的,我想在Keras中使用常规的分类交叉熵损失。所以我能否在Keras中为验证集传递不同的损失函数?我的意思是用加权损失函数进行训练,用常规损失函数进行验证集。

def weighted_loss(y_pred, y_ture):
 '
 '
 '


return loss

model.compile(loss= weighted_loss, metric='accuracy')
2个回答

16

您可以尝试使用后端函数K.in_train_phase(),该函数被DropoutBatchNormalization层用于在训练和验证中实现不同的行为。

def custom_loss(y_true, y_pred):
    weighted_loss = ... # your implementation of weighted crossentropy loss
    unweighted_loss = K.sparse_categorical_crossentropy(y_true, y_pred)
    return K.in_train_phase(weighted_loss, unweighted_loss)

K.in_train_phase()的第一个参数是训练阶段使用的张量,第二个参数是测试阶段使用的张量。

例如,如果我们将weighted_loss设置为0(仅为验证K.in_train_phase()函数的效果):

def custom_loss(y_true, y_pred):
    weighted_loss = 0 * K.sparse_categorical_crossentropy(y_true, y_pred)
    unweighted_loss = K.sparse_categorical_crossentropy(y_true, y_pred)
    return K.in_train_phase(weighted_loss, unweighted_loss)

model = Sequential([Dense(100, activation='relu', input_shape=(100,)), Dense(1000, activation='softmax')])
model.compile(optimizer='adam', loss=custom_loss)
model.outputs[0]._uses_learning_phase = True  # required if no dropout or batch norm in the model

X = np.random.rand(1000, 100)
y = np.random.randint(1000, size=1000)
model.fit(X, y, validation_split=0.1)

Epoch 1/10
900/900 [==============================] - 1s 868us/step - loss: 0.0000e+00 - val_loss: 6.9438

正如你所看到的,在训练阶段中的损失确实是乘以0的。

请注意,如果您的模型中没有使用dropout或batch norm,则需要手动“开启”_uses_learning_phase布尔开关,否则K.in_train_phase()默认情况下将不会起任何作用。


这正是我在寻找的。谢谢Yu-Yang。关于你最后提到的'_uses_learning_phase'的问题,我只有一个疑问。我认为测试的默认值为'0',训练的默认值为'1',我的模型具有批量归一化和dropout层。所以我需要手动打开它吗? - W. Sam
1
我提到的_uses_learning_phase是另一回事。它是一个布尔变量,用于控制“学习阶段”变量(即您提到的变量——测试为0,训练为1)在模型训练中是否起作用。如果您的模型中有dropout,则不需要手动打开它。 - Yu-Yang
1
"_uses_learning_phase" 是一个内部变量,如果模型输出中有任何在训练/验证过程中表现不同的组件(例如dropout、批量归一化),它将被附加到模型输出上。 - Yu-Yang
1
您可以选择模型的任何输出张量,并将其设置为 _uses_learning_phase = True,就像我在此答案的示例中所做的那样 (model.outputs[0]._uses_learning_phase = True)。这是一项实现细节,因此我认为不太可能在任何地方都有记录。 - Yu-Yang
你在损失函数方面似乎很有经验,能否看到我的问题并帮我解决一下?我会非常感激。https://stackoverflow.com/questions/52269603/multiple-losses-for-imbalanced-dataset-with-keras - W. Sam
显示剩余6条评论

2

验证损失函数仅是一种度量标准,实际上不需要用于训练。它的存在是因为比较你的网络实际优化的指标是有意义的。因此,在编译期间添加其他损失函数作为指标,你将在训练过程中看到它。


我知道每个epoch结束时验证损失报告的值仅用于优化目的和了解模型最佳水平有多远。但当验证集是平衡的,这意味着每个epoch报告的验证损失值是错误的数字,不能作为调整模型的依据,因为它基于训练不平衡的数据集。我说得对吗?我不明白当你说我可以将任何其他损失函数添加为指标时,请你再解释一下。我需要拥有在训练和验证集中具有不同权重的损失函数。 - W. Sam
1
听起来对我来说没问题。至于指标:Keras模型编译有一个度量参数,您可以在其中传递像准确性这样的度量函数。这些指标将在训练和评估集上的每个时期结束时进行评估。因此,您可以使用不同的权重添加自定义加权损失函数。如果这不可能,请展示一些代码,说明如何将您的自定义损失函数作为模型损失函数传递。 - dennis-w
我修改了帖子,加入了简单的代码。我想我明白你的意思了。你的意思是将普通的分类交叉熵损失作为指标传递,以便报告准确的验证损失值。但是那么我想要用于模型评估的准确性指标怎么办?我可以传递两个指标进行评估吗? - W. Sam
1
是的,你可以传递一个包含任意数量指标的数组。 - dennis-w

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接