● 텐서플로우 회귀 분석 모델

  • 다양한 방법이 존재
  • 텐서플로우2만 사용하는 방법, 케라스를 이용한 방법, 둘을 모두 섞은 방법 등

 

1. 선형 회귀

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

# 하이퍼 파라미터
learning_rate = 0.01
training_steps = 1000

# 데이터(연습용으로 랜덤 생성)
X = np.random.randn(50)
# Y에는 랜덤값을 더해 노이즈도 약간 추가
Y = 2 * X + np.random.randn(50)

# 가중치와 편향
W = tf.Variable(np.random.randn(), name = 'weight')
b = tf.Variable(np.random.randn(), name = 'bias')

# 선형회귀 함수
def linear_regression(x):
    return W * x + b

# 손실함수
def mean_square(y_pred, y_true):
    return tf.reduce_mean(tf.square(y_pred - y_true))

# 옵티마이저
optimizer = tf.optimizers.SGD(learning_rate

# 옵티마이저 실행 함수
def run_optimization():
    with tf.GradientTape() as tape:
        pred = linear_regression(X)
        loss = mean_square(pred, Y)
    
    gradients = tape.gradient(loss, [W, b])

    optimizer.apply_gradients(zip(gradients, [W, b]))

# 지정한 step만큼(1000번) 반복
for step in range(1, training_steps + 1):
    run_optimization()

    if step % 50 == 0:
        pred = linear_regression(X)
        loss = mean_square(pred, Y)
        print("step: {:4d}\tloss:{:.4f}\tW: {:.4f}\tb: {:.4f}".format(step, loss, W.numpy(), b.numpy()))

# 출력 결과
step:   50	loss:0.9240	W: 2.0819	b: 0.0301
step:  100	loss:0.9101	W: 2.1498	b: 0.0728
step:  150	loss:0.9084	W: 2.1726	b: 0.0893
step:  200	loss:0.9082	W: 2.1803	b: 0.0956
step:  250	loss:0.9082	W: 2.1829	b: 0.0980
step:  300	loss:0.9082	W: 2.1838	b: 0.0990
step:  350	loss:0.9082	W: 2.1841	b: 0.0993
step:  400	loss:0.9082	W: 2.1842	b: 0.0994
step:  450	loss:0.9082	W: 2.1842	b: 0.0995
step:  500	loss:0.9082	W: 2.1842	b: 0.0995
step:  550	loss:0.9082	W: 2.1842	b: 0.0995
step:  600	loss:0.9082	W: 2.1842	b: 0.0995
step:  650	loss:0.9082	W: 2.1842	b: 0.0995
step:  700	loss:0.9082	W: 2.1842	b: 0.0995
step:  750	loss:0.9082	W: 2.1842	b: 0.0995
step:  800	loss:0.9082	W: 2.1842	b: 0.0995
step:  850	loss:0.9082	W: 2.1842	b: 0.0995
step:  900	loss:0.9082	W: 2.1842	b: 0.0995
step:  950	loss:0.9082	W: 2.1842	b: 0.0995
step: 1000	loss:0.9082	W: 2.1842	b: 0.0995
# 시각화
plt.plot(X, Y, 'ro', label = 'Data')
plt.plot(X, np.array(W * X + b), label = 'Fitted Line')
plt.legend()
plt.grid()
plt.show()

 

 

2. 다항 회귀

  - modules import

from tensorflow.keras.optimizers import Adam

 

  - Hyper Parameters

epochs = 1000
learning_rate = 0.04

 

  - 변수 지정

a = tf.Variable(np.random.randn())
b = tf.Variable(np.random.randn())
c = tf.Variable(np.random.randn())

print(a.numpy())
print(b.numpy())
print(c.numpy())

# 출력 결과
0.74045
-0.027472999
-1.99301

 

  - 데이터 지정

X = np.random.randn(50)
Y = X**2 + X * np.random.randn(50)
# 데이터 분포 시각화
line_x = np.arange(min(X), max(X), 0.001)
line_y = a * line_x ** 2 + b * line_x + c

x_ = np.arange(-4., 4., 0.001)
y_ = a * x_ ** 2 + b * x_ + c

plt.scatter(X, Y, label = 'X data')
plt.plot(x_, y_, 'g--', label = 'origin line')
plt.plot(line_x, line_y, 'r--', label = 'before train')
plt.xlim(-4., 4.)
plt.legend()
plt.grid()
plt.show()

 

  - Util Functions

def compute_loss():
    pred_y = a * (np.array(X) ** 2) + b * np.array(X) + c
    loss = tf.reduce_mean((Y - pred_y) ** 2)
    return loss

 

  - Optimizer

optimizer = Adam(learning_rate = learning_rate)

 

  - 학습

for epoch in range(1, epochs + 1, 1):
    optimizer.minimize(compute_loss, var_list = [a, b, c])

    if epoch % 100 == 0:
        print("epoch: {:4d}\ta: {:.4f}\tb: {:.4f}\tc: {:.4f}".format(epoch, a.numpy(), b.numpy(), c.numpy()))

# 출력 결과
epoch:  100	a: 0.7958	b: -0.4986	c: 0.1659
epoch:  200	a: 0.7958	b: -0.4986	c: 0.1659
epoch:  300	a: 0.7958	b: -0.4986	c: 0.1659
epoch:  400	a: 0.7958	b: -0.4986	c: 0.1659
epoch:  500	a: 0.7958	b: -0.4986	c: 0.1659
epoch:  600	a: 0.7958	b: -0.4986	c: 0.1659
epoch:  700	a: 0.7958	b: -0.4986	c: 0.1659
epoch:  800	a: 0.7958	b: -0.4986	c: 0.1659
epoch:  900	a: 0.7958	b: -0.4986	c: 0.1659
epoch: 1000	a: 0.7958	b: -0.4986	c: 0.1659

 

  - 학습 후의 회귀선

line_x = np.arange(min(X), max(X), 0.001)
line_y = a * line_x ** 2 + b * line_x + c

plt.scatter(X, Y, label = 'X data')
plt.plot(x_, y_, 'g--', label = 'origin line')
plt.plot(line_x, line_y, 'r--', label = 'after train')
plt.xlim(-4., 4.)
plt.legend()
plt.grid()
plt.show()

 

 

3. 로지스틱 회귀

  • 다항 분류, MNIST

 

  - modules import

from tensorflow.keras.datasets import mnist

 

  - Hyper Parameters

# 데이터가 0~9, 총 10개의 숫자로 이루어져 있으므로 클래스의 개수는 10개
num_classes = 10
# 데이터가 28*28의 이미지로 되어 있으므로 한 개당 총 픽셀 수는 784개
num_features = 784

learning_rate = 0.1
training_steps = 1000
batch_size = 256

 

  - 데이터 로드

(x_train, y_train), (x_test, y_test) = mnist.load_data()

# 데이터 전처리
# 데이터 타입 변환
x_train, x_test = np.array(x_train, np.float32), np.array(x_test, np.float32)

# 28*28의 이미지 데이터를 1행 784열의 1차원 데이터로 평탄화
x_train, x_test = x_train.reshape([-1, num_features]), x_test.reshape([-1, num_features])

# mnist 데이터의 각 값은 한 픽셀이 가질 수 있는 색의 값으로,
# 0~255의 값을 가지므로 각 값을 255로 나누면 모든 값을 0~1사이의 값으로 정규화할 수 있음
x_train, x_test = x_train / 255., x_test / 255.

 

  - tf.data API 사용

train_data = tf.data.Dataset.from_tensor_slices((x_train, y_train))
train_data = train_data.repeat().shuffle(5000).batch(batch_size).prefetch(1)

 

  - 변수 지정

W = tf.Variable(tf.random.normal([num_features, num_classes]), name = 'weight')
b = tf.Variable(tf.zeros([num_classes]), name = 'bias')

 

  - Util Functions

def logistic_regression(x):
    return tf.nn.softmax(tf.matmul(x, W) + b)

def cross_entropy(pred_y, true_y):
    true_y = tf.one_hot(true_y, depth = num_classes)
    # 클립을 꽂은 것처럼 출력값의 범위를 미리 지정
    pred_y = tf.clip_by_value(pred_y, 1e-9, 1.)

    return tf.reduce_mean(-tf.reduce_sum(true_y * tf.math.log(pred_y), 1))

def accuracy(y_pred, y_true):
    correct_prediction = tf.equal(tf.argmax(y_pred, 1), tf.cast(y_true, tf.int64))
    return tf.reduce_mean(tf.cast(correct_prediction, tf.float32))

 

  - Optimizer

optimizer = tf.optimizers.SGD(learning_rate)

def run_optimization(x, y):
    with tf.GradientTape() as tape:
        pred = logistic_regression(x)
        loss = cross_entropy(pred, y)

    gradients = tape.gradient(loss, [W, b])

    optimizer.apply_gradients(zip(gradients, [W, b]))

 

  - 학습 진행

for step, (batch_x, batch_y) in enumerate(train_data.take(training_steps), 1):
    run_optimization(batch_x, batch_y)

    if step % 50 == 0:
        pred = logistic_regression(batch_x)
        loss = cross_entropy(pred, batch_y)
        acc = accuracy(pred, batch_y)
        print("step: {:4d}\tloss: {:.4f}\taccuracy: {:.4f}".format(step, loss, acc))

# 출력 결과
step:   50	loss: 5.8780	accuracy: 0.3086
step:  100	loss: 3.2118	accuracy: 0.4609
step:  150	loss: 2.5498	accuracy: 0.5508
step:  200	loss: 2.7539	accuracy: 0.5508
step:  250	loss: 2.6145	accuracy: 0.5625
step:  300	loss: 1.5360	accuracy: 0.6719
step:  350	loss: 1.8810	accuracy: 0.6602
step:  400	loss: 1.4833	accuracy: 0.7305
step:  450	loss: 1.4094	accuracy: 0.7109
step:  500	loss: 1.4736	accuracy: 0.7266
step:  550	loss: 1.4690	accuracy: 0.7188
step:  600	loss: 1.5128	accuracy: 0.6875
step:  650	loss: 1.3078	accuracy: 0.7695
step:  700	loss: 1.1052	accuracy: 0.7969
step:  750	loss: 1.1313	accuracy: 0.7500
step:  800	loss: 0.8837	accuracy: 0.8086
step:  850	loss: 0.9336	accuracy: 0.7891
step:  900	loss: 1.0169	accuracy: 0.7812
step:  950	loss: 0.8714	accuracy: 0.8047
step: 1000	loss: 0.9229	accuracy: 0.8086

 

  - 테스트

pred = logistic_regression(x_test)
print("Test Accuracy: {}".format(accuracy(pred, y_test)))

# 출력 결과
Test Accuracy: 0.8057000041007996
  • train 데이터 정확도는 위에서 최종적으로 0.8086으로 나왔고
    test 데이터 정확도는 0.8057로 나

 

  - 시각화

num_images = 5
test_images = x_test[:num_images]
predictions = logistic_regression(test_images)

plt.figure(figsize = (30, 8))
for i in range(1, num_images + 1):
    plt.subplot(1, num_classes, i)
    plt.imshow(np.reshape(test_images[i-1], [28, 28]), cmap = 'gray')
    # 예측한 것 중 가장 높은 값을 정답으로 해야함(argmax 사용)
    plt.title("Model prediction: {}".format(np.argmax(predictions.numpy()[i-1])))

plt.show()

제목에 해당 글자를 예측한 값이 정답으로 잘 표현된 것을 확인

 

+ Recent posts