tensorflow: 머신러닝을 효과적으로 하기 위한 파이썬 프레임워크이다. 앞선 글 중에, pytorch 프레임워크, scikit-learn 라이브러리를 다룬 내용이 있으니 먼저 보고 오자!
Tensorflow는 머신러닝/딥러닝을 하기 위한 파이썬 프레임워크이다. 수치적 계산을 그래프로 모델화하며, 기본 계산 단위인 tensor가 그래프를 타고 흐른다. 그래서 tensorflow라고 부른다.
tensorflow 프로그래밍 모델은 operation, kernel, variable, session으로 이루어져 있으며 간략히 각각을 설명하자면, operation은 계산, kernel은 실제로 작업을 수행하는 곳(gpu, cpu) 지정, variable은 값이 변하는 tensor를 담으며, session은 그래프를 실행한다. Tensorflow 외에도 많은 프레임워크가 그렇지만, 자동으로 역전파 계산을 해준다.
Tensorflow에는 다양한 라이브러리가 tf.keras 모듈을 통해 사용 가능하다. 이번에는 정말 기초적인 부분만 다루므로 tf.keras 모듈을 사용한다.
1. MNIST Data 준비하기
import tensorflow as tf
# keras를 통해 dataset 다운로드
data_train, data_test = tf.keras.datasets.mnist.load_data()
# train/test로 데이터 분리
(train_images, train_labels) = data_train
(test_images, test_labels) = data_test
# Numpy를 통한 모양과 type 바꾸기
train_images = train_images.reshape(train_images.shape[0], 28, 28, 1).astype('float32') # param : 총 data 개수, pixel, pixel, gray_map
test_images = test_images.reshape(test_images.shape[0], 28, 28, 1).astype('float32')
train_labels = train_labels.astype('int64')
test_labels = test_labels.astype('int64')
# Normalizing the images to the range of [0., 1.]
train_images /= 255. # 64 bit = 256
test_images /= 255.
print(train_images.shape, train_labels.shape)
print(test_images.shape, test_labels.shape)
출력 결과:
(60000, 28, 28, 1) (60000,) (10000, 28, 28, 1) (10000,)
train 데이터는 60000개, test 데이터는 10000개를 만들었따.
2. 커스텀 모델 만들기
커스텀 모델을 만드는 법은 비교적 간단하다. tf.keras.Model을 부모 class로 받고 순전파 내용을 정의해주면 된다. 각 레이어들은 처음에 생성자 __init__에서 tf.keras.layers 모듈을 통해 정의되고 class의 객체의 attribute이 된다. 순전파는 class안에서 call method 안에서 정의되며, 따라서 객체가 호출될 때 사용된다. 어떠한 모델의 학습 가능한 변수는 model.trainable_variables을 통해 접근 가능하다. Loss Function과 Optimizer도 각각 tf.keras.losses와 tf.keras.optimizers에서 제공되니 굉장히 편리하다.
tf.keras.Model class를 만들 때 input의 shape을 따로 설정할 필요는 없다. input이 처음으로 layer로 전파될 때 매개변수들이 설정된다. tf.keras.layers는 자신의 model 변수를 만들고 갖고 있으며, 존재하는 동안은 같이 묶여 있다. 이 변수를 공유하고 싶다면, 객체 자체를 공유하자.
from tensorflow.keras import Model
# tf.keras 활용
class First_CNN(Model):
def __init__(self):
super(First_CNN, self).__init__()
self.conv1 = tf.keras.layers.Conv2D(32, (3, 3), activation='relu', padding='valid')
self.conv2 = tf.keras.layers.Conv2D(64, (3, 3), activation='relu', padding='valid')
self.conv3 = tf.keras.layers.Conv2D(128, (3, 3), activation='relu', padding='valid')
self.maxpool = tf.keras.layers.MaxPooling2D((2, 2)) # 정보 줄이기
self.flatten = tf.keras.layers.Flatten() # neural network 들어가기 전 벡터로 만들기
self.dense1 = tf.keras.layers.Dense(256, activation='relu') # output 256 인 neural network
self.dense2 = tf.keras.layers.Dense(10, activation='softmax') # output 10 인 neural network
def call(self, x):
# 순전파 과정
x = self.conv1(x)
x = self.maxpool(x)
x = self.conv2(x)
x = self.maxpool(x)
x = self.conv3(x)
x = self.maxpool(x)
x = self.flatten(x)
x = self.dense1(x)
x = self.dense2(x)
return x
# 모델 객체 생성
model = First_CNN()
3. 모델 학습 전 준비 사항
모델이 생성되었으니, optimizer(최적화 알고리즘)과 loss function(손실 함수)를 정의한다. 또한 학습 과정을 기록하기 위해 tf.keras.metrics 모듈을 활용한다.
# 손실 함수 및 최적화 함수 설정
loss_fn = tf.keras.losses.SparseCategoricalCrossentropy()
optimizer = tf.keras.optimizers.Adam() # Adam, sgd, ,... mainly Adam
# 모델의 학습 경과를 알기 위한 지표(metrics)
train_loss = tf.keras.metrics.Mean(name='train_loss')
train_accuracy = tf.keras.metrics.SparseCategoricalAccuracy(name='train_accuracy')
test_loss = tf.keras.metrics.Mean(name='test_loss')
test_accuracy = tf.keras.metrics.SparseCategoricalAccuracy(name='test_accuracy')
4. tf.function을 통해 학습 파이프 라인 구축
# train을 위한 함수 정의
# 어떤 연산이 일어나는 지 보고 최적화 될 수 있는 부분을 최적화. 조금 더 빨라질 수 있음.
@tf.function
def train_step(images, labels):
with tf.GradientTape() as tape: # 역전파를 위해 gradient 기록
predictions = model(images, training=True)
loss = loss_fn(labels, predictions)
gradients = tape.gradient(loss, model.trainable_variables) # 손실 함수를 통한 gradient 계산
optimizer.apply_gradients(zip(gradients, model.trainable_variables)) # gradient update
# metrics (지표)
train_loss(loss)
train_accuracy(labels, predictions)
# test를 위한 함수 정의
@tf.function
def test_step(images, labels):
predictions = model(images, training=False)
loss = loss_fn(labels, predictions)
# metrics (지표)
test_loss(loss)
test_accuracy(labels, predictions)
5. 학습 시작!
batch_size = 100 # 반복 1회당 사용할 데이터 개수
# tf.data를 통해 데이터 준비
train_data = tf.data.Dataset.from_tensor_slices((train_images, train_labels))
train_data = train_ds.shuffle(10000) # 학습을 위한 셔플
train_data = train_ds.batch(batch_size)
test_data = tf.data.Dataset.from_tensor_slices((test_images, test_labels))
test_data = test_ds.batch(batch_size)
EPOCHS = 10 # 반복 횟수
for epoch in range(EPOCHS):
# 매번 반복마다 metrics 재설정
train_loss.reset_states()
train_accuracy.reset_states()
test_loss.reset_states()
test_accuracy.reset_states()
for images, labels in train_data:
train_step(images, labels)
for images, labels in test_data:
test_step(images, labels)
print('Epoch: %02d' % (epoch + 1),
'Loss = {:2.4f}'.format(train_loss.result()),
'Train accuracy = {:2.4f}'.format(train_accuracy.result()),
'Test loss = {:2.4f}'.format(test_loss.result()),
'Test accuracy = {:2.4f}'.format(test_accuracy.result()))
출력 결과:
Epoch: 01 Loss = 0.2890 Train accuracy = 0.9154 Test loss = 0.0954 Test accuracy = 0.9705
Epoch: 02 Loss = 0.0848 Train accuracy = 0.9743 Test loss = 0.0663 Test accuracy = 0.9798
Epoch: 03 Loss = 0.0607 Train accuracy = 0.9816 Test loss = 0.0679 Test accuracy = 0.9781
Epoch: 04 Loss = 0.0469 Train accuracy = 0.9860 Test loss = 0.0461 Test accuracy = 0.9864
Epoch: 05 Loss = 0.0388 Train accuracy = 0.9875 Test loss = 0.0415 Test accuracy = 0.9872
Epoch: 06 Loss = 0.0322 Train accuracy = 0.9900 Test loss = 0.0530 Test accuracy = 0.9834
Epoch: 07 Loss = 0.0283 Train accuracy = 0.9911 Test loss = 0.0455 Test accuracy = 0.9872
Epoch: 08 Loss = 0.0225 Train accuracy = 0.9930 Test loss = 0.0482 Test accuracy = 0.9860
Epoch: 09 Loss = 0.0191 Train accuracy = 0.9940 Test loss = 0.0497 Test accuracy = 0.9846
Epoch: 10 Loss = 0.0164 Train accuracy = 0.9945 Test loss = 0.0539 Test accuracy = 0.9858
6. Keras API를 통한 간단한 모델 구현
위에서 실행한 유사한 과정을 Keras API를 이용하면 간편하게 구현 가능하다. 코드를 보면 이해가 그렇게 어렵지 않으니 코드를 먼저 보자!
models.Sequential()을 먼저 설정한 후에 model.add를 통해 만들고 싶은 layer를 순서대로 넣어주면 된다.
모델 생성이 끝나면 compile을 통해 metrics, loss function, optimizer 등을 parameter로 넘겨주면 된다. 학습은 model.fit을 통해 실행 되며, 간단하게 구현 가능하다!
from tensorflow.keras import layers
# 모델 만들기
model = models.Sequential()
model.add(layers.Conv2D(32, (3,3), activation="relu", padding="valid"))
model.add(layers.MaxPooling2D((2,2)))
model.add(layers.Conv2D(64, (3,3), activation="relu", padding="valid"))
model.add(layers.MaxPooling2D((2,2)))
model.add(layers.Conv2D(128, (3,3), activation="relu", padding="valid"))
model.add(layers.MaxPooling2D((2,2)))
model.add(layers.Flatten())
model.add(layers.Dense(256, activation="relu"))
model.add(layers.Dense(256, activation="softmax"))
# 모델 compile 후 학습 및 테스트
model.compile(optimizer=tf.keras.optimizers.Adam(learning_rate=0.001),
loss=tf.keras.losses.SparseCategoricalCrossentropy(),
metrics=['accuracy'])
model.fit(train_images, train_labels, epochs=10, batch_size=128)
test_loss, test_acc = model.evaluate(test_images, test_labels, verbose=2)
print('Test accuracy:', test_acc)
출력 결과:
Epoch 1/10 469/469 [==============================] - 4s 5ms/step - loss: 0.0234 - accuracy: 0.9923
Epoch 2/10 469/469 [==============================] - 3s 6ms/step - loss: 0.0203 - accuracy: 0.9934
Epoch 3/10 469/469 [==============================] - 2s 5ms/step - loss: 0.0157 - accuracy: 0.9948
Epoch 4/10 469/469 [==============================] - 2s 5ms/step - loss: 0.0123 - accuracy: 0.9960
Epoch 5/10 469/469 [==============================] - 2s 5ms/step - loss: 0.0126 - accuracy: 0.9956
Epoch 6/10 469/469 [==============================] - 2s 5ms/step - loss: 0.0105 - accuracy: 0.9965
Epoch 7/10 469/469 [==============================] - 3s 6ms/step - loss: 0.0105 - accuracy: 0.9963
Epoch 8/10 469/469 [==============================] - 2s 5ms/step - loss: 0.0085 - accuracy: 0.9972
Epoch 9/10 469/469 [==============================] - 2s 5ms/step - loss: 0.0087 - accuracy: 0.9973
Epoch 10/10 469/469 [==============================] - 2s 5ms/step - loss: 0.0089 - accuracy: 0.9970
313/313 - 1s - loss: 0.0584 - accuracy: 0.9872 - 1s/epoch - 3ms/step Test accuracy: 0.9872000217437744