Neural Net & Back Propagation 구현(2)

이전 포스트에서는 numpy만을 사용하여 back propagation과 neural network를 구현하였다. 이번에는 tensorflow2를 사용하여 이전에 한 것과 똑같은 것을 보다 쉽게 구현하였다.

1. Import libraries

import tensorflow as tf
from tensorflow.keras import layers
import numpy as np

2. Set hyperparameters

EPOCHS = 1000

3. Network Architecture

  • Input layer : 2
  • Hidden layer : 128 (Sigmoid)
  • Output : 1 (Softmax)
class MyModel(tf.keras.Model):
    def __init__(self):
        super(MyModel, self).__init__()
        self.d1 = layers.Dense(128, input_dim=2, activation='sigmoid')
        self.d2 = layers.Dense(10, activation='softmax')
            
    def call(self, x, training=None, mask=None):
        x = self.d1(x)
        x = self.d2(x)
        return x

4. Train function

  • 함수의 인자값 : model, input & label, loss_object, optimizer, train loss & train metric
@tf.function
def train_step(model, inputs, labels, loss_object, optimizer, train_loss, train_metric):
    with tf.GradientTape() as tape:
        pred = model(inputs) # 예측값
        loss = loss_object(labels, pred) # 예측 손실
    grads = tape.gradient(loss, model.trainable_variables) # dy/dx
    
    optimizer.apply_gradients(zip(grads, model.trainable_variables))
    train_loss(loss)
    train_metric(labels, predictions)

5. Import Data

np.random.seed(0)

pts = list()
labels = list()
center_pts = np.random.uniform(-8.0, 8.0, (10, 2))
for label, center_pt in enumerate(center_pts):
    for _ in range(100):
        pts.append(center_pt + np.random.randn(*center_pt.shape))
        labels.append(label)

pts = np.stack(pts, axis=0).astype(np.float32)
labels = np.stack(labels, axis=0)

train_ds = tf.data.Dataset.from_tensor_slices((pts, labels)).shuffle(1000).batch(32)

6. Modeling

(1) Model

model = MyModel()

(2) Loss Object & Optimizer

  • Loss Object : spare categorical cross entropy, binary cross entropy..
  • Optimizer : Adam, RMSprop, …
loss_object = tf.keras.losses.SparseCategoricalCrossentropy()
optimizer = tf.keras.optimizers.Adam()

(3) Metric ( loss & accuracy )

train_loss = tf.keras.metrics.Mean(name='train_loss')
train_accuracy = tf.keras.metrics.SparseCategoricalAccuracy(name='train_accuracy')

7. Train

for epoch in range(EPOCHS):
    for x, label in train_ds:
        train_step(model, x, label, loss_object, optimizer, train_loss, train_accuracy)
        
    template = 'Epoch {}, Loss: {}, Accuracy: {}'
    print(template.format(epoch + 1,
                          train_loss.result(),
                          train_accuracy.result() * 100))
    train_loss.reset_states()
    train_accuracy.reset_states()
Epoch 1, Loss: 0.5004048347473145, Accuracy: 85.82125091552734
Epoch 2, Loss: 0.4983041286468506, Accuracy: 85.854736328125
Epoch 3, Loss: 0.49625158309936523, Accuracy: 85.8885498046875
Epoch 4, Loss: 0.49433252215385437, Accuracy: 85.91976165771484
Epoch 5, Loss: 0.49232837557792664, Accuracy: 85.9474868774414
Epoch 6, Loss: 0.49037522077560425, Accuracy: 85.9784927368164
Epoch 7, Loss: 0.4885392487049103, Accuracy: 86.0060806274414
Epoch 8, Loss: 0.48661574721336365, Accuracy: 86.03408813476562
Epoch 9, Loss: 0.4847148656845093, Accuracy: 86.0625
...
Epoch 994, Loss: 0.27788347005844116, Accuracy: 89.2856216430664
Epoch 995, Loss: 0.2778545022010803, Accuracy: 89.28681945800781
Epoch 996, Loss: 0.2778218984603882, Accuracy: 89.287109375
Epoch 997, Loss: 0.277792751789093, Accuracy: 89.28839874267578
Epoch 998, Loss: 0.277757853269577, Accuracy: 89.28913879394531
Epoch 999, Loss: 0.27772510051727295, Accuracy: 89.29024505615234
Epoch 1000, Loss: 0.2776941955089569, Accuracy: 89.29043579101562

8. Save / Load parameters

  • 학습한 모델의 weight를 따로 저장했다가 나중에 (다시 학습할 필요 없게) weight만 따로 불러들일 수 있다.
np.savez_compressed('ch2_dataset.npz', inputs=pts, labels=labels)

W_h, b_h = model.d1.get_weights()
W_o, b_o = model.d2.get_weights()
W_h = np.transpose(W_h)
W_o = np.transpose(W_o)
np.savez_compressed('ch2_parameters.npz',
                    W_h=W_h,
                    b_h=b_h,
                    W_o=W_o,
                    b_o=b_o)