J'ai écrit un autoencodeur Vanilla utilisant uniquement la couche Dense
. Voici mon code:
iLayer = Input ((784,))
layer1 = Dense(128, activation='relu' ) (iLayer)
layer2 = Dense(64, activation='relu') (layer1)
layer3 = Dense(28, activation ='relu') (layer2)
layer4 = Dense(64, activation='relu') (layer3)
layer5 = Dense(128, activation='relu' ) (layer4)
layer6 = Dense(784, activation='softmax' ) (layer5)
model = Model (iLayer, layer6)
model.compile(loss='binary_crossentropy', optimizer='adam')
(trainX, trainY), (testX, testY) = mnist.load_data()
print ("shape of the trainX", trainX.shape)
trainX = trainX.reshape(trainX.shape[0], trainX.shape[1]* trainX.shape[2])
print ("shape of the trainX", trainX.shape)
model.fit (trainX, trainX, epochs=5, batch_size=100)
1) softmax
fournit une distribution de probabilité. Compris. Cela signifie que j'aurais un vecteur de 784 valeurs avec une probabilité entre 0 et 1. Par exemple [0,02, 0,03 ..... jusqu'à 784 éléments], la somme des 784 éléments fournit 1.
2) Je ne comprends pas comment la crossentropie binaire fonctionne avec ces valeurs. L'entropie croisée binaire est pour deux valeurs de sortie, non?
Dans le contexte des encodeurs automatiques, l'entrée et la sortie du modèle sont identiques. Donc, si les valeurs d'entrée sont dans la plage [0,1], il est acceptable d'utiliser sigmoid
comme fonction d'activation de la dernière couche. Sinon, vous devez utiliser une fonction d'activation appropriée pour la dernière couche (par exemple linear
qui est la fonction par défaut).
Quant à la fonction de perte, elle revient à nouveau aux valeurs des données d'entrée. Si les données d'entrée sont seulement entre les zéros et les uns (et non les valeurs entre eux), puis binary_crossentropy
est acceptable comme fonction de perte. Sinon, vous devez utiliser d'autres fonctions de perte telles que 'mse'
(c.-à-d. erreur quadratique moyenne) ou 'mae'
(c'est-à-dire erreur absolue moyenne). Notez que dans le cas de valeurs d'entrée dans la plage [0,1]
vous pouvez utiliser binary_crossentropy
, comme il est généralement utilisé (par exemple tutoriel Keras autoencoder et cet article ). Cependant, ne vous attendez pas à ce que la valeur de perte devienne nulle puisque binary_crossentropy
ne renvoie pas zéro lorsque la prédiction et l'étiquette ne sont pas égales à zéro ou à un (qu'elles soient égales ou non). Ici est une vidéo de Hugo Larochelle où il explique les fonctions de perte utilisées dans les encodeurs automatiques (la partie sur l'utilisation de binary_crossentropy
avec des entrées dans la plage [0,1] commence à 5: )
Concrètement, dans votre exemple, vous utilisez l'ensemble de données MNIST. Ainsi, par défaut, les valeurs de MNIST sont des entiers dans la plage [0, 255]. Habituellement, vous devez d'abord les normaliser:
trainX = trainX.astype('float32')
trainX /= 255.
Maintenant, les valeurs seraient dans la plage [0,1]. Donc sigmoid
peut être utilisé comme fonction d'activation et soit binary_crossentropy
ou mse
comme fonction de perte.
Pourquoi binary_crossentropy
peut être utilisé même lorsque les vraies valeurs d'étiquette (c'est-à-dire la vérité du sol) sont dans la plage [0,1]?
Notez que nous essayons de minimiser la fonction de perte lors de la formation. Donc, si la fonction de perte que nous avons utilisée atteint sa valeur minimale (qui peut ne pas être nécessairement égale à zéro) lorsque la prédiction est égale à true label, alors c'est un choix acceptable. Vérifions que c'est le cas pour l'entropie croisée binray qui est définie comme suit:
bce_loss = -y*log(p) - (1-y)*log(1-p)
où y
est la véritable étiquette et p
est la valeur prédite. Considérons y
comme fixe et voyons quelle valeur de p
minimise cette fonction: nous devons prendre la dérivée par rapport à p
(j'ai supposé que le log
est la fonction de logarithme naturel pour la simplicité des calculs):
bce_loss_derivative = -y*(1/p) - (1-y)*(-1/(1-p)) = 0 =>
-y/p + (1-y)/(1-p) = 0 =>
-y*(1-p) + (1-y)*p = 0 =>
-y + y*p + p - y*p = 0 =>
p - y = 0 => y = p
Comme vous pouvez le voir, l'entropie croisée binaire a la valeur minimale lorsque y=p
, c'est-à-dire lorsque la véritable étiquette est égale à l'étiquette prédite et c'est exactement ce que nous recherchons.