python tensorflow - Quelle est la différence entre softmax et softmax_cross_entropy_with_logits?




tutorial pdf (5)

Je parcourais les docs de l'API tensorflow here . Dans la documentation tensorflow, ils ont utilisé un mot-clé appelé logits . Qu'Est-ce que c'est? Dans beaucoup de méthodes dans les documents de l'API, il est écrit comme

tf.nn.softmax(logits, name=None)

Si ce qui est écrit est ces logits sont seulement des Tensors , pourquoi garder un nom différent comme des logits ?

Une autre chose est qu'il y a deux méthodes que je ne pouvais pas différencier. Ils étaient

tf.nn.softmax(logits, name=None)
tf.nn.softmax_cross_entropy_with_logits(logits, labels, name=None)

Quelles sont les différences entre eux? Les documents ne sont pas clairs pour moi. Je sais ce tf.nn.softmax fait tf.nn.softmax . Mais pas l'autre. Un exemple sera vraiment utile.


Answers

tf.nn.softmax calcule la propagation vers l'avant à travers une couche softmax. Vous l'utilisez lors de l' évaluation du modèle lorsque vous calculez les probabilités que le modèle génère.

tf.nn.softmax_cross_entropy_with_logits calcule le coût d'une couche softmax. Il est seulement utilisé pendant l' entraînement .

Les logits sont les probabilités logarithmiques non normalisées qui sortent du modèle (les valeurs produites avant que la normalisation softmax ne leur soit appliquée).


Les réponses ci-dessus ont assez de description pour la question posée.

Ajoutant à cela, Tensorflow a optimisé l'opération d'application de la fonction d'activation puis le calcul du coût en utilisant sa propre activation suivie par des fonctions de coût. Par conséquent, il est tf.nn.softmax_cross_entropy() d'utiliser: tf.nn.softmax_cross_entropy() sur tf.nn.softmax(); tf.nn.cross_entropy() tf.nn.softmax(); tf.nn.cross_entropy()

Vous pouvez trouver une différence importante entre eux dans un modèle intensif en ressources.


Version courte:

Supposons que vous ayez deux tenseurs, où y_hat contient des scores calculés pour chaque classe (par exemple, à partir de y = W * x + b) et y_true contient des véritables labels codés à chaud.

y_hat  = ... # Predicted label, e.g. y = tf.matmul(X, W) + b
y_true = ... # True label, one-hot encoded

Si vous interprétez les scores dans y_hat comme des probabilités logarithmiques non normalisées, alors ils sont des logits .

De plus, la perte totale d'entropie croisée calculée de cette manière:

y_hat_softmax = tf.nn.softmax(y_hat)
total_loss = tf.reduce_mean(-tf.reduce_sum(y_true * tf.log(y_hat_softmax), [1]))

est essentiellement équivalent à la perte totale d'entropie calculée avec la fonction softmax_cross_entropy_with_logits() :

total_loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(y_hat, y_true))

Version longue:

Dans la couche de sortie de votre réseau de neurones, vous allez probablement calculer un tableau contenant les scores de classe pour chacune de vos instances d'apprentissage, par exemple à partir d'un calcul y_hat = W*x + b . Pour servir d'exemple, ci-dessous j'ai créé un y_hat sous la forme d'un tableau 2 x 3, où les lignes correspondent aux instances d'apprentissage et les colonnes correspondent aux classes. Donc, ici, il y a 2 instances d'entraînement et 3 classes.

import tensorflow as tf
import numpy as np

sess = tf.Session()

# Create example y_hat.
y_hat = tf.convert_to_tensor(np.array([[0.5, 1.5, 0.1],[2.2, 1.3, 1.7]]))
sess.run(y_hat)
# array([[ 0.5,  1.5,  0.1],
#        [ 2.2,  1.3,  1.7]])

Notez que les valeurs ne sont pas normalisées (les lignes ne totalisent pas 1). Afin de les normaliser, nous pouvons appliquer la fonction softmax, qui interprète l'entrée comme des probabilités logarithmiques non normalisées (alias logits ) et produit des probabilités linéaires normalisées.

y_hat_softmax = tf.nn.softmax(y_hat)
sess.run(y_hat_softmax)
# array([[ 0.227863  ,  0.61939586,  0.15274114],
#        [ 0.49674623,  0.20196195,  0.30129182]])

Il est important de bien comprendre ce que dit la sortie softmax. Ci-dessous, j'ai montré une table qui représente plus clairement la sortie ci-dessus. On peut voir que, par exemple, la probabilité que l'instance d'entraînement 1 soit «Classe 2» est de 0,619. Les probabilités de classe pour chaque instance d'entraînement sont normalisées, de sorte que la somme de chaque ligne est 1.0.

                      Pr(Class 1)  Pr(Class 2)  Pr(Class 3)
                    ,--------------------------------------
