5

J'ai construit un MLP avec la bibliothèque TensorFlow de Google. Le réseau fonctionne mais refuse d'apprendre correctement. Il converge toujours vers une sortie de près de 1,0, peu importe ce que l'entrée est réellement.TensorFlow MLP pas de formation XOR

Le code complet peut être vu here.

Des idées?


L'entrée et sortie (taille du lot 4) est la suivante:

input_data = [[0., 0.], [0., 1.], [1., 0.], [1., 1.]] # XOR input 
output_data = [[0.], [1.], [1.], [0.]] # XOR output 

n_input = tf.placeholder(tf.float32, shape=[None, 2], name="n_input") 
n_output = tf.placeholder(tf.float32, shape=[None, 1], name="n_output") 

configuration de couche cachée:

# hidden layer's bias neuron 
b_hidden = tf.Variable(0.1, name="hidden_bias") 

# hidden layer's weight matrix initialized with a uniform distribution 
W_hidden = tf.Variable(tf.random_uniform([2, hidden_nodes], -1.0, 1.0), name="hidden_weights") 

# calc hidden layer's activation 
hidden = tf.sigmoid(tf.matmul(n_input, W_hidden) + b_hidden) 

configuration de la couche de sortie:

W_output = tf.Variable(tf.random_uniform([hidden_nodes, 1], -1.0, 1.0), name="output_weights") # output layer's weight matrix 
output = tf.sigmoid(tf.matmul(hidden, W_output)) # calc output layer's activation 

Mon apprentissage méthodes ressemblent à ceci:

loss = tf.reduce_mean(cross_entropy) # mean the cross_entropy 
optimizer = tf.train.GradientDescentOptimizer(0.01) # take a gradient descent for optimizing 
train = optimizer.minimize(loss) # let the optimizer train 

J'ai essayé deux configurations pour entropie croisée:

cross_entropy = -tf.reduce_sum(n_output * tf.log(output)) 

et

cross_entropy = tf.nn.sigmoid_cross_entropy_with_logits(n_output, output) 

n_output est la sortie d'origine tel que décrit dans output_data et output la valeur prédite/calculée par mon réseau.


La formation dans la boucle for (pour les époques n) va comme ceci:

cvalues = sess.run([train, loss, W_hidden, b_hidden, W_output], 
        feed_dict={n_input: input_data, n_output: output_data}) 

Je sauve le résultat à CVALUES pour printig de débogage de loss, W_hidden, ...


Peu importe ce que j'ai essayé, quand je teste mon réseau, en essayant de valider la sortie, il produit toujours quelque chose lik e ceci:

(...) 
step: 2000 
loss: 0.0137040186673 
b_hidden: 1.3272010088 
W_hidden: [[ 0.23195425 0.53248233 -0.21644847 -0.54775208 0.52298909] 
[ 0.73933059 0.51440752 -0.08397482 -0.62724304 -0.53347367]] 
W_output: [[ 1.65939867] 
[ 0.78912479] 
[ 1.4831928 ] 
[ 1.28612828] 
[ 1.12486529]] 

(--- finished with 2000 epochs ---) 

(Test input for validation:) 

input: [0.0, 0.0] | output: [[ 0.99339396]] 
input: [0.0, 1.0] | output: [[ 0.99289012]] 
input: [1.0, 0.0] | output: [[ 0.99346077]] 
input: [1.0, 1.0] | output: [[ 0.99261558]] 

Il n'est pas apprendre correctement, mais toujours converger à près de 1,0, peu importe quelle entrée est alimentée.

+1

Votre variable 'b_hidden' est un scalaire - est-ce intentionnel? Je pense que vous devriez le créer comme 'b_hidden = tf.Variable (tf.constant (0.1, forme = [hidden_nodes]), name =" hidden_bias ")', ce qui pourrait aider. Une autre chose à essayer serait d'ajouter un terme de biais 'b_output' à votre couche de sortie. – mrry

+0

