是否有可能在keras中实现动态类权重?

Oph*_*tan 7 python machine-learning neural-network deep-learning keras

keras支持该class_weights功能,允许为不同的类提供不同的权重 - 例如,当样本数量不平衡时

我想做类似的事情,但要使用动态权重,基于每个批次中的类不平衡.

这可能吗?

Dan*_*ler 5

选项1:

为纪元和批次进行手动循环,使用方法train_on_batch,该方法也接受class_weight

for epoch in range(epochs):
    for batchX,batchY in batches: #adapt this loop to your way of creating/getting batches

        weights = calculateOrGetTheWeights(batch)
        model.train_on_batch(batchX,batchY,...,class_weight=weights)
Run Code Online (Sandbox Code Playgroud)

选项 2:

创建自定义损失。可能更棘手,取决于数据格式、类的数量、损失函数的类型等。

假设二维数据(样本、类)和多类问题:

import keras.backend as K

def customLoss(yTrue,yPred):

    classes = K.argmax(yTrue)
    classCount = K.sum(yTrue,axis=0)

    loss = K.some_loss_function(yTrue,yPred)

    return loss / K.gather(classCount, classes)
Run Code Online (Sandbox Code Playgroud)

假设使用一维或二维数据进行二元分类(仅 1 个类):

import keras.backend as K

def binaryCustomLoss(yTrue,yPred):

    positives = yTrue
    negatives = 1 - yTrue

    positiveRatio = K.mean(positives)
    negativeRatio = 1 - positiveRatio #or K.mean(negatives)

    weights = (positives / positiveRatio) + (negatives / negativeRatio)

    #you may need K.squeeze(weights) here

    return weights * K.some_loss_function(yTrue,yPred)
Run Code Online (Sandbox Code Playgroud)

警告:如果任何类计数为零,两个损失函数都将返回 Nan(或无穷大)。


Fre*_*red 5

一种选择是,而不是使用class_weight,使用样本权重

如果您希望样本权重是动态的,则需要使用fit_generator而不是fit,以便您可以在运行时更改权重

所以在伪代码中:

def gen(x, y):
    while True:
        for x_batch, y_batch in make_batches(x, y):
            weights = make_weights(y_batch)
            yield x_batch, y_batch, weights
model.fit_generator(gen(x_train, y_train))
Run Code Online (Sandbox Code Playgroud)

在这段代码中,make_weights应该返回一个与y_batch. 每个元素都是要应用于相应样本的权重

如果您不确定class_weight和样本权重的行为是否相同,请注意keras 如何标准化类权重。

所以类权重实际上最终被转换为样本权重:)