from IPython.core.display import display, HTML
display(HTML("<style>.container { width:90% !important; }</style>"))
Tensorflow(TF)_V2_API🐍¶
1. WHAT IS TF API??¶
Tensorflow는 V2로 업데이트 되면서 pyTorch가 가진 장점을 가지게되었으며,
keras라는 pyTorch와 유사한 API를 Tensorflow의 표준 API로 삼으면서,
Google이 가진 분산 환경을 다루는 기술력과 결합하여 더욱 향상된 딥러닝 프레임워크로 발전되었다.
Tensorflow(TF) V2 API의 구성상의 개요를 파악하고,
다양하고 깊이 있게 Tensorflow를 이해하고 활용할 수 있는 기본기를 갖추는 시간을 가졌으면 한다.
이를 통해 전문적인 딥러닝 엔지니어로 성장 할 수 있는 계기가 되기를.....
학습 목표¶
- Tensorflow V2의 개요와 특징 파악
- Tensorflow V2의 4가지 주요 API 구성 방식을 이해라고 활용
- GradientTape를 활용해 보고 좀 더 low level의 딥러닝 구현 방식에 대해 이해
2-1. TensorFlow V2 Sequential Model¶
import tensorflow as tf
from tensorflow import keras
model = keras.Sequential()
model.add(__input layer__) # 넣고 싶은 레이어
model.add(__input layer__)
model.add(__input layer__)
model.fit(x, y, epochs=5, batch_size=32)
model = keras.Sequential()
이라고 선한 부분에서 Sequential 모델을 활용하면 쉽게 딥러닝 모델을 쌓을 수 있다.
- 입력부터 출력까지 레이어를 Sequential하게 하나하나
.add
를 이용해서 쌓기만 하면 된다.
- 손쉽게 모델링이 가능하지만 모델의 입력과 출력이 여러 개인 경우에는 적합하지 않는 모델링 방식이다.
- Sequential 모델은 반드시 입력 1가지, 출력 1가지만 가능하다.
2-2. TensorFlow V2 Function API¶
import tensorflow as tf
from tensorflow import keras
imputs = 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)
- Sequential Model 과의 차이점은 keras.Model 을 사용하는 것이다.
- Sequential Model 은 keras.Model 을 상속받아 확장한 것이다.
- 때문에 Functional API 를 활용하면 Sequential Model 보다 더 자유로운 모델링이 가능하다.
What is Functional???
- 함수형으로 모델을 구성
입력과 출력을 규정함으로써 모델 전체를 규정한다는 것
Input 을 규정: Input 은 여러개의 tensor가 될 수 있다.
Output 을 규정: 레이어를 자유롭게 엮어 출력을 규정
Sequentail Model 의 단점은 1개의 입력과 출력만 가능했지만 Functional Api는 다중 입력과 출력을 가지는 모델을 만들 수 있다.
2-3. TensorFlow V2 Subclassing¶
import tensorflow as tf
from tensorflow import keras
class NewModel(keras.Model):
def __init__(self):
super(NewModel, self).__init__()
self.__정의하고자 하는 레이어__()
self.__정의하고자 하는 레이어__()
self.__정의하고자 하는 레이어__()
def call(self, x):
x = self.__정의하고자 하는 레이어__(x)
x = self.__정의하고자 하는 레이어__(x)
x = self.__정의하고자 하는 레이어__(x)
return x
model = NewModel()
model.fit(x, y, epochs=5, batch_size=32)
- Subclassing 은 자유로운 모델링이 가능하다.
- Subclassing 은 Keras.Model 을 상속받은 모델 클래스를 만드는 방법이다.
- keras.Model 은 위의 코드와 같이
__init__()
이라는 메서드 안에서 레이어를 구성 call()
이라는 메서드 안에서 레이어 간에 forward propagation을 구현
- keras.Model 은 위의 코드와 같이
- 본질적으로 Functional 접근과 차이가 없다.
3. Tensorflow V2 API로 모델 작성¶
3-1. MIST - Sequential API 활용¶
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))
# Sequential Model 설계
model = keras.Sequential([
keras.layers.Conv2D(32, 3, activation='relu'), # -----(1)
keras.layers.Conv2D(64, 3, activation='relu'), # -----(2)
keras.layers.Flatten(), # -----(3)
keras.layers.Dense(128, activation='relu'), # -----(4)
keras.layers.Dense(10, activation='softmax') # -----(5)
])
- 32개의 채널을 가지고, 커널의 크기가 3, activation function이 relu인 Conv2D 레이어
- 64개의 채널을 가지고, 커널의 크기가 3, activation function이 relu인 Conv2D 레이어
- Flatten 레이어
- 128개의 아웃풋 노드를 가지고, activation function이 relu인 Fully-Connected Layer(Dense)
- 데이터셋의 클래스 개수에 맞는 아웃풋 노드를 가지고, activation function이 softmax인 Fully-Connected Layer(Dense)
# 모델 학습 설정
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)
3-2. MIST - Functional API 활용¶
Squential API 와 큰 차이는 없지만, 이번에는 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))
# Functional 모델 설계
inputs = keras.Input(shape=(28, 28, 1)) # -----(1)
x = keras.layers.Conv2D(32, 3, activation='relu')(inputs) # -----(2)
x = keras.layers.Conv2D(64, 3, activation='relu')(x) # -----(3)
x = keras.layers.Flatten()(x) # -----(4)
x = keras.layers.Dense(128, activation='relu')(x) # -----(5)
predictions = keras.layers.Dense(10, activation='softmax')(x) # -----(6)
model = keras.Model(inputs=inputs, outputs=predictions)
- (28X28X1) 차원으로 정의된 Input
- 32개의 채널을 가지고, 커널의 크기가 3, activation function이 relu인 Conv2D 레이어
- 64개의 채널을 가지고, 커널의 크기가 3, activation function이 relu인 Conv2D 레이어
- Flatten 레이어
- 128개의 아웃풋 노드를 가지고, activation function이 relu인 Fully-Connected Layer(Dense)
- 데이터셋의 클래스 개수에 맞는 아웃풋 노드를 가지고, activation function이 softmax인 Fully-Connected Layer(Dense)
# 모델 학습 설정
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)
3-3. MIST - Subclassing 활용¶
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
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))
# Subclassing을 활용한 Model 설계
class NewModel(keras.Model): # -----(1)
def __init__(self):
super().__init__()
self.conv1 = keras.layers.Conv2D(32, 3, activation='relu') # -----(2)
self.conv2 = keras.layers.Conv2D(64, 3, activation='relu') # -----(3)
self.flatten = keras.layers.Flatten() # -----(4)
self.fc1 = keras.layers.Dense(128, activation='relu') # -----(5)
self.fc2 = keras.layers.Dense(10, activation='softmax') # -----(6)
def call(self, x): # -----(7)
x = self.conv1(x)
x = self.conv2(x)
x = self.flatten(x)
x = self.fc1(x)
x = self.fc2(x)
return x
model = NewModel()
- keras.Model 을 상속받았으며, init()와 call() 메서드를 가진 모델 클래스
- 32개의 채널을 가지고, 커널의 크기가 3, activation function이 relu인 Conv2D 레이어
- 64개의 채널을 가지고, 커널의 크기가 3, activation function이 relu인 Conv2D 레이어
- Flatten 레이어
- 128개의 아웃풋 노드를 가지고, activation function이 relu인 Fully-Connected Layer(Dense)
- 데이터셋의 클래스 개수에 맞는 아웃풋 노드를 가지고, activation function이 softmax인 Fully-Connected Layer(Dense)
- call의 입력값이 모델의 Input, call의 리턴값이 모델의 Output
# 모델 학습 설정
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)
▶ 위의 3가지 Sequential, Functional, Subclassing 모두 동일한 것임을 알 수 있다.👀👀¶
# 스크래핑 인증서 오류 발생시 아래의 코드로 방지할 수 있다.
import ssl
ssl._create_default_https_context = ssl._create_unverified_context
4-1. CIFAR-100 - Sequential API 활용¶
import tensorflow as tf
from tensorflow import keras
# 데이터 구성부분
cifar100 = tf.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))
# Squential Model 설계
model = keras.Sequential([
keras.layers.Conv2D(16, 3, activation='relu'), # -----(1)
keras.layers.MaxPool2D((2, 2)), # -----(2)
keras.layers.Conv2D(32, 3, activation='relu'), # -----(3)
keras.layers.MaxPool2D((2, 2)), # -----(4)
keras.layers.Flatten(),
keras.layers.Dense(256, activation='relu'), # -----(5)
keras.layers.Dense(100, activation='softmax') # -----(6)
])
- 16개의 채널을 가지고, 커널의 크기가 3, activation function이 relu인 Conv2D 레이어
- pool_size가 2인 MaxPool 레이어
- 32개의 채널을 가지고, 커널의 크기가 3, activation function이 relu인 Conv2D 레이어
- pool_size가 2인 MaxPool 레이어
- 256개의 아웃풋 노드를 가지고, activation function이 relu인 Fully-Connected Layer(Dense)
- 데이터셋의 클래스 개수에 맞는 아웃풋 노드를 가지고, activation function이 softmax인 Fully-Connected Layer(Dense)
# 모델 학습 설정
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)
4-2. CIFAR-100 - Functional API 활용¶
Squential API 와 큰 차이는 없지만, 이번에는 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))
# Functional API를 활용한 Model 설계
inputs = keras.Input(shape=(32, 32, 3))
x = keras.layers.Conv2D(16, 3, activation='relu')(inputs)
x = keras.layers.MaxPool2D((2,2))(x)
x = keras.layers.Conv2D(32, 3, activation='relu')(x)
x = keras.layers.MaxPool2D((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=2)
4-3. CIFAR-100 - Subclassing API 활용¶
Subclassing 은 keras.Model 을 상속받은 클래스를 만드는 것이다.
__init__()
메서드 안에서 레이어를 선언하고, call()
메서드 안에서 forward propagation을 구현하는 방식이다.
Functional 과는 다르게 call()
의 입력이 Input이고, call()
의 return 값이 Output 된다.
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 NewModel(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 = NewModel()
# 모델 학습 설정
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)
5. GradientTape의 활용¶
Automatic differentiation - GradientTape¶
MINST 와 CIFAR-100 테스크 2개를 본질적으로 큰 차이가 없는 3개의 모델 구성 방법을 활용하여 딥러닝으로 구현해보았다.
이 중 동일한 코딩은 아래와 같이 "모델 학습 설정" 부분이였다.
model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
model.fit(x_train, y_train, epochs=5)
👀model.fit()
이라는 한 줄로 수행 가능한 딥러닝 모델 훈련과정을 살펴보자.👀
Forward Propagation 수행 및 중간 레이어값 저장
Loss 값 계산
중간 레이어값 및 Loss를 활용한 체인룰(chain rule) 방식의 역전파(Backward Propagation) 수행
학습 파라미터 업데이트
4단계로 이루어진 train_step 을 여러 번 반복 시행한다.
이렇듯 TF2 API에는 model.fit()
이라는 메서드 안에 모두 코드로 이루어져있다.😃
Tensorflow 에서 제공하는 tf.GradientTape
는
위와 같이 순전파(forward pass)로 진행된 모든 연산의 중간 레이어 값을 tape 에 저장하고,
이를 이용해 gradient를 계산한 후 tap 을 폐기하는 기능을 수행한다.
👀위에서 진행했던 것을 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 NewModel(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 = NewModel()
아직까지는 앞에서 진행한 Subclassing 을 이용한 모델 설계와 다르지 않다.
달라질 부분은 "모델 학습 설정"인 model.compile()
, model.fit()
을 바꿀 것이다.
# 학습 모델 설정
model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
위의 "학습 모델 설정"은 모델 학습을 위해 loss, optimizer 를 지정해 주면
내부적으로 step by step 으로 발생하는 loss 및 gradient가 어떻게 학습 파라미터를
업데이트하게 되는지를지정해 주는 작업이 model.compile()
안에서 자동으로 진행이 되었다.
이제 아래의 코드는 tap.gradient()
를 통해 매번 스텝 학습이 진행될 때마다 발생하는 gradient를 추출한 후
optimizer.apply_gradients()
를 통해 발생한 gradient 가 업데이트해야 할 파라미터
model.trainalbe_variables
를 지정해 주는 과정을 살펴보자.
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
위와 같이 매 스텝 진행되는 학습의 동작이 def train_step()
메서드로 구현하였다.
model.fit(x_train, y_train, epochs=5, batch_size=32)
model.fit()
으로 한 줄로 간단하게 수행했던 실제 배치 학습 과정은,
매 스텝마다 위에서 구현한 def train_step()
가 호출되는 과정으로 바꾼 것이다.
model.fit()
호출 시에는 결정되는 batch_size
만 이번 스텝에서 결정해 주면 된다.
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()
위에서 구현한 def 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
'인공지능' 카테고리의 다른 글
[Part 2]CIFAR-10 을 활용한 이미지 생성기 (0) | 2022.02.16 |
---|---|
[Part 1]CIFAR-10 을 활용한 이미지 생성기 (1) | 2022.02.15 |
[Part 2]인공지능으로 새로운 패션을 만들 수 있다! (0) | 2022.02.11 |
[Part 1]인공지능으로 새로운 패션을 만들 수 있다! (0) | 2022.02.11 |
감성 분석[Emotional analysis] (0) | 2022.01.28 |