Merci pour le commentaire. En effet, je n'ai juste pas remarqué que 'b_hidden' devrait aussi être un vecteur et non un scalaire ... cependant, le réseau converge toujours vers presque 1.0 pour chaque entrée, avec ou sans biais caché, comme un scalaire ou un vecteur et avec ou sans biais pour la couche de sortie. Je pense vraiment que je manque une erreur dans la méthode d'apprentissage ou l'architecture réseau:/ – daniel451

Répondre

8

En attendant, avec l'aide d'un collègue, j'ai été en mesure de réparer ma solution et je voulais l'afficher pour l'exhaustivité. Ma solution fonctionne avec entropie croisée et sans modifier les données d'entraînement. De plus, il a la forme d'entrée désirée de (1, 2) et ouput est scalaire.

Il utilise un AdamOptimizer qui diminue l'erreur beaucoup plus vite qu'un GradientDescentOptimizer. Voir this post pour plus d'informations (& questions ^^) à propos de l'optimiseur.

En fait, mon réseau produit des résultats raisonnablement bons en seulement 400 à 800 étapes d'apprentissage.

Après 2000 apprentissage les étapes de la sortie est presque "parfait":

step: 2000 
loss: 0.00103311243281 

input: [0.0, 0.0] | output: [[ 0.00019799]] 
input: [0.0, 1.0] | output: [[ 0.99979786]] 
input: [1.0, 0.0] | output: [[ 0.99996307]] 
input: [1.0, 1.0] | output: [[ 0.00033751]] 

import tensorflow as tf  

##################### 
# preparation stuff # 
##################### 

# define input and output data 
input_data = [[0., 0.], [0., 1.], [1., 0.], [1., 1.]] # XOR input 
output_data = [[0.], [1.], [1.], [0.]] # XOR output 

# create a placeholder for the input 
# None indicates a variable batch size for the input 
# one input's dimension is [1, 2] and output's [1, 1] 
n_input = tf.placeholder(tf.float32, shape=[None, 2], name="n_input") 
n_output = tf.placeholder(tf.float32, shape=[None, 1], name="n_output") 

# number of neurons in the hidden layer 
hidden_nodes = 5 


################ 
# hidden layer # 
################ 

# hidden layer's bias neuron 
b_hidden = tf.Variable(tf.random_normal([hidden_nodes]), name="hidden_bias") 

# hidden layer's weight matrix initialized with a uniform distribution 
W_hidden = tf.Variable(tf.random_normal([2, hidden_nodes]), name="hidden_weights") 

# calc hidden layer's activation 
hidden = tf.sigmoid(tf.matmul(n_input, W_hidden) + b_hidden) 


################ 
# output layer # 
################ 

W_output = tf.Variable(tf.random_normal([hidden_nodes, 1]), name="output_weights") # output layer's weight matrix 
output = tf.sigmoid(tf.matmul(hidden, W_output)) # calc output layer's activation 


############ 
# learning # 
############ 
cross_entropy = -(n_output * tf.log(output) + (1 - n_output) * tf.log(1 - output)) 
# cross_entropy = tf.square(n_output - output) # simpler, but also works 

loss = tf.reduce_mean(cross_entropy) # mean the cross_entropy 
optimizer = tf.train.AdamOptimizer(0.01) # take a gradient descent for optimizing with a "stepsize" of 0.1 
train = optimizer.minimize(loss) # let the optimizer train 


#################### 
# initialize graph # 
#################### 
init = tf.initialize_all_variables() 

sess = tf.Session() # create the session and therefore the graph 
sess.run(init) # initialize all variables 

##################### 
# train the network # 
##################### 
for epoch in xrange(0, 2001): 
    # run the training operation 
    cvalues = sess.run([train, loss, W_hidden, b_hidden, W_output], 
         feed_dict={n_input: input_data, n_output: output_data}) 

    # print some debug stuff 
    if epoch % 200 == 0: 
     print("") 
     print("step: {:>3}".format(epoch)) 
     print("loss: {}".format(cvalues[1])) 
     # print("b_hidden: {}".format(cvalues[3])) 
     # print("W_hidden: {}".format(cvalues[2])) 
     # print("W_output: {}".format(cvalues[4])) 


