[텐서플로우로 시작하는 딥러닝 기초] Lab 05-3: Logistic Regression/Classification 를 TensorFlow로 구현하기

2020. 10. 24. 23:22카테고리 없음

이번 주는 방화지대 공사를 하느라 또 오랜만이다. 낫질과 톱질을 하도 했더니 손가락 마디가 쑤시네..

이번에는 Logistic Regression을 텐서플로우로 구현해보자!


import numpy as np
import matplotlib.pyplot as plt
import tensorflow as tf
tf.random.set_seed(1106)  # for reproducibility

x_train = [[1., 2.],
          [2., 3.],
          [3., 1.],
          [4., 3.],
          [5., 3.],
          [6., 2.]]
y_train = [[0.],
          [0.],
          [0.],
          [1.],
          [1.],
          [1.]]

x_test = [[5.,2.]]
y_test = [[1.]]


x1 = [x[0] for x in x_train]
x2 = [x[1] for x in x_train]

colors = [int(y[0]) for y in y_train]
plt.scatter(x1,x2, c=colors , marker='^')
plt.scatter(x_test[0][0],x_test[0][1], c="red")

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

 

두 개의 feature를 갖는 Data이다. label이 0인 녀석들은 보라색, 1인 녀석들은 노란색, test친구는 빨간 원이다. 


dataset = tf.data.Dataset.from_tensor_slices((x_train, y_train)).batch(len(x_train))

Tensorflow data API를 통해 학습시킬 값들을 담는다. train set을 slice를 통해 6개의 조각으로 나누고 각각의 조각은 1 row 2 column, 1 row의 크기를 갖게 될 것이다. (x_train과 y_train의 크기) 

한 번 더 짚고 가자면, batch란 학습 데이타 하나를 말한다.


W = tf.Variable(tf.zeros([2,1]), name='weight')
b = tf.Variable(tf.zeros([1]), name='bias')

W와 b를 임의의 값으로 설정해준다.  tf.random.normal로 선언해도 된다. 


def logistic_regression(features):
    hypothesis  = tf.divide(1., 1. + tf.exp(tf.matmul(features, W) + b))
    return hypothesis

시그모이드 함수인 Hypothesis를 만들어 준다. 

이렇게 생긴녀석. 잊을래야 잊을 수가 없다.


다음은 Cost 함수를 정의할 차례.

def loss_fn(hypothesis, labels):
    cost = -tf.reduce_mean(labels * tf.math.log(hypothesis) + (1 - labels) * tf.math.log(1 - hypothesis))
    return cost

optimizer = tf.keras.optimizers.SGD(learning_rate=0.01)

경사하강법(Stochastic Gradient Descent, SGD)  옵티마이저를 써버린다. https://keras.io/ko/optimizers/


모델이 잘 작동하나 알기위해 Test set의 label과 예측값을 비교하는 accuracy_fn을 만드는데, 꼭 필요하지는 않은 것 같다.

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.int32))
    return accuracy

tf.cast(조건, dtype) 함수는 한 마디로 casting 해주는 함수인데 여기서는 조건의 boolean값을 dtype으로 뱉어준다.


def grad(features, labels):
    with tf.GradientTape() as tape:
    	hypothesis = logistic_regression(features)
        loss_value = loss_fn(hypothesis,labels)
    return tape.gradient(loss_value, [W,b])

GradientTape으로 Cost함수를 W와 b로 미분해서 경사 값을 계산한다.


EPOCHS = 1001

for step in range(EPOCHS):
    for features, labels  in iter(dataset):
        grads = grad(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),labels)))
test_acc = accuracy_fn(logistic_regression(x_test),y_test)
print("Testset Accuracy: {:.4f}".format(test_acc))


 

지금까지 X값에 Weight를 부여하여 나온 가설을 Cost 값의 최적화를 통해 1과 0으로 구별하는 하나의 과정을 공부했다. 이는 Neural Networking의 하나의 Component가 된다고 한다. Input에 대해 1 또는 0의 output을 내뱉는 하나의 신경세포. 


두 개의 features를 갖는 Binary Logistic Regression을 수행해봤다. feature 수가 늘어나도 별 반 다르지 않을 것이다. 중간에 한 번 막혔던 만큼 확실히 하고 가 뿌듯하다.