이번 시간에는 우리가 사용할 TF V2 API의 구성상 개요를 파악하고, 보다 다양하고 깊이있게 TF를 활용할 기본기를 갖추자.
학습 목표
TensorFlow2를 활용함에 있어 딥러닝 모델을 3가지 방법으로 작성할 수 있다. 경우에 따라 적합한 모델링 방식을 택해서 사용할 수 있다는 점이 장점이다.
딥러닝 모델을 작성하는 방법들에는 Sequential
, Functional
, Model Subclassing
이 있다. Functional
은 Sequential
보다 일반화된 개념이고, Model Subclassing
은 클래스로 구현된 기존 모델을 상속받아 자신만의 모델을 만들어나가는 방식이다.
import tensorflow as tf from tensorflow import keras model = keras.Sequential() model.add(__넣고싶은 레이어__) model.add(__넣고싶은 레이어__) model.add(__넣고싶은 레이어__) model.fit(x, y, epochs=10, batch_size=32)
Sequential 모델을 활용하면 쉽게 딥러닝 모델을 쌓아나갈 수 있다.
import tensorflow as tf from tensorflow import keras inputs = keras.Input(shape=(__원하는 입력값 모양__)) x = keras.layers.__넣고싶은 레이어__(관련 파라미터)(input) x = keras.layers.__넣고싶은 레이어__(관련 파라미터)(x) outputs = keras.layers.__넣고싶은 레이어__(관련 파라미터)(x) model = keras.Model(inputs=inputs, outputs=outputs) model.fit(x,y, epochs=10, batch_size=32)
Keras.Model
을 사용한다는 점이 Sequential Model
을 쓰는 것보다 일반적인 접근이 되게 한다. Functional API
를 활용하면 앞서 배운 Sequential Model
보다 더 자유로운 모델링을 진행할 수 있다.
Funtional
이라는 뜻은: 함수형으로 모델을 구성한다는 것, 즉 입출력을 규정함으로써 모델 전체를 규정한다는 생각이다. 따라서 이번에는 Input
을 규정한다. 그리고 input과 layer들을 엮어 Output
까지 규정하면 된다.
import tensorflow as tf from tensorflow import keras class CustomModel(keras.Model): def __init__(self): super(CustomModel, self).__init__() self.__정의하고자 하는 레이어__() self.__정의하고자 하는 레이어__() self.__정의하고자 하는 레이어__() def call(self, x): x = self.__정의하고자 하는 레이어__(x) x = self.__정의하고자 하는 레이어__(x) x = self.__정의하고자 하는 레이어__(x) return x model = CustomModel() model.fit(x,y, epochs=10, batch_size=32)
Subclassing
을 활용하면 가장 자유로운 모델링이 가능해진다. 본질적으로는 Functional
한 접근과 차이는 없다. 두 방법 모두 keras.Model
을 상속받은 모델 클래스를 만드는 것이기 때문이다. keras.Model
은 __init__()
이라는 메서드 내에서 레이어 구성을 정의한다. 그리고 call()
이라는 메서드 내에서 레이어 간의 forward propagation
을 구현한다. 이것으로 끝이지만, 이는 각 레이어에 대한 깊은 이해를 필요로 하기 때문에 초심자에게 의도치 않은 버그를 유발할 수 있다.
TF2의 다양한 API에 대해 둘러보았다. 이제 이를 활용해서 이미지 문제를 풀어보며 자세하게 이해해보자.
총 2가지 문제를 3가지 API를 활용해 구현할 예정이고, 해당 과정은 최대한 스스로 진행하는 것을 목표로 한다.
첫 번째는 MNIST 문제를 구현해보자.
import tensorflow as tf
from tensorflow import keras
import numpy as np
# 데이터 구성부분
mnist = keras.datasets.mnist
(x_train, y_train), (x_test, y_test) = mnist.load_data()
x_train, x_test = x_train / 255.0, x_test / 255.0
x_train=x_train[...,np.newaxis]
x_test=x_test[...,np.newaxis]
print(len(x_train), len(x_test))
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/mnist.npz
11493376/11490434 [==============================] - 0s 0us/step
11501568/11490434 [==============================] - 0s 0us/step
60000 10000
✔ np.newaxis의 기능: used to increase the dimension of the existing array by one more dimension, when used once.
"numpy.newaxis"는 무엇이고 언제 사용하는가
✔ ...(Ellipsis 객체)을 사용하는 이유: used in numpy to slice higher-dimensional data structures. It's designed to mean at this point, insert as many full slices (:) to extend the multi-dimensional slice to all dimensions.
How do you use the ellipsis slicing syntax in Python?
# Sequential Model을 구성해주세요.
"""
Spec:
1. 32개의 채널을 가지고, 커널의 크기가 3, activation function이 relu인 Conv2D 레이어
2. 64개의 채널을 가지고, 커널의 크기가 3, activation function이 relu인 Conv2D 레이어
3. Flatten 레이어
4. 128개의 아웃풋 노드를 가지고, activation function이 relu인 Fully-Connected Layer(Dense)
5. 데이터셋의 클래스 개수에 맞는 아웃풋 노드를 가지고, activation function이 softmax인 Fully-Connected Layer(Dense)
"""
# 여기에 모델을 구성해주세요
model = keras.Sequential([
keras.layers.Conv2D(32, 3, activation='relu'),
keras.layers.Conv2D(64, 3, activation='relu'),
keras.layers.Flatten(),
keras.layers.Dense(128, activation='relu'),
keras.layers.Dense(10, activation='softmax')
])
# 모델 학습 설정
model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
model.fit(x_train, y_train, epochs=5)
model.evaluate(x_test, y_test, verbose=2)
Epoch 1/5
1875/1875 [==============================] - 26s 3ms/step - loss: 0.1093 - accuracy: 0.9663
Epoch 2/5
1875/1875 [==============================] - 6s 3ms/step - loss: 0.0351 - accuracy: 0.9891
Epoch 3/5
1875/1875 [==============================] - 6s 3ms/step - loss: 0.0194 - accuracy: 0.9935
Epoch 4/5
1875/1875 [==============================] - 6s 3ms/step - loss: 0.0130 - accuracy: 0.9956
Epoch 5/5
1875/1875 [==============================] - 6s 3ms/step - loss: 0.0096 - accuracy: 0.9971
313/313 - 1s - loss: 0.0489 - accuracy: 0.9875
[0.04890325665473938, 0.987500011920929]
이번에는 keras.Model
을 직접 활용해서 keras.Input
으로 정의된 input/output 레이어 구성을 통해 model을 구현하자.
import tensorflow as tf
from tensorflow import keras
import numpy as np
mnist = keras.datasets.mnist
(x_train, y_train), (x_test, y_test) = mnist.load_data()
x_train, x_test = x_train / 255.0, x_test / 255.0
x_train=x_train[...,np.newaxis]
x_test=x_test[...,np.newaxis]
print(len(x_train), len(x_test))
60000 10000
"""
Spec:
0. (28X28X1) 차원으로 정의된 Input
1. 32개의 채널을 가지고, 커널의 크기가 3, activation function이 relu인 Conv2D 레이어
2. 64개의 채널을 가지고, 커널의 크기가 3, activation function이 relu인 Conv2D 레이어
3. Flatten 레이어
4. 128개의 아웃풋 노드를 가지고, activation function이 relu인 Fully-Connected Layer(Dense)
5. 데이터셋의 클래스 개수에 맞는 아웃풋 노드를 가지고, activation function이 softmax인 Fully-Connected Layer(Dense)
"""
# 여기에 모델을 구성해 주세요.
inputs = keras.Input(shape=(28,28,1))
x = keras.layers.Conv2D(32,3, activation = 'relu')(inputs)
x = keras.layers.Conv2D(64,3, activation = 'relu')(x)
x = keras.layers.Flatten()(x)
x = keras.layers.Dense(128, activation='relu')(x)
predictions = keras.layers.Dense(10, activation='softmax')(x)
model = keras.Model(inputs=inputs, outputs=predictions)
# 모델 학습 설정
model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
model.fit(x_train, y_train, epochs=5)
model.evaluate(x_test, y_test, verbose=2)
Epoch 1/5
1875/1875 [==============================] - 7s 3ms/step - loss: 0.1024 - accuracy: 0.9685
Epoch 2/5
1875/1875 [==============================] - 6s 3ms/step - loss: 0.0339 - accuracy: 0.9897
Epoch 3/5
1875/1875 [==============================] - 6s 3ms/step - loss: 0.0197 - accuracy: 0.9938
Epoch 4/5
1875/1875 [==============================] - 7s 3ms/step - loss: 0.0118 - accuracy: 0.9961
Epoch 5/5
1875/1875 [==============================] - 6s 3ms/step - loss: 0.0088 - accuracy: 0.9973
313/313 - 1s - loss: 0.0479 - accuracy: 0.9876
[0.0479215532541275, 0.9876000285148621]
이번 스텝 결과는 이전 스텝과 비교해서 큰 차이가 나지 않음을 확인할 수 있을 것이다.
마지막 SubClassing
방법은 keras.Model
을 상속받은 클래스를 만드는 것이다.
__init__()
메서드 안에서 레이어를 선언하고, call()
메서드 안에서 forward propagation
을 구현하는 방식임을 기억하자.
Functional
방식과 비교하면, call()
의 입력이 Input이고, call()
의 return값이 Output이 되는 것이다.
import tensorflow as tf
from tensorflow import keras
import numpy as np
# 데이터 구성부분
mnist = keras.datasets.mnist
(x_train, y_train), (x_test, y_test) = mnist.load_data()
x_train, x_test = x_train / 255.0, x_test / 255.0
x_train=x_train[...,np.newaxis]
x_test=x_test[...,np.newaxis]
print(len(x_train), len(x_test))
60000 10000
# Subclassing을 활용한 Model을 구성해주세요.
"""
Spec:
0. keras.Model 을 상속받았으며, __init__()와 call() 메서드를 가진 모델 클래스
1. 32개의 채널을 가지고, 커널의 크기가 3, activation function이 relu인 Conv2D 레이어
2. 64개의 채널을 가지고, 커널의 크기가 3, activation function이 relu인 Conv2D 레이어
3. Flatten 레이어
4. 128개의 아웃풋 노드를 가지고, activation function이 relu인 Fully-Connected Layer(Dense)
5. 데이터셋의 클래스 개수에 맞는 아웃풋 노드를 가지고, activation function이 softmax인 Fully-Connected Layer(Dense)
6. call의 입력값이 모델의 Input, call의 리턴값이 모델의 Output
"""
# 여기에 모델을 구성해주세요
class CustomModel(keras.Model):
def __init__(self):
super().__init__()
self.conv1 = keras.layers.Conv2D(32, 3, activation='relu')
self.conv2 = keras.layers.Conv2D(64, 3, activation='relu')
self.flatten = keras.layers.Flatten()
self.fc1 = keras.layers.Dense(128, activation='relu')
self.fc2 = keras.layers.Dense(10, activation='softmax')
def call(self, x):
x = self.conv1(x)
x = self.conv2(x)
x = self.flatten(x)
x = self.fc1(x)
x = self.fc2(x)
return x
model = CustomModel()
# 모델 학습 설정
model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
model.fit(x_train, y_train, epochs=5)
model.evaluate(x_test, y_test, verbose=2)
Epoch 1/5
1875/1875 [==============================] - 7s 3ms/step - loss: 0.1119 - accuracy: 0.9662
Epoch 2/5
1875/1875 [==============================] - 6s 3ms/step - loss: 0.0338 - accuracy: 0.9893
Epoch 3/5
1875/1875 [==============================] - 6s 3ms/step - loss: 0.0199 - accuracy: 0.9934
Epoch 4/5
1875/1875 [==============================] - 6s 3ms/step - loss: 0.0133 - accuracy: 0.9955
Epoch 5/5
1875/1875 [==============================] - 6s 3ms/step - loss: 0.0094 - accuracy: 0.9970
313/313 - 1s - loss: 0.0423 - accuracy: 0.9892
[0.042330220341682434, 0.9891999959945679]
위 3가지 방법 모두 본질적으로는 동일하다!!
먼저, 아래 링크를 방문해 CIFAR-100 문제가 무엇인지 확인해 보자.
import tensorflow as tf
from tensorflow import keras
# 데이터 구성부분
cifar100 = keras.datasets.cifar100
(x_train, y_train), (x_test, y_test) = cifar100.load_data()
x_train, x_test = x_train / 255.0, x_test / 255.0
print(len(x_train), len(x_test))
Downloading data from https://www.cs.toronto.edu/~kriz/cifar-100-python.tar.gz
169009152/169001437 [==============================] - 3s 0us/step
169017344/169001437 [==============================] - 3s 0us/step
50000 10000
# Sequential Model을 구성해주세요.
"""
Spec:
1. 16개의 채널을 가지고, 커널의 크기가 3, activation function이 relu인 Conv2D 레이어
2. pool_size가 2인 MaxPool 레이어
3. 32개의 채널을 가지고, 커널의 크기가 3, activation function이 relu인 Conv2D 레이어
4. pool_size가 2인 MaxPool 레이어
5. 256개의 아웃풋 노드를 가지고, activation function이 relu인 Fully-Connected Layer(Dense)
6. 데이터셋의 클래스 개수에 맞는 아웃풋 노드를 가지고, activation function이 softmax인 Fully-Connected Layer(Dense)
"""
# 여기에 모델을 구성해주세요
model = keras.Sequential([
keras.layers.Conv2D(16, 3, activation='relu'),
keras.layers.MaxPool2D((2,2)),
keras.layers.Conv2D(32, 3, activation='relu'),
keras.layers.MaxPool2D((2,2)),
keras.layers.Flatten(),
keras.layers.Dense(256, activation='relu'),
keras.layers.Dense(100, activation='softmax')
])
model.compile(optimizer = 'adam',
loss = 'sparse_categorical_crossentropy',
metrics=['accuracy'])
model.fit(x_train, y_train, epochs=5)
model.evaluate(x_test, y_test, verbose=1)
Epoch 1/5
1563/1563 [==============================] - 5s 3ms/step - loss: 1.9267 - accuracy: 0.4889
Epoch 2/5
1563/1563 [==============================] - 5s 3ms/step - loss: 1.8034 - accuracy: 0.5165
Epoch 3/5
1563/1563 [==============================] - 5s 3ms/step - loss: 1.6984 - accuracy: 0.5412
Epoch 4/5
1563/1563 [==============================] - 5s 3ms/step - loss: 1.5894 - accuracy: 0.5676
Epoch 5/5
1563/1563 [==============================] - 5s 3ms/step - loss: 1.4942 - accuracy: 0.5865
313/313 [==============================] - 1s 2ms/step - loss: 2.8394 - accuracy: 0.3697
[2.8394346237182617, 0.36970001459121704]
이전 스텝과 차이가 없지만, 이번엔 keras.Model을 직접 활용해야 하므로, keras.Input으로 정의된 Input, Output 레이어 구성을 통해 model을 구현해야 한다.
import tensorflow as tf
from tensorflow import keras
cifar100 = keras.datasets.cifar100
(x_train, y_train), (x_test, y_test) = cifar100.load_data()
x_train, x_test = x_train / 255.0, x_test / 255.0
print(len(x_train), len(x_test))
50000 10000
# Functional API를 활용한 Model을 구성해주세요.
"""
Spec:
0. (32X32X3) 차원으로 정의된 Input
1. 16개의 채널을 가지고, 커널의 크기가 3, activation function이 relu인 Conv2D 레이어
2. pool_size가 2인 MaxPool 레이어
3. 32개의 채널을 가지고, 커널의 크기가 3, activation function이 relu인 Conv2D 레이어
4. pool_size가 2인 MaxPool 레이어
5. 256개의 아웃풋 노드를 가지고, activation function이 relu인 Fully-Connected Layer(Dense)
6. 데이터셋의 클래스 개수에 맞는 아웃풋 노드를 가지고, activation function이 softmax인 Fully-Connected Layer(Dense)
"""
# 여기에 모델을 구성해주세요
inputs = keras.Input(shape=(32,32,3))
x = keras.layers.Conv2D(16, 3, activation='relu')(inputs)
x = keras.layers.MaxPool2D(pool_size=(2,2))(x)
x = keras.layers.Conv2D(32, 3, activation='relu')(x)
x = keras.layers.MaxPool2D(pool_size=(2,2))(x)
x = keras.layers.Flatten()(x)
x = keras.layers.Dense(256, activation='relu')(x)
predictions = keras.layers.Dense(100, activation='softmax')(x)
model = keras.Model(inputs = inputs, outputs = predictions)
model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy']
)
model.fit(x_train, y_train, epochs=5)
model.evaluate(x_test, y_test, verbose=1)
Epoch 1/5
1563/1563 [==============================] - 5s 3ms/step - loss: 2.9193 - accuracy: 0.2801
Epoch 2/5
1563/1563 [==============================] - 5s 3ms/step - loss: 2.6502 - accuracy: 0.3338
Epoch 3/5
1563/1563 [==============================] - 5s 3ms/step - loss: 2.4510 - accuracy: 0.3743
Epoch 4/5
1563/1563 [==============================] - 5s 3ms/step - loss: 2.2922 - accuracy: 0.4084
Epoch 5/5
1563/1563 [==============================] - 5s 3ms/step - loss: 2.1514 - accuracy: 0.4399
313/313 [==============================] - 1s 2ms/step - loss: 2.6098 - accuracy: 0.3559
[2.6097517013549805, 0.35589998960494995]
keras.Model을 상속받은 클래스를 만드는 것이다. 여전히 정확도는 40% 미만일텐데, 이번엔 Subclassing과 함께, 딥러닝 기법을 다양하게 적용해보자.
import tensorflow as tf
from tensorflow import keras
# 데이터 구성부분
cifar100 = keras.datasets.cifar100
(x_train, y_train), (x_test, y_test) = cifar100.load_data()
x_train, x_test = x_train / 255.0, x_test / 255.0
print(len(x_train), len(x_test))
50000 10000
# Subclassing을 활용한 Model을 구성해주세요.
"""
Spec:
0. keras.Model 을 상속받았으며, __init__()와 call() 메서드를 가진 모델 클래스
1. 16개의 채널을 가지고, 커널의 크기가 3, activation function이 relu인 Conv2D 레이어
2. pool_size가 2인 MaxPool 레이어
3. 32개의 채널을 가지고, 커널의 크기가 3, activation function이 relu인 Conv2D 레이어
4. pool_size가 2인 MaxPool 레이어
5. 256개의 아웃풋 노드를 가지고, activation function이 relu인 Fully-Connected Layer(Dense)
6. 데이터셋의 클래스 개수에 맞는 아웃풋 노드를 가지고, activation function이 softmax인 Fully-Connected Layer(Dense)
7. call의 입력값이 모델의 Input, call의 리턴값이 모델의 Output
"""
# 여기에 모델을 구성해주세요
class CustomModel(keras.Model):
def __init__(self):
super().__init__()
self.conv1 = keras.layers.Conv2D(16, 3, activation='relu')
self.pool1 = keras.layers.MaxPool2D((2,2))
self.conv2 = keras.layers.Conv2D(32, 3, activation='relu')
self.pool2 = keras.layers.MaxPool2D((2,2))
self.flatten = keras.layers.Flatten()
self.fc1 = keras.layers.Dense(256, activation='relu')
self.fc2 = keras.layers.Dense(100, activation='softmax')
def call(self, x):
x= self.conv1(x)
x= self.pool1(x)
x= self.conv2(x)
x= self.pool2(x)
x= self.flatten(x)
x= self.fc1(x)
x= self.fc2(x)
return x
model = CustomModel()
model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
model.fit(x_train, y_train, epochs=5)
model.evaluate(x_test, y_test, verbose=2)
Epoch 1/5
1563/1563 [==============================] - 5s 3ms/step - loss: 3.5767 - accuracy: 0.1630
Epoch 2/5
1563/1563 [==============================] - 5s 3ms/step - loss: 2.8711 - accuracy: 0.2893
Epoch 3/5
1563/1563 [==============================] - 5s 3ms/step - loss: 2.5653 - accuracy: 0.3523
Epoch 4/5
1563/1563 [==============================] - 5s 3ms/step - loss: 2.3550 - accuracy: 0.3989
Epoch 5/5
1563/1563 [==============================] - 5s 3ms/step - loss: 2.1705 - accuracy: 0.4346
313/313 - 1s - loss: 2.5499 - accuracy: 0.3658
[2.5498905181884766, 0.36579999327659607]
우리는 좀전까지 아주 비슷한 테스크 2개, 본질적으로 큰 차이가 없는 3개의 모델 구성방법을 활용해 딥러닝으로 구현해보았다.
그동안 동일하게 구성된 부분은 바로 아래 부분이다.
#모델 학습 설정 model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy']) model.fit(x_train, y_train, epochs=5)
Numpy만 가지고 딥러닝을 구현하는 것을 회상해보자. model.fit()이라는 한 줄의 딥러닝 모델 훈련과정은 실제로 어땠는가??
위 4단계의 train_step을 반복했다. 이 과정은 TF2 API에는 model.fit()
이라는 메서드 하나에 모두 추상화되어 있다.
TF에서 제공하는 tf.GradientTape
는 순전파로 진행된 모든 연산의 중간 레이어 값을 tape에 기록하고, 이를 이용해 gradient를 계산한 후 tape를 폐기하는 기능을 수행한다. 이번엔 이전 스텝에서 진행한 학습을 tf.GradientTape
를 이용한 것으로 변형해보자. tf.GradientTape
는 이후 그래디언트를 좀더 고급스럽게 활용하는 여러 기법을 통해 만날 게 될 것이다.
# 앞부분과 동일
import tensorflow as tf
from tensorflow import keras
# 데이터 구성부분
cifar100 = keras.datasets.cifar100
(x_train, y_train), (x_test, y_test) = cifar100.load_data()
x_train, x_test = x_train / 255.0, x_test / 255.0
print(len(x_train), len(x_test))
# 모델 구성부분
class CustomModel(keras.Model):
def __init__(self):
super().__init__()
self.conv1 = keras.layers.Conv2D(16, 3, activation='relu')
self.maxpool1 = keras.layers.MaxPool2D((2,2))
self.conv2 = keras.layers.Conv2D(32, 3, activation='relu')
self.maxpool2 = keras.layers.MaxPool2D((2,2))
self.flatten = keras.layers.Flatten()
self.fc1 = keras.layers.Dense(256, activation='relu')
self.fc2 = keras.layers.Dense(100, activation='softmax')
def call(self, x):
x = self.conv1(x)
x = self.maxpool1(x)
x = self.conv2(x)
x = self.maxpool2(x)
x = self.flatten(x)
x = self.fc1(x)
x = self.fc2(x)
return x
model = CustomModel()
50000 10000
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])
위와 같이 학습을 진행하면 내부적으로는 매 스텝 학습이 진행될 때마다 발생하는 loss및 그래디언트가 어떻게 학습 파라미터를 업데이트하게 되는지를 지정해주는 작업이 model.compile()
에서 자동으로 진행되었다.
아래 코드는 tape.gradient()
를 통해 매 스텝 학습이 진행될 때마다 발생하는 그래디언트를 추출한 후 optimizer.apply_gradients()
를 통해 발생한 그래디언트가 업데이터해야 할 파라미터 model.trainable_variables
를 지정해주는 과정을 기술한 것이다.
# 매 스텝 진행되는 학습의 실제 동작을 train_step으로 구현하기
loss_func = tf.keras.losses.SparseCategoricalCrossentropy()
optimizer = tf.keras.optimizers.Adam()
# tf.GradientTape()를 활용한 train_step
def train_step(features, labels):
with tf.GradientTape() as tape:
predictions = model(features)
loss = loss_func(labels, predictions)
gradients = tape.gradient(loss, model.trainable_variables)
optimizer.apply_gradients(zip(gradients, model.trainable_variables))
return loss
model.fit(x_train, y_train, epochs=5, batch_size=32)
이렇게 진행된 배치 학습 과정은, 매 스텝마다 train_step()
가 호출되는 과정으로 바꾸어 구현할 수 있다.
model.fit()
호출 시에 결정되는 batch_size만 결정해 주면 된다.
# fit
import time
def train_model(batch_size=32):
start = time.time()
for epoch in range(5):
x_batch = []
y_batch = []
for step, (x, y) in enumerate(zip(x_train, y_train)):
x_batch.append(x)
y_batch.append(y)
if step % batch_size == batch_size-1:
loss = train_step(np.array(x_batch, dtype=np.float32), np.array(y_batch, dtype=np.float32))
x_batch = []
y_batch = []
print('Epoch %d: last batch loss = %.4f' % (epoch, float(loss)))
print("It took {} seconds".format(time.time() - start))
train_model()
Epoch 0: last batch loss = 3.3150
Epoch 1: last batch loss = 3.0266
Epoch 2: last batch loss = 2.9100
Epoch 3: last batch loss = 2.7622
Epoch 4: last batch loss = 2.5931
It took 77.00022721290588 seconds
위에서 구현한 train_model()
메서드가 model.fit()
메서드와 기능적으로 같댜는 게 확인될 것이다!!
이렇듯 tf.GradientTape()
를 활용하면 model.compile()
과 model.fit()
안에 있던 한 스텝의 학습 단계를 끄집어내서 원하는 대로 재구성할 수 있게 된다. 그동안 다뤄왔던 지도학습 방식과 다른 강화학습/Gan의 학습을 위해서는 train_step
메서드의 재구성이 필수이므로 tf.GradientTape()
의 활용법을 꼭 숙지해야한다!!!
# evaluation
prediction = model.predict(x_test, batch_size=x_test.shape[0], verbose=1)
temp = sum(np.squeeze(y_test) == np.argmax(prediction, axis=1))
temp/len(y_test) # Accuracy
1/1 [==============================] - 1s 848ms/step
0.3399
그래디언트를 활용할 필요가 없는 evaluation 단계는 predict 메서드를 활용해보았다.