Можно ли реализовать динамические веса классов в керас? - PullRequest
0 голосов
/ 26 апреля 2018

keras поддерживает функцию class_weights, позволяющую придавать разным классам разные веса - например, когда количество выборок несбалансировано

Я хочу сделать нечто подобное, но использовать динамические веса, основанные на дисбалансе классов в каждой партии.

это возможно?

Ответы [ 2 ]

0 голосов
/ 26 апреля 2018

Один из вариантов - вместо 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))

В этом коде make_weights должен возвращать массив той же длины, что и y_batch. Каждый элемент представляет собой вес, который будет применен к соответствующему образцу

Если вы не уверены, что поведение class_weight и веса выборок одинаковы, обратите внимание , как keras стандартизирует веса классов.

Таким образом, веса классов фактически переводятся в примерные веса в конце:)

0 голосов
/ 26 апреля 2018

Вариант 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)

Вариант 2:

Создание собственной потери. Может быть более сложным и зависит от формата данных, количества классов, типа функции потерь и т. Д.

Предположим, 2D-данные (образцы, классы) и проблема мультикласса:

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)

Предполагая двоичную классификацию (только 1 класс) с 1D или 2D данными:

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)

Предупреждение: обе функции потерь будут возвращать Nan (или бесконечность), если число классов равно нулю.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...