5

Ich habe ein MLP mit Googles TensorFlow Bibliothek gebaut. Das Netzwerk funktioniert, aber irgendwie weigert es sich, richtig zu lernen. Es konvergiert immer zu einer Ausgabe von fast 1,0, egal was die Eingabe tatsächlich ist.TensorFlow MLP kein Training XOR

Der vollständige Code kann here gesehen werden.

Irgendwelche Ideen?


Die Eingangs- und Ausgangs (Ansatzgröße 4) ist wie folgt:

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

verborgene Schicht Konfiguration:

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

Ausgangsschichtkonfiguration:

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 

Meine Lernen Methoden wie folgt aussehen:

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 

Ich habe versucht, beide Setups für Kreuzentropie:

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

und

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

wo n_output die ursprüngliche Ausgabe ist, wie in output_dataoutput und der vorausgesagte/berechnete Wert durch mein Netzwerk beschrieben.


Die Ausbildung innerhalb der for-Schleife (für n Epochen) geht so:

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

Ich bin das Ergebnis zu cvalues ​​für Debug printig von loss Speichern W_hidden, ...

Egal was ich versucht habe, wenn ich mein Netzwerk teste, versuche, die Ausgabe zu validieren, produziert es immer etwas lik e dies:

(...) 
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]] 

es also ist nicht richtig Lernen aber immer auf fast 1,0 egal konvergierenden die Eingangszugeführt wird.

+1

Ihre 'b_hidden' Variable ein Skalar ist - ist das Absicht? Ich denke, Sie sollten es als 'b_hidden = tf.Variable (tf.constant (0.1, shape = [hidden_nodes]), name =" hidden_bias ")' erstellen, was helfen könnte. Eine andere Sache, die Sie ausprobieren sollten, wäre, einen 'b_output'-Bias-Ausdruck zu Ihrer Ausgabeschicht hinzuzufügen. – mrry

+0

Vielen Dank für den Kommentar. In der Tat habe ich nicht bemerkt, dass "b_hidden" auch ein Vektor und kein Skalar sein sollte ... das Netzwerk konvergiert jedoch immer noch für jede Eingabe auf fast 1.0, mit oder ohne versteckten Bias, als Skalar oder Vektor und mit oder ohne eine Vorspannung für die Ausgabeschicht. Ich glaube wirklich, dass mir ein Fehler in der Lernmethode oder Netzwerkarchitektur fehlt:/ – daniel451

Antwort

8

Inzwischen konnte ich mit Hilfe eines Kollegen meine Lösung fixieren und wollte sie auf Vollständigkeit posten. Meine Lösung funktioniert mit Kreuz Entropie und ohne Änderung der Trainingsdaten. Zusätzlich hat es die gewünschte Eingabeform von (1, 2) und Ausgabe ist Skalar.

Es macht die Verwendung eines AdamOptimizer, die den Fehler viel schneller als ein GradientDescentOptimizer abnimmt. Weitere Informationen finden Sie unter this post (& Fragen ^^) zum Optimierer.

In der Tat produziert mein Netzwerk in nur 400-800 Lernschritten ziemlich gute Ergebnisse.

Nach 2000 Lernschritte der Ausgang fast "perfekt" ist:

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

Ich kann nicht kommentieren, weil ich nicht genug Ruf habe, aber ich habe einige Fragen zu dieser Antwort mrry. Die $ L_2 $ Loss-Funktion macht Sinn, weil sie im Grunde genommen die MSE-Funktion ist, aber warum funktioniert Cross-Entropy nicht? Sicher funktioniert für andere NN-Bibliotheken.Zweitens, warum in der Welt würde übersetzen Ihren Eingabebereich von $ [0,1] -> [-1,1] $ jeden Einfluss haben vor allem, da Sie Bias-Vektoren hinzugefügt.

EDIT Dies ist eine Lösung unter Verwendung von Kreuzentropie und one-hot aus verschiedenen Quellen zusammengestellt EDIT^2 den Code veränderte ohne zusätzliche Codierung oder einen seltsamen Zielwert Quer Entropie verwenden Verschiebung

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

Die Verwendung von Kreuzentropie zur Lösung von XOR als Klassifikationsproblem ist sicherlich möglich (und ich beantworte eine vorherige Frage dazu: http://stackoverflow.com/questions/33747596/Probleme-Implementieren-XOR-Gate-mit-neuronalen Netzen-in-Tensor-Flow/33750395 # 33750395). Die Frage wurde als Regressionsproblem gestellt, für das MSE geeigneter ist. Ich bin mir nicht ganz sicher, warum Neuskalierung der Eingabedaten notwendig ist, aber vielleicht bleibt es in einem lokalen Minimum hängen? – mrry

+0

Nun, vielleicht aber enthält die XOR-Fehlerfläche lokale min? Oder gibt es nur eine lokale min, d. H. Globale min – user2879934

+0

Auch: warum funktioniert das nicht ohne one-hot! Wenn du vielleicht die Ziele 1 dimensional änderst und die entsprechenden Gewichtsmatrizen änderst, funktioniert es nicht - sprengt zu NaNs --- Ich bin mir nicht sicher, ob dieser ganze Tensorfluss eher für NN geeignet ist. – user2879934