머신러닝

1-8 TensorFlow Softmax Classification에서 Hypothesis Contour 작도

coding art 2020. 1. 12. 13:40
728x90


XOR 데이터나 Iris Flowers 데이터 Classification에서 샘플들과 Hyperplane이 함께 표시되도록 Sklearn에서 지원하는 plot_decision_regions 루틴을 사용하여 작도하였으나 이 루틴을 TensorFlow 코드와 연동하여 사용하기 위해서는 코드의 일부를 TensorFlow 코드에 맞춰서 수정할 필요가 있다.

 

Sklearn 이 지원하는 SVC루틴에서는 학습결과를 plot_decision_regions루틴의 classifier=svm 으로 지정함으로 인해 학습 정보의 전달이 가능하지만 TensorFlow 학습결과를 작도에 사용하기 위해서는 TensorFlow 코드와 동시에 plot_decision_regions루틴을 수정해야 한다. 특히 Hypothesis Contour를 작도하기 위해서는 TensorFlow 코드에서 학습된 웨이트와 바이아스를 사용하여 Hypothesis 레벨 별로 Contour를 미리 계산할 수 있도록 아래의 수정된 코드에서처럼 Graph 가 준비되어 있어야 한다.


XOR 문제에서도 hypothesis = 0.5 hyperplane 인데 거의 “+”형상에 가깝다. 반면에 hypothesis 레벨 값이 그 이상이거나 그 이하에서는 쌍곡선(Hyperbola) 형태의 Contour 곡선을 보며주며 classification 에러가 증가하게 된다.



Contour 작도를 위한 수정된 루틴 tf_plot_decision_regions를 실행시키려면 반드시 Session 단계에서 필요한 argument들을 넘겨주어야 한다. 즉 샘플데이타와 라벨 데이터 그리고 Graph 상태의 hypothesis, p1, p2, ∙∙∙,p7 들이다. Graph 상태의 데이터라 함은 계산 공식을 의미하며 따라서 Graph를 넘겨 받은 후 tf_plot_decision_regions 내부에서 Session 이 이루어져야 작도를 위한 데이터가 얻어지게 된다. 특히 hypothesis 는 함수로 되어 있지만 tf_plot_decision_regions 내부에서 hypothesis 레벨 값 계산을 위해 Session을 실행하면 자동적으로 호출이 된다.


 

    tf_ 루틴 내에서 그래프를 작도하기 위한 테두리 크기를 결정하고 설정된 resolution에 맞춰 많은 수의 meshgrid 점들을 생성 후 이 좌표 값을 hypothesis 에 적용하여 지정된 레벨 값 보다 큰지 작은 지 결정하고 중복하여 출력한다. 이때에 투명도 조절이 되지 않으면 다른 hypothesis 레벨 곡선을 관찰할 수 없으므로 거의 투명에 가깝도록 alpha 값을 낮게 잡도록 한다.

 

작도된 Contour를 관찰해 보자.


#SVM_sigmoid_contourf_01.py


from sklearn import __version__ as sklearn_version
from sklearn import datasets
import numpy as np

from matplotlib.colors import ListedColormap
import matplotlib.pyplot as plt
from sklearn.svm import SVC


def plot_decision_regions(X, y, classifier, test_idx=None, resolution=0.01):

    # setup marker generator and color map
    markers = ('s', 'x', 'o', '^', 'v')
    colors = ('red', 'blue', 'lightgreen', 'gray', 'cyan')
    cmap = ListedColormap(colors[:len(np.unique(y))])

    # plot the decision surface
    x1_min, x1_max = X[:, 0].min() - 1, X[:, 0].max() + 1
    x2_min, x2_max = X[:, 1].min() - 1, X[:, 1].max() + 1
    xx1, xx2 = np.meshgrid(np.arange(x1_min, x1_max, resolution),
                           np.arange(x2_min, x2_max, resolution))
    #print('xx1,xx2=',xx1,xx2)
    P=np.array([xx1.ravel(), xx2.ravel()])
    print('P=',P.T)
    print(classifier)
    Z = classifier.predict(np.array([xx1.ravel(), xx2.ravel()]).T)
    print('Z=',Z)
    print('Z.shape=',Z.shape)
    Z = Z.reshape(xx1.shape)
    #print('Z.reshape=',Z.reshape)
    plt.contourf(xx1, xx2, Z, alpha=0.3, cmap=cmap)
    plt.grid(True)
    plt.xlim(xx1.min(), xx1.max())
    plt.ylim(xx2.min(), xx2.max())

    for idx, cl in enumerate(np.unique(y)):
        plt.scatter(x=X[y == cl, 0],
                    y=X[y == cl, 1],
                    alpha=0.8,
                    c=colors[idx],
                    marker=markers[idx],
                    label=cl,
                    edgecolor='black')

    # highlight test samples
    if test_idx:
        # plot all samples
        X_test, y_test = X[test_idx, :], y[test_idx]

        plt.scatter(X_test[:, 0],
                    X_test[:, 1],
                    c='',
                    edgecolor='black',
                    alpha=1.0,
                    linewidth=1,
                    marker='o',
                    s=100,
                    label='test set')


