web-dev-qa-db-fra.com

Implémentation de perte personnalisée Keras: ValueError: Une opération a `None` pour gradient

J'essaie d'implémenter cette fonction de perte: MCFD_loss_function de ce document (P6): Fonctions de perte

J'ai donc créé une nouvelle fonction comme celle-ci:

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')
    )

Mais lorsque je commence à m'entraîner, cette erreur se produit:

ValueError: Une opération a None pour gradient. Veuillez vous assurer que toutes vos opérations ont un gradient défini (c'est-à-dire qu'elles sont différenciables). Opérations courantes sans gradient: K.argmax, K.round, K.eval.

Je ne sais pas quel point j'ai manqué. L'erreur semble être déclenchée car j'utilise une plus grande fonction. Je ne sais pas ce que signifie cette erreur et comment corriger mon problème.

Merci.

12
bastien enjalbert

Vous voulez que votre fonction de perte vérifie si sign(f_(t,1))*sign(Y_(t+1)) est supérieur à 0. Puisque sign n'est pas différentiable à 0, je suggère d'utiliser softsign à la place.

Puisque la fonction greate than n'est pas non plus différenciable, on peut utiliser l'approximation suivante (voir ici ): maxϵ(x,y):= 0.5(x + y + absϵ(x − y)), où absϵ(x):=sqrt(x^2 + ϵ) et ϵ > 0. Pour simplifier, j'appellerai cette approximation dans l'exemple de code ci-dessous comme greater_approx. (Notez que vous n'avez qu'à insérer les calculs ci-dessus)

En regardant la définition de la fonction de perte, vous devez diviser la somme par le nombre de prédictions (K.get_variable_shape(y_pred)[0]) (et également ajouter un moins). P correspond au nombre de prédictions selon Fonctions de perte dans le papier de prévision de séries chronologiques .

Dans l'ensemble, votre fonction de perte devrait ressembler à ceci:

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')
   )

Dernière remarque: pour utiliser une fonction de perte personnalisée dans Keras checkout this SO question

1
Simdi