2016-07-25 5 views
3

私は、TensorFlow(Python 3版)に完全に接続された簡単なフィードフォワードニューラルネットを実装しようとしています。ネットワークには2つの入力と1つの出力があり、私はそれをトレーニングして2つの入力のXORを出力しようとしています。次のように私のコードは次のとおりです。TensorFlow:2層フィードフォワードニューラルネット

import numpy as np 
import tensorflow as tf 

sess = tf.InteractiveSession() 

inputs = tf.placeholder(tf.float32, shape = [None, 2]) 
desired_outputs = tf.placeholder(tf.float32, shape = [None, 1]) 

weights_1 = tf.Variable(tf.zeros([2, 3])) 
biases_1 = tf.Variable(tf.zeros([1, 3])) 
layer_1_outputs = tf.nn.sigmoid(tf.matmul(inputs, weights_1) + biases_1) 

weights_2 = tf.Variable(tf.zeros([3, 1])) 
biases_2 = tf.Variable(tf.zeros([1, 1])) 
layer_2_outputs = tf.nn.sigmoid(tf.matmul(layer_1_outputs, weights_2) + biases_2) 

error_function = -tf.reduce_sum(desired_outputs * tf.log(layer_2_outputs)) 
train_step = tf.train.GradientDescentOptimizer(0.05).minimize(error_function) 

sess.run(tf.initialize_all_variables()) 

training_inputs = [[0.0, 0.0], [0.0, 1.0], [1.0, 0.0], [1.0, 1.0]] 
training_outputs = [[0.0], [1.0], [1.0], [0.0]] 

for i in range(10000): 
    train_step.run(feed_dict = {inputs: np.array(training_inputs), desired_outputs: np.array(training_outputs)}) 

print(sess.run(layer_2_outputs, feed_dict = {inputs: np.array([[0.0, 0.0]])})) 
print(sess.run(layer_2_outputs, feed_dict = {inputs: np.array([[0.0, 1.0]])})) 
print(sess.run(layer_2_outputs, feed_dict = {inputs: np.array([[1.0, 0.0]])})) 
print(sess.run(layer_2_outputs, feed_dict = {inputs: np.array([[1.0, 1.0]])})) 

それは十分に単純なようだが、最後のprint文は、ニューラルネットは関係なく、トレーニングの繰り返しや学習率の数の、希望出力の近くにどこにもないことを示しています。誰でも私が間違っていることを見ることができますか?

ありがとうございます。

EDIT:誤差関数は、エラーの二乗和であることを

error_function = 0.5 * tf.reduce_sum(tf.sub(layer_2_outputs, desired_outputs) * tf.sub(layer_2_outputs, desired_outputs)) 

: 私はまた、次の代替の誤差関数を試してみました。それは常にネットワークが正確に0.5の値を出力する結果になる - 私のコードのどこかに間違いの別の兆候。

EDIT 2 : 私のコードは、ANDとORでは正常に動作しますが、XORではうまく動作しません。私は今非常に困惑しています。

答えて

8

コードにはいくつかの問題があります。以下では、あなたをソリューションに導くために各行にコメントするつもりです。

注:XORは直線的に分離できません。 1つ以上の隠れたレイヤーが必要です。

N.B:# [!]で始まる行は、間違っていた行です。

import numpy as np 
import tensorflow as tf 

sess = tf.InteractiveSession() 

# a batch of inputs of 2 value each 
inputs = tf.placeholder(tf.float32, shape=[None, 2]) 

# a batch of output of 1 value each 
desired_outputs = tf.placeholder(tf.float32, shape=[None, 1]) 

# [!] define the number of hidden units in the first layer 
HIDDEN_UNITS = 4 

# connect 2 inputs to 3 hidden units 
# [!] Initialize weights with random numbers, to make the network learn 
weights_1 = tf.Variable(tf.truncated_normal([2, HIDDEN_UNITS])) 

# [!] The biases are single values per hidden unit 
biases_1 = tf.Variable(tf.zeros([HIDDEN_UNITS])) 

# connect 2 inputs to every hidden unit. Add bias 
layer_1_outputs = tf.nn.sigmoid(tf.matmul(inputs, weights_1) + biases_1) 