print("") 
print("input: {} | output: {}".format(input_data[0], sess.run(output, feed_dict={n_input: [input_data[0]]}))) 
print("input: {} | output: {}".format(input_data[1], sess.run(output, feed_dict={n_input: [input_data[1]]}))) 
print("input: {} | output: {}".format(input_data[2], sess.run(output, feed_dict={n_input: [input_data[2]]}))) 
print("input: {} | output: {}".format(input_data[3], sess.run(output, feed_dict={n_input: [input_data[3]]}))) 
0

Je ne peux pas commenter parce que je n'ai pas assez de réputation mais j'ai quelques questions sur cette réponse mrry. La fonction de perte $ L_2 $ est logique parce que c'est essentiellement la fonction MSE, mais pourquoi ne pas effectuer un travail d'entropie croisée? Fonctionne certainement pour d'autres librairies NN.Deuxièmement, pourquoi traduire dans le monde votre espace d'entrée à partir de $ [0,1] -> [-1,1] $ affecte-t-il en particulier puisque vous avez ajouté des vecteurs de biais.

EDIT Ceci est une solution à l'aide transversale entropie et une chaude compilée à partir de sources multiples EDIT^2 changé le code à utiliser entropie croisée sans codage supplémentaire ou d'une valeur cible bizarre décalage

import math 
import tensorflow as tf 
import numpy as np 

HIDDEN_NODES = 10 

x = tf.placeholder(tf.float32, [None, 2]) 
W_hidden = tf.Variable(tf.truncated_normal([2, HIDDEN_NODES])) 
b_hidden = tf.Variable(tf.zeros([HIDDEN_NODES])) 
hidden = tf.nn.relu(tf.matmul(x, W_hidden) + b_hidden) 

W_logits = tf.Variable(tf.truncated_normal([HIDDEN_NODES, 1])) 
b_logits = tf.Variable(tf.zeros([1])) 
logits = tf.add(tf.matmul(hidden, W_logits),b_logits) 


y = tf.nn.sigmoid(logits) 


y_input = tf.placeholder(tf.float32, [None, 1]) 



loss = -(y_input * tf.log(y) + (1 - y_input) * tf.log(1 - y)) 

train_op = tf.train.GradientDescentOptimizer(0.01).minimize(loss) 

init_op = tf.initialize_all_variables() 

sess = tf.Session() 
sess.run(init_op) 

xTrain = np.array([[0, 0], [0, 1], [1, 0], [1, 1]]) 


yTrain = np.array([[0], [1], [1], [0]]) 


for i in xrange(2000): 
    _, loss_val,logitsval = sess.run([train_op, loss,logits], feed_dict={x: xTrain, y_input: yTrain}) 

    if i % 10 == 0: 
    print "Step:", i, "Current loss:", loss_val,"logits",logitsval 

print "---------" 
print sess.run(y,feed_dict={x: xTrain}) 
+0

Utiliser l'entropie croisée pour résoudre XOR comme un problème de classification est certainement possible (et j'ai répondu à une question précédente à ce sujet: http://stackoverflow.com/questions/33747596/problems-implementation-an-xor-gate-with-neural-nets-in-tensorflow/33750395 # 33750395). La question a été posée comme un problème de régression, pour lequel MSE est plus approprié. Je ne suis pas exactement sûr pourquoi le rééchelonnement des données d'entrée est nécessaire, mais peut-être qu'il se coince dans un minimum local? – mrry

+0

Eh bien peut-être mais la surface d'erreur XOR comprend-elle min local? Ou y a-t-il seulement un min local, c'est-à-dire min min – user2879934

+0

Aussi: pourquoi cela ne fonctionne-t-il pas sans un chaud! Si vous faites peut-être les cibles 1 dimensionnelles et changez les matrices de poids correspondantes cela ne fonctionne pas - souffle jusqu'à NaNs --- Je ne suis pas sûr de tout ce flux tensoriel semble être mieux adapté à NN – user2879934