Récemment, j'ai commencé à jouer avec les réseaux de neurones. J'essayais d'implémenter une porte AND
avec Tensorflow. J'ai du mal à comprendre quand utiliser différentes fonctions de coût et d'activation. Il s'agit d'un réseau neuronal de base avec uniquement des couches d'entrée et de sortie, pas de couches cachées.
J'ai d'abord essayé de l'implémenter de cette manière. Comme vous pouvez le voir, c'est une mauvaise mise en œuvre, mais je pense que cela fait le travail, au moins d'une certaine manière. Donc, je n'ai essayé que les vraies sorties, pas de vraies sorties à chaud. Pour les fonctions d'activation, j'ai utilisé une fonction sigmoïde et pour la fonction de coût, j'ai utilisé la fonction de coût d'erreur au carré (je pense que cela s'appelle ainsi, corrigez-moi si je me trompe).
J'ai essayé d'utiliser ReLU et Softmax comme fonctions d'activation (avec la même fonction de coût) et cela ne fonctionne pas. J'ai compris pourquoi ils ne fonctionnaient pas. J'ai également essayé la fonction sigmoïde avec la fonction de coût de l'entropie croisée, cela ne fonctionne pas non plus.
import tensorflow as tf
import numpy
train_X = numpy.asarray([[0,0],[0,1],[1,0],[1,1]])
train_Y = numpy.asarray([[0],[0],[0],[1]])
x = tf.placeholder("float",[None, 2])
y = tf.placeholder("float",[None, 1])
W = tf.Variable(tf.zeros([2, 1]))
b = tf.Variable(tf.zeros([1, 1]))
activation = tf.nn.sigmoid(tf.matmul(x, W)+b)
cost = tf.reduce_sum(tf.square(activation - y))/4
optimizer = tf.train.GradientDescentOptimizer(.1).minimize(cost)
init = tf.initialize_all_variables()
with tf.Session() as sess:
sess.run(init)
for i in range(5000):
train_data = sess.run(optimizer, feed_dict={x: train_X, y: train_Y})
result = sess.run(activation, feed_dict={x:train_X})
print(result)
après 5000 itérations:
[[ 0.0031316 ]
[ 0.12012422]
[ 0.12012422]
[ 0.85576665]]
Question 1 - Y a-t-il une autre fonction d'activation et fonction de coût, qui peut fonctionner (apprendre) pour le réseau ci-dessus, sans changer les paramètres (c'est-à-dire sans changer W, x, b).
Question 2 - J'ai lu dans un post StackOverflow ici :
La sélection de [Fonction d'activation] dépend du problème.
Il n'y a donc aucune fonction de coût qui peut être utilisée n'importe où? Je veux dire qu'il n'y a pas de fonction de coût standard qui peut être utilisée sur n'importe quel réseau de neurones. Droite? Veuillez me corriger là-dessus.
J'ai également implémenté la porte AND
avec une approche différente, avec la sortie comme true one-hot. Comme vous pouvez voir le train_Y
[1,0]
signifie que le 0e index est 1, donc la réponse est 0. J'espère que vous l'obtiendrez.
Ici, j'ai utilisé une fonction d'activation softmax, avec entropie croisée comme fonction de coût. La fonction sigmoïde comme fonction d'activation échoue lamentablement.
import tensorflow as tf
import numpy
train_X = numpy.asarray([[0,0],[0,1],[1,0],[1,1]])
train_Y = numpy.asarray([[1,0],[1,0],[1,0],[0,1]])
x = tf.placeholder("float",[None, 2])
y = tf.placeholder("float",[None, 2])
W = tf.Variable(tf.zeros([2, 2]))
b = tf.Variable(tf.zeros([2]))
activation = tf.nn.softmax(tf.matmul(x, W)+b)
cost = -tf.reduce_sum(y*tf.log(activation))
optimizer = tf.train.GradientDescentOptimizer(0.5).minimize(cost)
init = tf.initialize_all_variables()
with tf.Session() as sess:
sess.run(init)
for i in range(5000):
train_data = sess.run(optimizer, feed_dict={x: train_X, y: train_Y})
result = sess.run(activation, feed_dict={x:train_X})
print(result)
après 5000 itérations
[[ 1.00000000e+00 1.41971401e-09]
[ 9.98996437e-01 1.00352429e-03]
[ 9.98996437e-01 1.00352429e-03]
[ 1.40495342e-03 9.98595059e-01]]
Question 3 Dans ce cas, quelle fonction de coût et fonction d'activation puis-je utiliser? Comment puis-je comprendre quel type de fonctions de coût et d'activation dois-je utiliser? Existe-t-il une méthode ou une règle standard, ou simplement une expérience uniquement? Dois-je avoir à essayer toutes les fonctions de coût et d'activation de manière brutale? J'ai trouvé une réponse ici . Mais j'espère une explication plus élaborée.
Question 4 J'ai remarqué qu'il faut de nombreuses itérations pour converger vers une prédiction presque précise. Je pense que le taux de convergence dépend du taux d'apprentissage (en utilisant trop de, la solution manquera) et de la fonction de coût (corrigez-moi si je me trompe). Alors, existe-t-il un moyen optimal (c'est-à-dire le plus rapide) ou une fonction de coût pour converger vers une solution correcte?
Je vais répondre à vos questions un peu dans l’ordre, en commençant par des réponses plus générales et en terminant par celles spécifiques à votre expérience particulière.
Fonctions d'activation Différentes fonctions d'activation ont en fait des propriétés différentes. Considérons d'abord une fonction d'activation entre deux couches d'un réseau neuronal. Le seul but d'une fonction d'activation est de servir de non-linéarité. Si vous ne mettez pas de fonction d'activation entre deux couches, alors deux couches ensemble ne serviront pas mieux qu'une, car leur effet sera toujours juste une transformation linéaire. Pendant longtemps, les gens utilisaient la fonction sigmoïde et le tanh, choisissant à peu près arbitrairement, avec sigmoïde étant plus populaire, jusqu'à récemment, lorsque ReLU est devenu la non-particularité dominante. La raison pour laquelle les gens utilisent ReLU entre les couches est qu'il n'est pas saturant (et est également plus rapide à calculer). Pensez au graphique d'une fonction sigmoïde. Si la valeur absolue de x
est grande, alors la dérivée de la fonction sigmoïde est petite, ce qui signifie que lorsque nous propagerons l'erreur vers l'arrière, le gradient de l'erreur disparaîtra très rapidement au fur et à mesure que nous remontons les couches . Avec ReLU, la dérivée est 1
pour toutes les entrées positives, donc le gradient pour les neurones qui ont tiré ne sera pas modifié du tout par l'unité d'activation et ne ralentira pas la descente du gradient.
Pour la dernière couche du réseau, l'unité d'activation dépend également de la tâche. Pour la régression, vous voudrez utiliser l'activation sigmoïde ou tanh, car vous voulez que le résultat soit compris entre 0 et 1. Pour la classification, vous voudrez qu'une seule de vos sorties soit un et tous les autres zéros, mais il n'y a pas de moyen différentiable pour atteindre précisément cela, vous voudrez donc utiliser un softmax pour l'approcher.
Votre exemple. Voyons maintenant votre exemple. Votre premier exemple essaie de calculer la sortie de AND
sous la forme suivante:
sigmoid(W1 * x1 + W2 * x2 + B)
Notez que W1
et W2
convergera toujours vers la même valeur, car la sortie de (x1
, x2
) doit être égal à la sortie de (x2
, x1
). Par conséquent, le modèle que vous ajustez est:
sigmoid(W * (x1 + x2) + B)
x1 + x2
ne peut prendre qu'une des trois valeurs (0, 1 ou 2) et vous souhaitez renvoyer 0
pour le cas où x1 + x2 < 2
et 1 pour le cas où x1 + x2 = 2
. Étant donné que la fonction sigmoïde est plutôt fluide, il faudra de très grandes valeurs de W
et B
pour rendre la sortie proche de celle souhaitée, mais en raison d'un faible taux d'apprentissage, ils ne peuvent pas y accéder. ces grandes valeurs rapidement. L'augmentation du taux d'apprentissage dans votre premier exemple augmentera la vitesse de convergence.
Votre deuxième exemple converge mieux car la fonction softmax
est bonne pour rendre précisément une sortie égale à 1
et tous les autres à 0
. Puisque c'est précisément votre cas, il converge rapidement. Notez que sigmoid
finira également par converger vers de bonnes valeurs, mais cela prendra beaucoup plus d'itérations (ou un taux d'apprentissage plus élevé).
Quoi utiliser. Maintenant à la dernière question, comment choisir les fonctions d'activation et de coût à utiliser. Ces conseils fonctionneront dans la majorité des cas:
Si vous effectuez une classification, utilisez softmax
pour la non-linéarité de la dernière couche et cross entropy
comme fonction de coût.
Si vous effectuez une régression, utilisez sigmoid
ou tanh
pour la non-linéarité de la dernière couche et squared error
comme fonction de coût.
Utilisez ReLU comme une non-linéarité entre les couches.
Utilisez de meilleurs optimiseurs (AdamOptimizer
, AdagradOptimizer
) au lieu de GradientDescentOptimizer
, ou utilisez l'élan pour une convergence plus rapide,