Training instance 1 | 0.227863   | 0.61939586 | 0.15274114
Training instance 2 | 0.49674623 | 0.20196195 | 0.30129182

Alors maintenant nous avons des probabilités de classe pour chaque instance d'entraînement, où nous pouvons prendre l'argmax () de chaque rangée pour générer une classification finale. D'en haut, nous pouvons générer que l'instance de formation 1 appartient à "Classe 2" et l'instance de formation 2 appartient à "Classe 1".

Ces classifications sont-elles correctes? Nous devons mesurer par rapport aux véritables étiquettes de l'ensemble de formation. Vous aurez besoin d'un tableau y_true codé à chaud, où les lignes sont à nouveau des instances d'entraînement et les colonnes sont des classes. Ci-dessous j'ai créé un exemple de y_true une seule y_true où le vrai label pour l'instance d'entraînement 1 est "Classe 2" et le vrai label pour l'instance d'apprentissage 2 est "Classe 3".

y_true = tf.convert_to_tensor(np.array([[0.0, 1.0, 0.0],[0.0, 0.0, 1.0]]))
sess.run(y_true)
# array([[ 0.,  1.,  0.],
#        [ 0.,  0.,  1.]])

La distribution de probabilité dans y_hat_softmax proche de la distribution de probabilité dans y_true ? Nous pouvons utiliser la perte d'entropie croisée pour mesurer l'erreur.

Nous pouvons calculer la perte d'entropie croisée selon le rang et voir les résultats. Ci-dessous, nous pouvons voir que l'instance d'entraînement 1 a une perte de 0,479, alors que l'instance d'entraînement 2 a une perte plus élevée de 1,200. Ce résultat est logique car dans notre exemple ci-dessus, y_hat_softmax montré que la probabilité la plus élevée de l'instance d'apprentissage 1 était pour "Classe 2", qui correspond à l'instance d'apprentissage 1 dans y_true ; cependant, la prédiction pour l'instance d'apprentissage 2 a montré une probabilité plus élevée pour la «Classe 1», qui ne correspond pas à la vraie classe «Classe 3».

loss_per_instance_1 = -tf.reduce_sum(y_true * tf.log(y_hat_softmax), reduction_indices=[1])
sess.run(loss_per_instance_1)
# array([ 0.4790107 ,  1.19967598])

Ce que nous voulons vraiment, c'est la perte totale sur toutes les instances d'entraînement. Nous pouvons donc calculer:

total_loss_1 = tf.reduce_mean(-tf.reduce_sum(y_true * tf.log(y_hat_softmax), reduction_indices=[1]))
sess.run(total_loss_1)
# 0.83934333897877944

Utilisation de softmax_cross_entropy_with_logits ()

Nous pouvons calculer la perte totale d'entropie croisée en utilisant la fonction tf.nn.softmax_cross_entropy_with_logits() , comme indiqué ci-dessous.

loss_per_instance_2 = tf.nn.softmax_cross_entropy_with_logits(y_hat, y_true)
sess.run(loss_per_instance_2)
# array([ 0.4790107 ,  1.19967598])

total_loss_2 = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(y_hat, y_true))
sess.run(total_loss_2)
# 0.83934333897877922

Notez que total_loss_1 et total_loss_2 produisent des résultats essentiellement équivalents avec quelques petites différences dans les chiffres finaux. Cependant, vous pouvez aussi bien utiliser la deuxième approche: elle prend une ligne de code de moins et accumule moins d'erreur numérique parce que la softmax est faite pour vous à l'intérieur de softmax_cross_entropy_with_logits() .


Logits signifie simplement que la fonction fonctionne sur la sortie non calibrée des couches précédentes et que l'échelle relative pour comprendre les unités est linéaire. Cela signifie, en particulier, que la somme des entrées peut ne pas être égale à 1, que les valeurs ne sont pas des probabilités (vous pourriez avoir une entrée de 5).

tf.nn.softmax produit juste le résultat de l'application de la fonction softmax à un tenseur d'entrée. Le softmax "écrase" les entrées de sorte que sum (input) = 1; c'est une façon de normaliser. La forme de la sortie d'une softmax est la même que l'entrée - elle normalise simplement les valeurs. Les sorties de softmax peuvent être interprétées comme des probabilités.

a = tf.constant(np.array([[.1, .3, .5, .9]]))
print s.run(tf.nn.softmax(a))
[[ 0.16838508  0.205666    0.25120102  0.37474789]]

En revanche, tf.nn.softmax_cross_entropy_with_logits calcule l'entropie croisée du résultat après l'application de la fonction softmax (mais elle le fait tous de manière plus mathématique). C'est semblable au résultat de:

sm = tf.nn.softmax(x)
ce = cross_entropy(sm)

L'entropie croisée est une métrique sommaire - elle résume les éléments. La sortie de tf.nn.softmax_cross_entropy_with_logits sur un tenseur de forme [2,5] est de forme [2,1] (la première dimension est traitée comme le lot).

