본문 바로가기

DEEP LEARNING/Tensorflow Training

Make A Dataset

tf.data를 이용하여 Dataset 만들기

## Library import
import tensorflow as tf
import numpy as np
from tensorflow import keras

TensorFlow를 이용하여 deep learning model을 학습할 때, input data 및 label을 공급해주기 위하여 tf.data.Dataset을 이용

## 0에서 19까지 정수가 input data라고 가정
a = np.arange(20)
print(a)

## dataset 만들기
ds_tensors = tf.data.Dataset.from_tensor_slices(a)

## 앞 5개 data 확인
data = ds_tensors.take(3)
for x in data:
    print (x)
[ 0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19]
tf.Tensor(0, shape=(), dtype=int64)
tf.Tensor(1, shape=(), dtype=int64)
tf.Tensor(2, shape=(), dtype=int64)

dataset 내의 각 data에 함수를 적용하기 위한 map, shuffle, batch size 사용

ds_tensors = ds_tensors.map(tf.square).shuffle(3).batch(5)

for x in ds_tensors:
    print(x)
tf.Tensor([ 1  4  0  9 36], shape=(5,), dtype=int64)
tf.Tensor([ 16  64  25  49 100], shape=(5,), dtype=int64)
tf.Tensor([144 169  81 121 256], shape=(5,), dtype=int64)
tf.Tensor([196 289 324 361 225], shape=(5,), dtype=int64)

TensorFlow를 이용하여 자동미분 계산하기

Deep learning model을 학습시키기 위해서는 gradient descent 방법을 사용 (Loss 를 weight로 미분)

TensorFlow는 자동 미분을 위한 tf.GradientTape API를 제공
tf.GradientTape는 컨텍스트(context) 안에서 실행된 모든 연산을 테이프(tape)에 "기록"한 후,
후진 방식 자동미분(reverse mode differentiation)을 사용해 테이프에 "기록된" 연산의 그래디언트를 계산

  1. GradientTape()로 만들어지는 gradient tape 컨텍스트 내에서 함수값 결과를 저장한 텐서 y를 만든다.
  2. tape.gradient(y, x) 명령으로 변수형 텐서 x에 대한 y의 미분값을 계산한다.
x = tf.ones((2, 2))

with tf.GradientTape() as t:
    t.watch(x)    
    y = tf.reduce_sum(x)
    z = tf.multiply(y, y)

dz_dx = t.gradient(z, x)

기본적으로 Variable들은 자동으로 watch가 적용되어 있기 때문에, 수동으로 watch를 해 줄 필요는 없습니다.

x = tf.Variable(x)
with tf.GradientTape() as t:   
    y = tf.reduce_sum(x)
    z = tf.multiply(y, y)

dz_dx = t.gradient(z, x)
print(dz_dx)
tf.Tensor(
[[8. 8.]
 [8. 8.]], shape=(2, 2), dtype=float32)

End-to-End 예제: 선형 회귀

## Library import
import matplotlib.pyplot as plt
## For reproducibility
np.random.seed(777)
tf.random.set_seed(777)

Input data 생성

## y = 1 * x + 2를 따르는 noisy한 data를 100개 생성
x = np.linspace(0, 1, 100, dtype=np.float32)

slopes = 1  # 기울기
intercept = np.random.normal(2, 0.2, 100).astype(np.float32)  # noise

## outputs
y = x * slopes + intercept
## 만들어진 data와 ground truth 확인
plt.scatter(x, y)
plt.plot(x, x * 1 + 2., label="ground truth", c="r")
plt.legend()
plt.show()

## Dataset 만들기
dataset = tf.data.Dataset.from_tensor_slices((x, y))
dataset = dataset.shuffle(buffer_size=100).batch(50)

## Weight와 bias 만들기
w = tf.Variable(.1, tf.float32)
b = tf.Variable(0., tf.float32)

learning_rate = 0.1  # learning rate
## linear regression model 만들기
def compute_predictions(x):
    return x * w + b

## loss function - Mean Squared Error
def compute_loss(labels, predictions):
    return tf.reduce_mean(tf.square(labels - predictions))

## gradient 계산하여 gradient descent 학습법으로 weight와 bias update
def train_on_batch(x, y):
    with tf.GradientTape() as tape:
        predictions = compute_predictions(x)
        loss = compute_loss(y, predictions)
        dloss_dw, dloss_db = tape.gradient(loss, [w, b])
    w.assign_sub(learning_rate * dloss_dw)
    b.assign_sub(learning_rate * dloss_db)
    return loss
## 20 epoch 동안 학습진행
loss_list, w_list, b_list = [], [], []
for epoch in range(20):
    loss = 0.
    for x, y in dataset:
        loss_ = train_on_batch(x, y)
        loss += loss_ / 2.

    loss_list.append(loss.numpy())
    w_list.append(w.numpy())
    b_list.append(b.numpy())
# Training graph
plt.plot(loss_list, label="loss")
plt.plot(w_list, label="w")
plt.plot(b_list, label="b")
plt.legend()
plt.show()

## 결과 확인
plt.scatter(x, y)
plt.plot(x, x * w_list[-1] + b_list[-1], label="model", c="r")
plt.plot(x, x * 1 + 2., label="ground truth", c="g")
plt.legend()
plt.show()