티스토리 뷰

밑바닥부터 시작하는 딥러닝 책을 이용하여 딥러닝의 기본 구조를 공부했습니다.

하지만 numpy만 가지고 사용하기에는 효율이 떨어지기에 tensorflow2를 이용해 간단한 실습을 하겠습니다.

컴파일은 구글 코랩을 이용하였습니다. 구글 코랩에는 기본적으로 tensorflow와 pytorch 모두 지원하기에 엄청 큰 데이터셋을 이용하는 것이 아니라면 아주 훌륭한 도구입니다. (12시간 지나면 세션이 꺼져서 며칠 씩 돌리는 용으로는 부적합....)

 

MNIST는 유명한 손글씨 데이터입니다. 0~9까지 손글씨 데이터를 지원합니다. tensorflow의 keras.datasets 에는 mnist 데이터 파일을 지원합니다. 조금 색다르지만, 간단한 데이터로는 fashion_mnist 도 있습니다. (이 또한 지원)

 

먼저 tensorflow를 가져와야합니다. 나중에 그래프 그릴 것도 생각해 matplot도 가져옵니다.

import tensorflow as tf
import matplotlib.pyplot as plt

mnist 데이터셋을 가져온 뒤, load_data 함수를 이용해 훈련 데이터셋과 시험용 데이터셋으로 구분합니다.

Mnist = tf.keras.datasets.mnist
(x_train, t_train), (x_test, t_test) = Mnist.load_data()

다운이 잘 완료되었습니다.

 

어떻게 생긴 녀석인지 한 번 보겠습니다.

for i in range(9):
  plt.subplot(3,3,i+1)
  plt.tight_layout()
  plt.imshow(x_train[i].reshape(28,28), cmap="gray", interpolation="none")
  plt.title("digit: {}".format(t_train[i]))
  plt.xticks([])
  plt.yticks([])

plt.show()

간단히 처음 9개 데이터만 불러왔습니다.

 

불러온 훈련 데이터 셋과 시험용 데이터 셋을 조금 수정합니다. 

기본적으로 int형이지만, 훈련이 잘 되기 위해 float32로 타입을 변경합니다. 그리고 MNIST에서 원래 해당 픽셀의 값이 0~255의 값으로 구성되어 있기 때문에 계산의 편의를 위해 255로 나누어 줍니다.

또한 keras.layers.Conv2D를 이용하기 위해 형변환을 시킵니다. 기본적으로 훈련데이터셋은 (60000, 28, 28) 이지만, 채널이 1개이므로 (흑백이므로 채널(색) 1개) (60000, 28, 28, 1)로 변환합니다. 

x_train.astype('float32')
x_test.astype('float32')
x_train, x_test = x_train/255, x_test/255
x_train = x_train.reshape(60000,28,28,1)
x_test = x_test.reshape(10000,28,28,1)
print(x_train.shape)
print(t_train.shape)

그 다음으로 계산의 편의를 위해 정답레이블을 원핫 벡터로 변경하겠습니다. (안 해도 괜찮지만, 원-핫 벡터로 변환 또는 확률로 표현하지 않고 원래의 값을 이용하려면 compile의 loss값에 sparse를 붙혀야 한다.)

num_category = 10
t_train = tf.keras.utils.to_categorical(t_train, num_category)
t_test = tf.keras.utils.to_categorical(t_test, num_category)
print(t_train[0])

데이터셋과 정답레이블 모두 원하는데로 잘 바뀌었습니다.

 

이제 CNN 모델을 간단하게 정의하겠습니다.

1. 64개 필터, 커널 사이즈 3 (필터 크기), 활성화는 relu, 패딩은 원래 인풋과 같은 크기를 갖도록 0을 패딩시킵니다. (padding="same"), 입력데이터는 28x28x1 (채널 1개)를 넣는 것입니다. (스트라이드는 default=1 이므로 따로 적지 않았습니다.)

2. 2x2 MaxPooling을 시킵니다.

3. 필터 개수를 128개로 늘리고 나머지는 같습니다.

4. 2x2 MaxPooling을 시킵니다.

5. 25% 확률의 Dropout을 시킵니다.