# [!] The XOR problem is that the function is not linearly separable 
# [!] A MLP (Multi layer perceptron) can learn to separe non linearly separable points (you can 
# think that it will learn hypercurves, not only hyperplanes) 
# [!] Lets' add a new layer and change the layer 2 to output more than 1 value 

# connect first hidden units to 2 hidden units in the second hidden layer 
weights_2 = tf.Variable(tf.truncated_normal([HIDDEN_UNITS, 2])) 
# [!] The same of above 
biases_2 = tf.Variable(tf.zeros([2])) 

# connect the hidden units to the second hidden layer 
layer_2_outputs = tf.nn.sigmoid(
    tf.matmul(layer_1_outputs, weights_2) + biases_2) 

# [!] create the new layer 
weights_3 = tf.Variable(tf.truncated_normal([2, 1])) 
biases_3 = tf.Variable(tf.zeros([1])) 

logits = tf.nn.sigmoid(tf.matmul(layer_2_outputs, weights_3) + biases_3) 

# [!] The error function chosen is good for a multiclass classification taks, not for a XOR. 
error_function = 0.5 * tf.reduce_sum(tf.sub(logits, desired_outputs) * tf.sub(logits, desired_outputs)) 

train_step = tf.train.GradientDescentOptimizer(0.05).minimize(error_function) 

sess.run(tf.initialize_all_variables()) 

training_inputs = [[0.0, 0.0], [0.0, 1.0], [1.0, 0.0], [1.0, 1.0]] 

training_outputs = [[0.0], [1.0], [1.0], [0.0]] 

for i in range(20000): 
    _, loss = sess.run([train_step, error_function], 
         feed_dict={inputs: np.array(training_inputs), 
            desired_outputs: np.array(training_outputs)}) 
    print(loss) 

print(sess.run(logits, feed_dict={inputs: np.array([[0.0, 0.0]])})) 
print(sess.run(logits, feed_dict={inputs: np.array([[0.0, 1.0]])})) 
print(sess.run(logits, feed_dict={inputs: np.array([[1.0, 0.0]])})) 
print(sess.run(logits, feed_dict={inputs: np.array([[1.0, 1.0]])})) 

列の反復回数を増やして、ランダム初期設定値が何であってもネットワークが収束することを確認しました。

出力、20000列車の繰り返しがある後:

[[ 0.01759939]] 
[[ 0.97418505]] 
[[ 0.97734243]] 
[[ 0.0310041]] 

それはかなりよさそうです。

+0

徹底的な答えをありがとうございました。私はあなたが行った変更を理解しています。しかし、OR演算ではなく、XOR演算を実行しようとしています。だから実際には私の目標出力に間違いがなかった。目標出力は[[0.0]、[1.0]、[1.0]、[0.0]]です。あなたのコードを使って、私はまだXORを実行する神経回路網を得ることができません。それについて何か助けてもらえますか? – CircuitScholar

+0

答えを更新しました。 – nessuno

+0

ありがとうございます。私は実際には2つの層だけで目標を達成することができました。ウェイトをゼロ以外の値に初期化するという考えは、私のコードを動作させるものです。 – CircuitScholar

1

あなたの実装は正しいようです。使用すると、より多くの層

    • 変更tf.nn.sigmoid他の非線形活性化関数へ
    • (1E-5に1E-3)小さな学習率を使用します。ここでは、試みることができるいくつかのことがありますXOR neural network architecture
  • +0

    私はあなたの提案を試みました。失敗。私は、訓練の後、全ての入力が非常に似通った出力(すなわち、00、01、10、および11すべてがニューラルネット出力~0.77をもたらすという結果)を加えたことを付け加えたい。これは完全に接続された単純なネットワークなので、この場合のレイヤーが増えると追加の機能や精度が得られないので、避けたいのです。私も前にMATLABでこの正確なニューラルネットを実装しました。それがうまくいきました。私は単にコードのどこかで間違いを犯したと確信しています。 – CircuitScholar

    +0

    'error_function'では、目的の出力を直接乗算するのではなく、値を減算します。また、それをユークリッドの損失に変換してみてください。あるいは、これを回帰問題ではなく分類としてフレーム化することもできます。 – ahaque

    +0

    クロスエントロピーの代わりに、ターゲットと出力の違いを含むより慣習的なエラー機能を試しました(元の投稿の私の編集を参照)。しかし、私はまだ間違った動作を経験しています。 – CircuitScholar

    関連する問題