머신러닝

Covariance 항을 포함한 Softmax Classifier의 XOR 로직 적용

coding art 2019. 8. 3. 23:10
728x90



지난해 겨울 텐서플로우 OpenCV 출간 이후 7개월 만에 2권에 해당하는 “Scikit PyTorch 머신러닝을 출간하게 되었다. 각권이 450 페이지이므로 합 900 페이지에 달하는 내용이라 무슨 머신러닝을 공부하는데 분량이 왜 이렇게 많은가? 하고 의문을 가질 수도 있겠으나 그 내용이 튜토리얼성에 가까워 사실 그렇게 큰 부담은 없는 책이다. 물론 책 내부에 파이선 코드를 끼워 넣는 먹통 짓은 지금 세상에서는 할 필요가 없을 것이다. 해당 책의 머리말에 써둔 하이퍼링크 목차를 다운받으면 블로그를 직접 열어 볼 수 있으며 거기서 예제 코드를 다운 받을 수 있다.


 

1권에 해당하는 텐서플로우 OpenCV 머신러닝에서는 20179월경부터 201812월 사이에 머신러닝을 이해하고자 하는 필자의 열공(?) 내용을 담아 보았다면 2권에서는 1권에서 제기되었던 여러 내용들에 대해서 해답을 찾아가는 내용들을 꽤 많이 포함하였다. 2권이라고 해서 내용적으로 완전히 정리된 것은 아니기 때문에 다시 3권의 출발점이 될 수도 있을 것이다.

 

다소 아쉬운 점은 흥미 위주로 시작했던 1, 2권의 Softmax 관련 내용을 완전히 정리하지는 못했는데 이 그 이유는 R&D 영역으로 넘어갔기 때문이다. 2020년에는그 내용까지도 포함하여 출간할 계획이다.

 

본 서의 출간 목적은 작가들과 출판사가 염원하는 베스트셀러 화가 목표가 아니다. 사회적으로 인공지능(머신러닝)에 대한 이해 필요성이 점증하는 시기이며, 인공지능 분야의 발전 속도가 상당히 빠르기 때문에 그에 맞춰서 비전공자라 할지라도 머신러닝에 입문해 볼 수 있도록 경험과 생각을 공유해 보고자 하는 것이다.

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++




XOR 로직 계산은 Rosenblatt 의 퍼셉트론 연구로부터 잉태되었던 뉴럴 네트워크 발전의 중요한 고비로 기억된다. 1969년에 MIT 민스키 교수가 그의 저서 퍼셉트론에서 Rosenblatt 의 퍼셉트론으로는 XOR 로직 계산이 불가능하다고 부정적인 의견을 제시했던 바로 그 문제로서 1971년에 퍼셉트론 개발의 주역이었던 Rosenblatt 이 사고로 사망하면서 이 문제의 해결을 보지 못했다. 아울러 1970년대에 들어서면서 인공지능 및 머신 러닝 분야의 연구개발 지원이 완전히 끓어지면서 인공지능 발전의 암흑기에 들어서게 된다. 하지만 MIT의 민스키 교수가 퍼셉트론으로 처리 할 수 없는 영역을 건드렸던 것이 사실이긴 하지만 그래도 인공지능의 발전을 위한 단서 정도는 남긴 듯하다. XOR 로직 문제는 multi-layer 뉴럴 네트워크를 사용하면 문제를 해결 할 수 있는 가능성은 없지는 않다는 점을 지적했다. 하지만 당시의 인공지능 수준으로는 불가능했지만 상당한 기간이 흘러 1986년에 Hinton 교수가 Back Propagation 에 의한 웨이트 업데이트 알고리듬을 제안하면서 해결이 이루어진 것으로 보인다.


XOR 로직 문제는 그림의 우측에 볼 수 있듯이 2개의 영역으로 나누어야 할 데이타들이 서로 교차하는 지점에 있어 하나의 hyperplane 으로는 당연히 classification 이 불가능하다. 오늘날에도 이 문제는 머신 러닝을 공부하는 많은 이들에게도 꼭 다루어 보고 넘어가야 할 중요한 과제로 남아 있다. 이 문제 해결을 위한 고전적인 뉴럴 네트워크 구성문제는 필자의 저서 파이선 코딩 초보자를 위한 텐서플로우OpenCV 머신러닝편에서도 이미 다루었다. 아래 url 주소를 참조하기 바란다.

 

3-6 XOR 논리 처리를 위한 Neural Network(NN) 구성 232

https://steemit.com/kr/@codingart/3-6-xor-neural-network-nn

3-11 바이아스가 추가된 Quadratic Hypothesis Perceptron에 의한 XOR 논리 처리 248

https://steemit.com/kr/@codingart/3-11-quadratic-hypothesis-perceptron-xor

 

한편으로는 XOR 문제 자체가 비선형이므로 다항식 알고리듬에 의한 성공적인 계산 결과를 이미 제시하였다. 한편 뉴럴 네트워크나 다항식 알고리듬이 아닌 Covariance 항을 이용한 Softmax에 의한 알고리듬을 제시하기로 한다. 유도 과정은 볼츠만 분포 이상으로 길므로 생략하고 최종 공식을 사용하여 설명하기로 하자.

Softmax 공식에서 linear 파트만을 가지고는 아예 학습이 불가능하므로 배제하기로 하면 비선형 항 즉 Covariance 항만 남게 된다. Covariance 항을 구성하는 2개의 Hypothesis 자체가 학습 첫 단계에서 랜덤 넘버로 초기화 되므로 Lagrange’s multiplier α 값은 임의로 설정이 가능하다.

  

 

아래의 100회 학습 계산 결과를 참조해 보자. “1” True인 경우 0.97 이상으로 잘 수렴된 결과를 보여준다.



첨부된 파이선 코드를 실행해 보자.

#quadratic_softmax_XOR_01.py

from matplotlib import pyplot as plt
import numpy as np
import tensorflow as tf

tf.set_random_seed(777)  # for reproducibility

x_data = [[ 0, 0 ], [ 1, 0], [ 0, 1], [ 1, 1] ]
y_data =  [ [1, 0], [0, 1], [0, 1],[1, 0] ]

X = tf.placeholder("float", [None, 2])
Y = tf.placeholder("float", [None, 2])

dof = 2
threshold = 0.5
training_num = 101
lr=0.5
W2 = tf.Variable(tf.random_normal([2, dof]), name='weight2')
W3 = tf.Variable(tf.random_normal([2, dof]), name='weight3')
b2 = tf.Variable(tf.random_normal([ dof]), name='bias2')
b3 = tf.Variable(tf.random_normal([ dof]), name='bias3')

c_d = (tf.matmul(X, W2) + b2)*(tf.matmul(X, W3) + b3)

hypothesis = tf.nn.softmax(c_d)

#Cross entropy cost/loss
cost = tf.reduce_mean(-tf.reduce_sum(Y * tf.log(hypothesis), axis=1))
optimizer = tf.train.GradientDescentOptimizer(learning_rate=lr).minimize(cost)

predicted = tf.cast(hypothesis > threshold, dtype=tf.float32)
accuracy = tf.reduce_mean(tf.cast(tf.equal(predicted, Y), dtype=tf.float32))

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

    for step in range(training_num):
        sess.run(optimizer, feed_dict={X: x_data, Y: y_data})
        if step % 100 == 0:
            print(step, sess.run(cost, feed_dict={X: x_data, Y: y_data}),
                                 sess.run(W2),sess.run(W3),sess.run(b2),sess.run(b3))

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