5

Я построил MLP с помощью библиотеки TensorFlow Google. Сеть работает, но почему-то отказывается учиться должным образом. Он всегда сходится к выходу около 1.0, независимо от того, что на самом деле представляет собой вход.TensorFlow MLP не тренируется XOR

полный код вид here.

Любые идеи?


вход и выход (размер партии 4) следующим образом:

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

конфигурации Скрытый слой:

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

конфигурации Выходной слой:

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 

Мои обучения методы выглядеть следующим образом:

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 

Я попробовал обе установки для перекрестной энтропии:

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

и

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

, где n_output оригинальный выход, как описано в output_data и output предсказанное/вычисленные значения моей сети.


обучение внутри для цикла (для русских эпох) выглядит следующим образом:

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

Я спасаю результат в cvalues ​​для отладки printig из loss, W_hidden ...

Независимо от того, что я пробовал, когда я тестирую свою сеть, пытаясь проверить выход, он всегда производит что-то похожее е это:

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

Так не обучения должным образом, но всегда сходящихся почти 1,0 независимо от того, который подается входной.

+1

Ваш 'b_hidden' переменная является скаляром - это то, что намеренно? Я думаю, вы должны создать его как 'b_hidden = tf.Variable (tf.constant (0.1, shape = [hidden_nodes]), name =" hidden_bias ")', что может помочь. Еще одна вещь, которую нужно попробовать, заключается в добавлении выражения смещения 'b_output' к вашему уровню вывода. – mrry

+0

Благодарим вас за комментарий. В самом деле, я просто не заметил, что «b_hidden» также должен быть вектором, а не скаляром ... однако сеть все еще сходится почти до 1.0 для каждого входа, с или без скрытого смещения, как скаляр или вектор и с или без смещения для выходного слоя. Я действительно думаю, что мне недостает некоторой ошибки в методе обучения или сетевой архитектуре:/ – daniel451

ответ

8

Между тем с помощью коллеги я смог исправить свое решение и хотел опубликовать его для полноты. Мое решение работает с кросс-энтропией и без изменения данных обучения. Дополнительно он имеет желаемую форму ввода (1, 2) и . Ouput является скаляром.

Это делает использование AdamOptimizer что уменьшает ошибку гораздо быстрее, чем GradientDescentOptimizer. См. this post для получения дополнительной информации (& вопросов ^^) об оптимизаторе.

На самом деле, моя сеть производит достаточно хорошие результаты всего за 400-800 шагов обучения.

После 2000 года обучения шаги выход почти "идеальный":

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

Я не могу комментировать, потому что у меня недостаточно репутации, но у меня есть некоторые вопросы по этому ответу mrry. Функция потери $ L_2 $ имеет смысл, потому что это в основном функция MSE, но почему бы не кросс-энтропия работать? Разумеется, работает для других NN-библиотек.Во-вторых, почему в мире будет отображаться ваше входное пространство от $ [0,1] -> [-1,1] $, какое-либо влияние , особенно, так как вы добавили векторы смещения.

РЕДАКТИРОВАТЬ Этого решения с использованием перекрестной энтропии и один горячей скомпилированной из нескольких источников РЕДАКТИРОВАТЬ^2 изменил код, чтобы использовать перекрестную энтропию без какого-либо дополнительного кодирования или любого странного целевого значения сдвига

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

Использование кросс-энтропии для решения XOR как задачи классификации, безусловно, возможно (и я ответил на предыдущий вопрос об этом: http://stackoverflow.com/questions/33747596/проблемы реализующей-ан-XOR-ворот-с нейронными сетями-в-tensorflow/33750395 # 33750395). Вопрос был поставлен как проблема регрессии, для которой MSE более уместен. Я не совсем уверен, почему необходимо масштабирование входных данных, но, возможно, оно застряло в локальном минимуме? – mrry

+0

Ну, может быть, но поверхность ошибки XOR включает локальный мин? Или есть только один локальный мин, т. Е. Глобальный мин. – user2879934

+0

Также: почему это не работает без разогрева! Если вы, возможно, мишень целиком и меняете соответствующие весовые матрицы, она не работает - взрывается до NaN --- Я не уверен, что весь этот тензорный поток кажется, что анано может быть более подходящим для NN – user2879934

Смежные вопросы