머신러닝

3-13 Quadratic Exponent를 가지는 softmax에 의한 XOR 논리 처리

coding art 2021. 7. 2. 20:07
728x90

XOR 논리 문제를 처리함에 있어 2차 다항식이나 3차 다항식 hypothesis 또는 quadratic hypothesis를 사용하는 최소제곱법은 NN에 비해 괄목할 만큼 효율적으로 반복학습 횟수를 줄이면서도 높은 정밀도로 결과를 계산할 수 있었다.

 

즉 그러한 hypothesis들을 사용하여 XOR 문제를 성공적으로 풀 수 있었다면 SoftmaxSigmoid 함수에서 이들 exponent를 사용하여 XOR 문제를 처리해 보도록 하자. 한편 AND 또는 OR 논리 문제를 다루는 경우에는 선형 hypothesis 뿐만 아니라 Softmax기법이나 Sigmoid 함수를 사용해서도 성공적으로 문제를 풀 수 있지만 XOR 문제에 있어서는 선형 hypothesis 뿐만 아니라 선형 exponent에 의한 Softmax기법이나 Sigmoid 함수를 사용하더라도 XOR 문제를 풀 수는 없었다는 점을 참고하기로 한다.

 

Softmax 확장 이전에 XOR 문제를 풀기 위한 다항식 기법을 다시 정리해 보자.

hypothesis = (x1 * w1 + x2 * w2 + b1)*(x1 * w1 + x2 * w2 + b2)

hypothesis를 사용하면 50:50 비율로 계산이 성공과 실패를 반복하므로 실패로 보면 된다. b1 = 0 으로 두면 100% 성공적인 계산이 이루어진다.

#secondorder_regression_XOR_01.py

 

3차식(third order) hypothesis를 사용할 때도 거의 동일한 결과를 준다.

hypothesis =(x1 * w1 + x2 * w2 + b0)*(x1 * w1 + x2 * w2+ b1)* (x1 * w1 + x2 * w2 + b2)

hypothesis를 사용하면 50:50 비율로 계산이 성공과 실패를 반복하므로 실패로 보면 된다. b0 = 0 으로 두면 100% 성공적인 계산이 이루어진다.

 

Softmax 기법에서는 지수 형태에 선형 엑스포넨트를 적용하지만 바로 앞의 계산 결과에서 실패했던 2차 또는 3차 다항식 hypothesis 사례를 엑스포넨트로 적용해 보자.

 

한편 두 종류로 분리해 보는 XOR 라벨링 문제이므로 Softmax 사용법을 확장해 보도록 하자.

다음 그림에서처럼 선형 hypothesis를 사용하는 경우의 입력 데이터는 Softmax를 사용할 경우 리스트형으로 변환하고 출력 값 또한 one hot code 형태로 처리한다. 아울러 초기 값 설정에서 random_normal 보다는 random_uniform을 사용하여 설정하기로 한다. 사실 어느 것으로 해도 결과에 차이는 없을 것이다.

2차 다항식 엑스포넨트의 경우 b1 = 0 이든 아니든 상관없이 성공적으로 계산된다. 3차 다항식의 경우도 마찬가지이다. 아울러 별도의 웨이트 벡터가 추가되는 quadratic hypothesis를 사용하는 경우도 성공적인 계산 결과를 준다.

#secondorder_softmax_XOR_01.py

#cubicorder_softmax_XOR_01.py

#quadratic_softmax_XOR_01.py

 

Sigmoid 함수를 사용하는 경우도 비슷한 경향을 보여주는데 첨부파일을 다운 받아 실행해보자.

#quadratic_sigmoid_XOR_01.py

from matplotlib import pyplot as plt
import numpy as np

import tensorflow as tf
tf.set_random_seed(777)  # for reproducibility

def gen_image(arr):
    t_d = np.reshape(arr, (3, 3))
    two_d = (np.reshape(arr, (3, 3)) * 255).astype(np.uint8)
    print(two_d)
    plt.imshow(two_d, interpolation='nearest')
    plt.savefig('batch.png')
    return plt

x_data = [[ 0, 0 ], [ 1, 0], [ 0, 1], [ 1, 1] ]
#y_data =  [ [1, 0], [0, 1], [0, 1],[0, 1] ]
y_data =  [ [1, 0], [0, 1], [0, 1],[1, 0] ]
X = tf.placeholder("float", [None, 2])
Y = tf.placeholder("float", [None, 2])
nb_classes = 2

W1 = tf.Variable(tf.random_normal([2, nb_classes]), name='weight1')
b1 = tf.Variable(tf.random_normal([ nb_classes]), name='bias1')
W2 = tf.Variable(tf.random_normal([2, nb_classes]), name='weight2')
b2 = tf.Variable(tf.random_normal([ nb_classes]), name='bias2')
#W1 = tf.Variable(tf.random_uniform([2, nb_classes]), name='weight1')
#b1 = tf.Variable(tf.random_uniform([ nb_classes]), name='bias1')
#W2 = tf.Variable(tf.random_uniform([2, nb_classes]), name='weight2')
#b2 = tf.Variable(tf.random_uniform([ nb_classes]), name='bias2')
#uniform is better than normal!!!!!!

#tf.nn.softmax computes softmax activations
#softmax = exp(logits) / reduce_sum(exp(logits), dim)
c = tf.matmul(X, W1) + b1
d = tf.matmul(X, W2) + b2
c_d = tf.multiply(c,d)

hypothesis = tf.nn.sigmoid(c_d)

#Cross entropy cost/loss

cost = -tf.reduce_mean(Y * tf.log(hypothesis) + (1 - Y) *
                       tf.log(1 - hypothesis))
optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.1).minimize(cost)

#Launch graph
with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())

    for step in range(2001):
        sess.run(optimizer, feed_dict={X: x_data, Y: y_data})
        if step % 1000 == 0:
            print(step, sess.run(cost, feed_dict={X: x_data, Y: y_data}))

    print('--------------')

    #Testing & One-hot encoding
    a = sess.run(hypothesis, feed_dict={X: [[ 0.0, 0.0 ]]})
    print(a, sess.run(tf.argmax(a, 1)))

    print('--------------')


    all = sess.run(hypothesis, feed_dict={
               X: [[ 0.0, 0.0 ],[ 1.0, 0.0], [ 0.0, 1.0 ], [ 1.0, 1.0 ]]})
    print(all, sess.run(tf.argmax(all, 1)))