5

Ho costruito un MLP con la libreria di Google TensorFlow. La rete funziona ma in qualche modo si rifiuta di apprendere correttamente. Converge sempre in un output di circa 1,0 indipendentemente dal fatto che l'input sia effettivamente.tensorflow MLP non si allena XOR

Il codice completo può essere visto here.

Qualche idea?


Il ingresso e uscita (dimensione del lotto 4) è il seguente:

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

configurazione strato nascosto:

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

configurazione uscita strato:

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 

mio apprendimento metodi simile a questa:

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 

ho provato entrambe le configurazioni per entropia croce:

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

e

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

dove n_output è l'uscita originale come descritto in output_data e output il valore previsto/calcolato mia rete.


Il formazione all'interno del ciclo for (per n epoche) va in questo modo:

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

Mi risparmio il risultato di cvalues ​​per il debug printig di loss, W_hidden, ...


Non importa quello che ho provato, quando provo la mia rete, provando a convalidare l'output, produce sempre qualcosa di simile e questo:

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

Quindi non è apprendimento correttamente ma sempre convergenti a quasi 1,0 non importa quale ingresso è alimentato.

+1

vostro 'variabile b_hidden' è uno scalare - è intenzionale? Penso che dovresti crearlo come 'b_hidden = tf.Variable (tf.constant (0.1, shape = [hidden_nodes]), name =" hidden_bias ")', che potrebbe aiutare. Un'altra cosa da provare sarebbe aggiungere un termine di bias 'b_output' al livello di output. – mrry

+0

Grazie per il commento. In effetti, non sono riuscito a notare che 'b_hidden' dovrebbe essere anche un vettore e non uno scalare ... tuttavia, la rete converge ancora a quasi 1.0 per ogni input, con o senza un bias nascosto, come scalare o un vettore e con o senza pregiudizi per il livello di output. Penso davvero che mi manchi qualche errore nel metodo di apprendimento o nell'architettura di rete:/ – daniel451

risposta

8

Nel frattempo con l'aiuto di un collega sono riuscito a risolvere la mia soluzione e volevo pubblicarla per completezza. La mia soluzione funziona con con entropia incrociata e senza modificare i dati di allenamento. Inoltre ha la forma di input desiderata di (1, 2) e ouput è scalare.

si avvale di un AdamOptimizer che diminuisce l'errore molto più veloce di un GradientDescentOptimizer. Vedere this post per ulteriori informazioni (& domande ^^) sull'ottimizzatore.

In effetti, la mia rete produce risultati ragionevolmente buoni in soli 400-800 passi di apprendimento.

Dopo il 2000 l'apprendimento passi l'uscita è quasi "perfetta":

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

non posso commentare perché non hanno abbastanza reputazione, ma ho alcune domande su quella risposta mrry. La funzione di perdita $ L_2 $ ha senso perché è fondamentalmente la funzione MSE, ma perché la cross-entropy non dovrebbe funzionare? Certamente funziona per altre librerie NN.In secondo luogo, perché nel mondo la traduzione dello spazio di input da $ [0,1] -> [-1,1] $ ha effetto in particolare da quando hai aggiunto i vettori di bias.

EDIT Questa è una soluzione utilizzando entropia incrociata e un caldo compilato da più fonti EDIT^2 cambiato il codice per utilizzare cross-entropia senza alcuna codifica supplementare o qualsiasi valore obiettivo strano spostamento

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

Usare l'entropia incrociata per risolvere XOR come un problema di classificazione è certamente possibile (e ho risposto a una precedente domanda a riguardo: http://stackoverflow.com/questions/33747596/problemi-attuazione-un-porta xor-con-neurali reti-in-tensorflow/33750395 # 33750395). La domanda è stata posta come un problema di regressione, per il quale MSE è più appropriato. Non sono esattamente sicuro del motivo per cui è necessario ridimensionare i dati di input, ma forse si sta bloccando in un minimo locale? – mrry

+0

Beh, forse, ma la superficie dell'errore XOR include locale min? O c'è solo un min locale, cioè il minimo globale – user2879934

+0

Inoltre: perché non funziona senza uno-caldo! Se tu forse i bersagli 1 dimensionale e cambia le matrici di peso corrispondenti non funziona - salta in aria ai NaN --- Non sono sicuro che l'intera tensorflow sembri essere più adatta a NN – user2879934

Problemi correlati