6. Flatten을 이용해 1D로 바꿉니다. (정답 레이블은 1D이기 때문에)

7. Dense를 이용하여 64개 노드로 만듭니다. (활성화 relu)

8. 50% 확률의 Dropout을 시킵니다.

9. 정답레이블의 원소가 10개이므로 Dense를 이용해 10개의 노드로 만듭니다. 최종 출력이므로 활성화함수는 softmax를 이용합니다. (손실함수로 crossentropy 이용하기 위해)

model = tf.keras.models.Sequential([
              tf.keras.layers.Conv2D(64, 3, activation="relu", padding="same", input_shape=(28,28,1)),
              tf.keras.layers.MaxPool2D(2),
              tf.keras.layers.Conv2D(128, 3, activation="relu", padding="same"),
              tf.keras.layers.MaxPool2D(2),
              tf.keras.layers.Dropout(0.25),
              tf.keras.layers.Flatten(),
              tf.keras.layers.Dense(64, activation="relu"),
              tf.keras.layers.Dropout(0.5),
              tf.keras.layers.Dense(num_category, activation="softmax")
])

입력 시 (28, 28, 1)로 input_shape를 가져오고, 마지막에 softmax를 이용하는 것 외에는 층 구조를 다르게 하거나 필터 수를 바꾸는 등의 작업은 적당히 각자 하면 됩니다. (결과에 차이는 존재)

 

만든 model을 compile 합니다.

model.compile은 손실함수와 기울기 최솟값을 구하기 위한 최적화 함수, 구하고자 하는 metrics 등을 설정할 수 있습니다.

손실함수는 crossentropy, 기울기 최적화는 adam, 구하고자 하는 것은 accuracy를 구하도록 해보겠습니다.

model.compile(loss="categorical_crossentropy", optimizer="adam", metrics=["accuracy"])

 

batch 크기는 128, epoch 크기는 10으로 정하겠습니다. 

그리고 fit 함수를 이용해 학습을 시키면 됩니다. 여기서 검증데이터는 보통 훈련용 데이터의 10% 정도로 사용하지만, 따로 만들지 않고 그냥 시험용 데이터를 검증용 데이터로 사용하겠습니다.

batch_size = 128
num_epoch = 10
History = model.fit(x_train, t_train, 
	batch_size=batch_size, epochs=num_epoch, validation_data=(x_test, t_test))

학습이 아주 잘 되었습니다. 최종적으로 나온 loss 값과 accuracy를 확인해보겠습니다.

score = model.evaluate(x_test, t_test, verbose=0)
print("Test loss = ", score[0])
print("Test accuracy = ", score[1])

최종적으로 정확도는 99% 정도가 되어 잘 학습되었음을 알 수 있습니다. 1%가 모자란 이유는 사람 눈으로 봐도 뭔지 햇갈리는 글씨들이 포함되어 있기 때문입니다.

 

마지막으로 epoch 별로 정확도와 손실의 차이를 그래프로 보겠습니다.

plt.plot(History.history['accuracy'], label="train")
plt.plot(History.history['val_accuracy'], label="test")
plt.xlabel('epoch')
plt.ylabel('accuracy')
plt.legend(loc='lower right')
plt.show()

plt.plot(History.history['loss'], label="train")
plt.plot(History.history['val_loss'], label="test")
plt.xlabel('epoch')
plt.ylabel('accuracy')
plt.legend(loc='lower right')
plt.show()

테스트 데이터를 검증데이터로 사용하여 test 데이터의 결과가 더 좋게 나왔지만, 전체적으로 훈련데이터와 크게 차이가 없습니다. 학습이 잘 되었습니다.

'딥러닝' 카테고리의 다른 글

간단한 RNN, LSTM 모델 설계  (0) 2021.03.11
밑바닥부터 시작하는 딥러닝 2권 후기 및 앞으로 계획  (0) 2021.02.19
기울기 클리핑 / 기본적인 LSTM  (0) 2021.01.29
BPTT  (0) 2021.01.29
네거티브 샘플링  (0) 2021.01.27
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
TAG
more
«   2025/02   »
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28
글 보관함