Внедрение пользовательских потерь Keras: ValueError: операция имеет "None" для градиента

Я пытаюсь реализовать эту функцию потерь: MCFD_loss_function из этого документа (P6): Потеря функций

Поэтому я создал новую функцию, подобную этой:

def mcfd_loss(y_true, y_pred):
    return K.sum( # ∑
        K.cast(
            K.greater( # only values greater than 0 (+ float32 cast)
                  K.dot(K.sign(y_pred),  # π
                        K.sign(y_true))
           , 0)
        , 'float32')
    )

Но когда я начинаю тренировку, возникает ошибка:

ValueError: Операция имеет None для градиента. Пожалуйста, убедитесь, что все ваши операции имеют определенный градиент (то есть, дифференцируемы). Обычные операции без градиента: K.argmax, K.round, K.eval.

Я не знаю, какой момент я упустил. Ошибка, кажется, возникает, потому что я использую большую функцию. Я не знаю, что означает эта ошибка и как исправить мою проблему.

Благодарю.

Ответ 1

Вы хотите, чтобы ваша функция потерь проверяла, больше ли sign(f_(t,1))*sign(Y_(t+1)), чем 0. Поскольку sign не дифференцируется при 0, я бы предложил вместо этого использовать softsign.

Поскольку функция greate than также не дифференцируема, можно использовать следующее приближение (см. здесь): maxϵ(x,y):= 0.5(x + y + absϵ(x − y)), где absϵ(x):=sqrt(x^2 + ϵ) и ϵ > 0. Для простоты я буду называть это приближение в примере кода ниже greater_approx. (Обратите внимание, что вам просто нужно вставить приведенные выше расчеты)

Глядя на определение функции потерь, вы должны разделить сумму на количество прогнозов (K.get_variable_shape(y_pred)[0]) (а также добавить минус). P соответствует числу прогнозов согласно функциям потерь в документе по прогнозированию временных рядов.

В целом ваша функция потерь должна выглядеть следующим образом:

def mcfd_loss(y_true, y_pred):
   return - (1/K.get_variable_shape(y_pred)[0]) * K.sum( # ∑
      K.cast(
         greater_approx( # only values greater than 0 (+ float32 cast)
            K.dot(K.softsign(y_pred),  # π
                    K.softsign(y_true))
         , 0)
      , 'float32')
   )

Последнее замечание: за использование пользовательской функции потерь в Keras проверьте этот ТАК вопрос