Ошибка входного размера пользовательской функции потерь (фокусная потеря) в Керасе - PullRequest
3 голосов
/ 06 ноября 2019

Я использую нейтральную сеть для многоклассовой классификации. Есть 3 несбалансированных класса, поэтому я бы хотел использовать потерю фокуса для обработки баланса. Поэтому я использую пользовательскую функцию потерь, чтобы вписаться в последовательную модель Keras. Я попробовал несколько версий кода для функции потери фокуса, которую я нашел в Интернете, но они возвращают одно и то же сообщение об ошибке, в основном говоря, что размер ввода - это ожидаемый размер ванны. 1. Может ли кто-нибудь взглянуть на проблему и сообщить, если вы можетепочини это? Я действительно ценю это !!!

model = build_keras_model(x_train, name='training1')

class FocalLoss(keras.losses.Loss):
    def __init__(self, gamma=2., alpha=4.,
             reduction = tf.keras.losses.Reduction.AUTO, name='focal_loss'):

    super(FocalLoss, self).__init__(reduction=reduction,
                                    name=name)
    self.gamma = float(gamma)
    self.alpha = float(alpha)

def call(self, y_true, y_pred):

        epsilon = 1.e-9
        y_true = tf.convert_to_tensor(y_true, tf.float32)
        y_pred = tf.convert_to_tensor(y_pred, tf.float32)
        model_out = tf.add(y_pred, epsilon)
        ce = tf.multiply(y_true, -tf.math.log(model_out))
        weight = tf.multiply(y_true, tf.pow(
            tf.subtract(1., model_out), self.gamma))
        fl = tf.multiply(self.alpha, tf.multiply(weight, ce))
        reduced_fl = tf.reduce_max(fl, axis=1)
        return tf.reduce_mean(reduced_fl)

model.compile(optimizer = tf.keras.optimizers.Adam(0.001),
          loss = FocalLoss(alpha=1),
          metrics=['accuracy'])
​
class_weight = {0: 1.,
            1: 6.,
            2: 6.}

# fit the model (train for 5 epochs) history = model.fit(x=x_train, y=y_train, batch_size=64, epochs=5, class_weight = class_weight)

ValueError: Can not squeeze dim[0], expected a dimension of 1, got 64 for 'loss/output_1_loss/weighted_loss/Squeeze' (op: 'Squeeze') with input shapes: [64].

Ответы [ 2 ]

1 голос
/ 06 ноября 2019

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

В этом случае вы используете tf.keras.losses.Loss. Все, что вам нужно сделать, это реализовать call() (и, необязательно, __init__). К сожалению, документация вообще не говорит о том, что ожидает call(). Но так как вам нужно указать reduction в __init__(), мы можем предположить, что call(), как ожидается, вернет не только одно число. В противном случае reduction будет бесполезным. Другими словами: ошибка говорит о том, что call() возвращает одно число, в то время как ожидается, что он вернет 64 числа (размер вашей партии).

Таким образом, вместо того, чтобы самим сворачивать партию в одно число (позвонив tf.reduce_mean(reduced_fl)), пусть класс помощников сделает это за вас и просто вернет reduced_f1 напрямую. В настоящее время вы используете reduction=tf.keras.losses.Reduction.AUTO, что, скорее всего, то, что вы хотите.

0 голосов
/ 06 ноября 2019

Функции потерь Keras принимают пакет предсказаний и обучающих данных и используют их для получения тензора потерь. Одним из способов реализации этого является простое определение функции с двумя тензорными входами, которая возвращает число, например,

def mse(y_true, y_pred):
    return K.mean(K.square(y_pred - y_true), axis=-1)

Затем передайте это модели при компиляции, например,

model.compile(optimizer = tf.keras.optimizers.Adam(0.001), loss = mse)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...