# **Note**
np.random.seed(3)

pts = 200  # total number of random points
X_xor = np.random.randn(pts, 2)
y_xor = np.logical_xor(X_xor[:, 0] > 0, X_xor[:, 1] > 0)
print(y_xor)
y_xor = np.where(y_xor, 1, 0)
print(y_xor)

print(X_xor.shape)
print(y_xor.shape)

plt.scatter(X_xor[y_xor == 1, 0], X_xor[y_xor == 1, 1],
            c='b', marker='x', label='1')
plt.scatter(X_xor[y_xor == 0, 0], X_xor[y_xor == 0, 1],
            c='r', marker='s', label='0')

plt.xlim([-3, 3])
plt.ylim([-3, 3])
plt.legend(loc='best')
plt.tight_layout()
plt.show()

#Support Vector Machine "RBF"
svm = SVC(kernel='rbf', random_state=1, gamma=1.0, C=10.0)
svm.fit(X_xor, y_xor)
plot_decision_regions(X_xor, y_xor,classifier=svm)

plt.legend(loc='upper left')
plt.tight_layout()
plt.show()

#Following is method to convert numpy array to tensor
import tensorflow as tf
import time

start_time = time.time()

def fn(X,W1,b1,W2,b2):
    hypothesis =  tf.sigmoid((tf.matmul(X, W2) + b2)*(tf.matmul(X, W1) + b1))
    return hypothesis


def tf_plot_decision_regions(X_xor, y, hypothesis, p1,p2,p3,p4,p5,p6,p7,test_idx=None, resolution=0.02):
  
    # setup marker generator and color map
    markers = ('s', 'x', 'o', '^', 'v')
    colors = ('red', 'blue', 'lightgreen', 'gray', 'cyan')
    cmap = ListedColormap(colors[:len(np.unique(y))])
    # plot the decision surface
    x1_min, x1_max = X_xor[:, 0].min() - 1, X_xor[:, 0].max() + 1
    x2_min, x2_max = X_xor[:, 1].min() - 1, X_xor[:, 1].max() + 1
    xx1, xx2 = np.meshgrid(np.arange(x1_min, x1_max, resolution),
                           np.arange(x2_min, x2_max, resolution))
    XX = np.array([xx1.ravel(), xx2.ravel()]).T
    print(XX.shape)
    #Z = classifier.predict(np.array([xx1.ravel(), xx2.ravel()]).T)
    #Z = Z.reshape(xx1.shape)
    #h, p = sess.run([hypothesis, predicted], feed_dict={X: (np.array([xx1.ravel(), xx2.ravel()]).T) })
    h, p1,p2,p3,p4,p5,p6,p7 = sess.run([hypothesis, p1,p2,p3,p4,p5,p6,p7], feed_dict={X: XX })

    p1 = p1.reshape(xx1.shape)
    p2 = p2.reshape(xx1.shape)
    p3 = p3.reshape(xx1.shape)
    p4 = p4.reshape(xx1.shape)
    p5 = p5.reshape(xx1.shape)
    p6 = p6.reshape(xx1.shape)
    p7 = p7.reshape(xx1.shape)
    plt.contourf(xx1, xx2, p1, alpha=0.1, cmap=cmap)
    plt.contourf(xx1, xx2, p2, alpha=0.1, cmap=cmap)
    plt.contourf(xx1, xx2, p3, alpha=0.1, cmap=cmap)
    plt.contourf(xx1, xx2, p4, alpha=0.1, cmap=cmap)
    plt.contourf(xx1, xx2, p5, alpha=0.1, cmap=cmap)
    plt.contourf(xx1, xx2, p6, alpha=0.1, cmap=cmap)
    plt.contourf(xx1, xx2, p7, alpha=0.1, cmap=cmap)
    plt.grid(True)
    plt.xlim(xx1.min(), xx1.max())
    plt.ylim(xx2.min(), xx2.max())

    for idx, cl in enumerate(np.unique(y)):
        plt.scatter(x=X_xor[y == cl, 0],
                    y=X_xor[y == cl, 1],
                    alpha=0.8,
                    c=colors[idx],
                    marker=markers[idx],
                    label=cl,
                    edgecolor='black')

    # highlight test samples
    if test_idx:
        # plot all samples
        X_test, y_test = X_xor[test_idx, :], y[test_idx]

        plt.scatter(X_test[:, 0],
                    X_test[:, 1],
                    c='',
                    edgecolor='black',
                    alpha=1.0,
                    linewidth=1,
                    marker='o',
                    s=100,
                    label='test set')


