[tf] XOR tensorflow로 학습구현
+ Tensorflow로 XOR 학습을 구현하기
XOR 학습을 수동으로 계산하지 않고, tensorflow의 api를 사용하면 심플해진다.
복잡한 네트웍도 쉽게 구현이 가능하다.
노드의 개수 및 레이어를 2-4-1 로 구성.
입력층에 노드 2개(feature 개수. x1, x2)
은닉층에는 4개
출력층은 1개의 노드. (Y)
back-propagation을 위한 골치 아픈 작업(미분)들을 할 필요없이 api 하나로 학습 가능! activation function도 원하는대로 쉽게 변경하고, 학습 알고리즘은 쉽게 바꿀 수 있다.
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Tue May 23 14:56:53 2017
@author: crazyj
"""
import numpy as np
import tensorflow as tf
# trainint set
X_train = np.array( [[0,0], [0,1], [1,0], [1,1]])
T_train = np.array( [[0], [1], [1], [0]] )
# placeholder
X = tf.placeholder(tf.float32, [None, 2])
T = tf.placeholder(tf.float32, [None, 1])
# variable
W1 = tf.Variable(tf.truncated_normal([2,4]))
b1 = tf.Variable(tf.zeros([4]))
W2 = tf.Variable(tf.truncated_normal([4,1]))
b2 = tf.Variable(tf.zeros([1]), dtype=tf.float32)
# model
A1 = tf.matmul(X, W1)+b1
Z1 = tf.sigmoid(A1)
A2 = tf.matmul(Z1, W2)+b2
Z2 = tf.sigmoid(A2)
learn_rate = 0.1
Cost = tf.reduce_mean(tf.reduce_sum(tf.square(Z2-T), 1))
train = tf.train.GradientDescentOptimizer(learn_rate).minimize(Cost)
predict = Z2
sess = tf.Session()
sess.run(tf.global_variables_initializer())
for i in range(5000):
_train, _Cost = sess.run([train, Cost], feed_dict={X:X_train, T:T_train})
print( "cost=", _Cost)
_predict = sess.run([predict], feed_dict={X:X_train})
print("predict=", _predict)
print("result=", np.array(np.array(_predict)>=0.5, np.int))
결과
cost= 0.021748
cost= 0.0217359
cost= 0.0217239
predict= [array([[ 0.10571096],
[ 0.86153752],
[ 0.84178925],
[ 0.17739831]], dtype=float32)]
result= [[[0]
[1]
[1]
[0]]]
+ 코드 설명
# trainint set
X_train = np.array( [[0,0], [0,1], [1,0], [1,1]])
T_train = np.array( [[0], [1], [1], [0]] )
훈련 데이터는 당연히 xor의 입력 조합에 따른 결과를 훈련시킨다. (0,0) -> 0 , (0,1) -> 1 , (1,0) -> 1 , (1,1)->1
# placeholder
X = tf.placeholder(tf.float32, [None, 2])
T = tf.placeholder(tf.float32, [None, 1])
플레이스 홀더는 텐서플로우내에서 돌아갈 입출력 변수들이라고 보면 된다. 노드에서 변수가 되는 것을 X 입력층은 (?,2) 매트릭스 크기(로우는 임의의 개수, 컬럼은 2개(x1,x2)), 출력층 T는 (n,1) 매트릭스 형태로 선언한다.
# variable
W1 = tf.Variable(tf.truncated_normal([2,4]))
b1 = tf.Variable(tf.zeros([4]))
W2 = tf.Variable(tf.truncated_normal([4,1]))
b2 = tf.Variable(tf.zeros([1]), dtype=tf.float32)
텐서 플로우 변수들을 정의한다. 이것은 그래프에 구성될 노드들의 변수의 형태를 정의한다.
네트웍을 2-4-1로 구성할 것이므로 여기에 따른 weight를 담을 변수와 bias 변수의 형태는 다음과 같다.
2개 노드는 placeholder로 X이고, 2-4연결되는 W(웨이트)는 2행(입력노드개수) 4열(출력노드개수) 매트릭스이다. bias는 4개(출력노드개수)이다.
4-1로 연결되는 파트의 W는 4x1 이렇게 b는 1개 이렇게 구성한다. 초기값들은 랜덤하게 채워준다. bias는 0으로 초기화해준다.
# model
A1 = tf.matmul(X, W1)+b1
Z1 = tf.sigmoid(A1)
A2 = tf.matmul(Z1, W2)+b2
Z2 = tf.sigmoid(A2)
이제 빠진 히든 노드들과 출력층 노드들을 구성한다.
2-4-1네트웍에서 2개는 X, 4개는 A1으로 정하고,
A1 = X x W1 + b1 으로 정의한다.
Z1=은 A1에 활성화함수 sigmoid를 적용한다.
A2=Z1 x W2 + b2로 정의한다. 앞 노드의 출력 결과에 weighted sum이다.
Z2 = A2에 sigmoid를 적용한 것으로 최종 output이다.
learn_rate = 0.1
Cost = tf.reduce_mean(tf.reduce_sum(tf.square(Z2-T), 1))
train = tf.train.GradientDescentOptimizer(learn_rate).minimize(Cost)
predict = Z2
sess = tf.Session()
sess.run(tf.global_variables_initializer())
for i in range(5000):
_train, _Cost = sess.run([train, Cost], feed_dict={X:X_train, T:T_train})
print( "cost=", _Cost)
print("result=", np.array(np.array(_predict)>=0.5, np.int))
최종 결과로 시그모이드 함수에서 0.5이상이면 1로 미만이면 0으로 출력하여 binary 분류를 한다.