텐서플로우로 보는 딥러닝 기초

Neural Nets (XOR) 예제로 알아보기

창창호 2023. 2. 16. 23:18

K(x) = sigmoid(XW1 + B1)

Y' = H(X) = sigmoid(K(x)W2 + B2)

2차원 배열이 x_data를 2차원 공간에 표현하여 x1, x2를 기준으로 y_data를 0 또는 1로 구분하는 예제

  1. 라이브러리 선언
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline  # 그림 등을 바로 볼 수 있게 해주는 라이브러리 선언
import tensorflow as tf
  1. 붉은색 과 푸른색으로 0, 1 표현하는 기본 틀 생성
x_data = [[0, 0],
          [0, 1],
          [1, 0],
          [1, 1]]
y_data = [[0],
          [1],
          [1],
          [0]]

plt.scatter(x_data[0][0],x_data[0][1], c='red' , marker='^')
plt.scatter(x_data[3][0],x_data[3][1], c='red' , marker='^')
plt.scatter(x_data[1][0],x_data[1][1], c='blue' , marker='^')
plt.scatter(x_data[2][0],x_data[2][1], c='blue' , marker='^')

plt.xlabel("x1")
plt.ylabel("x2")
plt.show()

  1. tensorflow data API로 학습시킬 값 담고 preprocess function으로 학습에 쓰일 Data 연산을 위해 Type을 맞춰줌
dataset = tf.data.Dataset.from_tensor_slices((x_data, y_data)).batch(len(x_data))

def preprocess_data(features, labels):
    features = tf.cast(features, tf.float32)
    labels = tf.cast(labels, tf.float32)
    return features, labels
  1. W, b값 설정
W = tf.Variable(tf.zeros((2,1)), name='weight')
b = tf.Variable(tf.zeros((1,)), name='bias')
print("W = {}, B = {}".format(W.numpy(), b.numpy()))

W = [[0.]
[0.]], B = [0.]

  1. Sigmoid 함수를 가설로 선언
def logistic_regression(features):
    hypothesis  = tf.divide(1., 1. + tf.exp(tf.matmul(features, W) + b))
    return hypothesis
  1. 가설 검증을 위한 Cost 함수 정의
def loss_fn(hypothesis, features, labels):
    cost = -tf.reduce_mean(labels * tf.math.log(logistic_regression(features)) + (1 - labels) * tf.math.log(1 - hypothesis))
    return cost

optimizer = tf.keras.optimizers.SGD(learning_rate=0.01)
  1. Sigmoid 함수를 통해 예측값이 0.5보다 크면 1을 반환, 0.5보다 작으면 0으로 반환하는 과정
def accuracy_fn(hypothesis, labels):
    predicted = tf.cast(hypothesis > 0.5, dtype=tf.float32)
    accuracy = tf.reduce_mean(tf.cast(tf.equal(predicted, labels), dtype=tf.float32))
    return accuracy
  1. GradientTape를 이용해 경사 값 계산
def grad(hypothesis, features, labels):
    with tf.GradientTape() as tape:
        loss_value = loss_fn(logistic_regression(features),features,labels)
    return tape.gradient(loss_value, [W,b])
  1. 위의 Data를 Cost함수를 통해 학습시킨 후 모델을 생성
EPOCHS = 1001

for step in range(EPOCHS):
    for features, labels  in dataset:
        features, labels = preprocess_data(features, labels)
        grads = grad(logistic_regression(features), features, labels)
        optimizer.apply_gradients(grads_and_vars=zip(grads,[W,b]))
        if step % 100 == 0:
            print("Iter: {}, Loss: {:.4f}".format(step, loss_fn(logistic_regression(features),features,labels)))
print("W = {}, B = {}".format(W.numpy(), b.numpy()))
x_data, y_data = preprocess_data(x_data, y_data)
test_acc = accuracy_fn(logistic_regression(x_data),y_data)
print("Testset Accuracy: {:.4f}".format(test_acc))

Iter: 0, Loss: 0.6931
Iter: 100, Loss: 0.6931
Iter: 200, Loss: 0.6931
Iter: 300, Loss: 0.6931
Iter: 400, Loss: 0.6931
Iter: 500, Loss: 0.6931
Iter: 600, Loss: 0.6931
Iter: 700, Loss: 0.6931
Iter: 800, Loss: 0.6931
Iter: 900, Loss: 0.6931
Iter: 1000, Loss: 0.6931
W = [[0.]
[0.]], B = [0.]
Testset Accuracy: 0.5000

실제 값은 Loss 가 계속 떨어지면서 Testset Accuracy : 1이 나와야하지만
Logistic function에선 Loss 가 동일하고 Testset Accuracy : 0.5가 나오는 걸 봐서 50%정도의 정확도를 가지고 있다고 말할 수 있다.