#Training Data
Y_xor = np.zeros([pts,1])
  
Y_xor[y_xor == 0] = [0.]
Y_xor[y_xor == 1] = [1.]
print(Y_xor)

X_xor = np.float32(X_xor)
Y_xor = np.float32(Y_xor)
#print(Y_xor)

print(X_xor.shape)
print(Y_xor.shape)

#hyperparameter
learning_rate = 0.00001
training_epochs = 20000
display_steps = 1000
#Network parameters
n_input = 2
dof1 = 1
#Graph Nodes
X = tf.placeholder("float", [None, n_input])
Y = tf.placeholder("float", [None, dof1])
print(X)
print(Y)

#Weights and Biases, model, loss and optimizer
W1 = tf.Variable(tf.random_normal([n_input, dof1], stddev=0.01))
b1 = tf.Variable(tf.random_normal([dof1], stddev=0.01))
W2 = tf.Variable(tf.random_normal([n_input, dof1], stddev=0.01))
b2 = tf.Variable(tf.random_normal([dof1], stddev=0.01))

#hypothesis =  (tf.matmul(X, W2) + b2)*(tf.matmul(X, W1) + b1)
hypothesis = fn(X,W1,b1,W2,b2)

# cost/loss function
cost = -tf.reduce_mean(Y * tf.log(hypothesis) + (1 - Y) * tf.log(1 - hypothesis))
optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.001).minimize(cost)
#optimizer = tf.train.AdamOptimizer(learning_rate).minimize(cost)

p1 = tf.cast(hypothesis > 0.2, dtype=tf.float32)
p2 = tf.cast(hypothesis > 0.3, dtype=tf.float32)
p3 = tf.cast(hypothesis > 0.4, dtype=tf.float32)
p4 = tf.cast(hypothesis > 0.5, dtype=tf.float32)
p5 = tf.cast(hypothesis > 0.6, dtype=tf.float32)
p6 = tf.cast(hypothesis > 0.7, dtype=tf.float32)
p7 = tf.cast(hypothesis > 0.71, dtype=tf.float32)
accuracy = tf.reduce_mean(tf.cast(tf.equal(tf.argmax(p5,1), tf.argmax(Y,1)), dtype=tf.float32))

#Initializing global variables
init = tf.global_variables_initializer()

with tf.Session() as sess:
    sess.run(init)
   
    for epoch in range(training_epochs):
        _, c, w1, B1, w2, B2 = sess.run([optimizer, cost, W1, b1, W2, b2], feed_dict={X: X_xor, Y: Y_xor})
        if(epoch + 1) % display_steps == 0:
            print( "Epoch: ", (epoch+1), "Cost: ", c, w1, B1, w2, B2 )
    print("Optimization Finished!")

    # Accuracy report
    h, p, a = sess.run([hypothesis, p4, accuracy],
                       feed_dict={X: X_xor, Y: Y_xor})
    print("\nHypothesis:\n ", h, "\nCorrect:\n ", p, "\nAccuracy: ", a)
    #print(p.shape)
    #print(p)
    tf_plot_decision_regions(X_xor, y_xor, hypothesis, p1,p2,p3,p4,p5,p6,p7)
    plt.legend(loc='upper left')
    plt.tight_layout()
    plt.show()
    sess.close()

end_time = time.time()
print( "Completed in ", end_time - start_time , " seconds")