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 수가 늘어나도 별 반 다르지 않을 것이다. 중간에 한 번 막혔던 만큼 확실히 하고 가 뿌듯하다.