Si vous voulez faire l'optimisation pour minimiser l'entropie croisée, ET que vous êtes en train de faire un softmaxing après votre dernière couche, vous devriez utiliser tf.nn.softmax_cross_entropy_with_logits au lieu de le faire vous-même, car il couvre mathématiquement les cas de coin numériquement instables. Sinon, vous finirez par le pirater en ajoutant de petites epsilons ici et là.

(Édité 2016-02-07: Si vous avez des étiquettes de classe unique, où un objet ne peut appartenir qu'à une seule classe, vous pouvez maintenant utiliser tf.nn.sparse_softmax_cross_entropy_with_logits afin de ne pas avoir à convertir vos étiquettes en denses. un-hot array Cette fonction a été ajoutée après la version 0.6.0.)


méthode de classe vs méthode statique en Python

Méthode de classe

Le décorateur @classmethod est un décorateur de fonction intégré qui est une expression qui est évaluée après la définition de votre fonction. Le résultat de cette évaluation assombrit la définition de votre fonction.

Une méthode de classe reçoit la classe comme premier argument implicite, tout comme une méthode d'instance reçoit l'instance

Syntaxe:

class C(object):
    @staticmethod
    def fun(arg1, arg2, ...):
        ...
returns: a static method for function fun.
  • Une méthode de classe est une méthode liée à la classe et non à l'objet de la classe.
  • Ils ont accès à l'état de la classe car il faut un paramètre de classe qui pointe vers la classe et non l'instance de l'objet.
  • Il peut modifier un état de classe qui s'appliquerait à toutes les instances de la classe. Par exemple, il peut modifier une variable de classe qui sera applicable à toutes les instances.

Méthode statique

Une méthode statique ne reçoit pas de premier argument implicite.

Syntaxe:

# Python program to demonstrate 
# use of class method and static method.
from datetime import date

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    # a class method to create a Person object by birth year.
    @classmethod
    def fromBirthYear(cls, name, year):
        return cls(name, date.today().year - year)

    # a static method to check if a Person is adult or not.
    @staticmethod
    def isAdult(age):
        return age > 18

person1 = Person('mayank', 21)
person2 = Person.fromBirthYear('mayank', 1996)

print person1.age
print person2.age

# print the result
print Person.isAdult(22)
  • Une méthode statique est également une méthode liée à la classe et non à l'objet de la classe.
  • Une méthode statique ne peut pas accéder ni modifier l'état de la classe.
  • Il est présent dans une classe car il est logique que la méthode soit présente en classe.

Méthode de classe vs méthode statique

  • Une méthode de classe prend cls en tant que premier paramètre, tandis qu'une méthode statique ne nécessite aucun paramètre spécifique.
  • Une méthode de classe peut accéder à ou modifier l'état de la classe alors qu'une méthode statique ne peut pas y accéder ou la modifier.
  • Nous utilisons @classmethod decorator en python pour créer une méthode de classe et nous utilisons @staticmethod decorator pour créer une méthode statique en python.

Quand utiliser quoi?

  • Nous utilisons généralement la méthode de classe pour créer des méthodes d'usine. Les méthodes d'usine renvoient un objet de classe (similaire à un constructeur) pour différents cas d'utilisation.
  • Nous utilisons généralement des méthodes statiques pour créer des fonctions utilitaires.

Comment définir une méthode de classe et une méthode statique?

Pour définir une méthode de classe en python, nous utilisons @classmethod decorator et pour définir une méthode statique, nous utilisons @staticmethod decorator.

Regardons un exemple pour comprendre la différence entre les deux. Disons que nous voulons créer une personne de classe. Maintenant, python ne supporte pas la surcharge de méthodes comme C ++ ou Java, nous utilisons donc des méthodes de classe pour créer des méthodes de fabrique. Dans l'exemple ci-dessous, nous utilisons une méthode de classe pour créer un objet Personne à partir de l'année de naissance.

Comme expliqué ci-dessus, nous utilisons des méthodes statiques pour créer des fonctions utilitaires. Dans l'exemple ci-dessous, nous utilisons une méthode statique pour vérifier si une personne est adulte ou non.

la mise en oeuvre

21
21
True

Sortie

>>> class Klaus:
        @classmethod
        def classmthd(*args):
            return args

        @staticmethod
        def staticmthd(*args):
            return args

# 1. Call classmethod without any arg
>>> Klaus.classmthd()  
(__main__.Klaus,)  # the class gets passed as the first argument

# 2. Call classmethod with 1 arg
>>> Klaus.classmthd('chumma')
(__main__.Klaus, 'chumma')

# 3. Call staticmethod without any arg
>>> Klaus.staticmthd()  
()

# 4. Call staticmethod with 1 arg
>>> Klaus.staticmthd('chumma')
('chumma',)

Reference







python machine-learning tensorflow