Google에서 만든 딥러닝 프레임워크인 TensorFlow를 활용해서 CNN 모델인 AlexNet과 VGGNet을 만들고 학습시킬 예정이다. 우리가 사용할 데이터셋은 MNIST이다.
본격적인 미션에 앞서 먼저 MNIST에 대해 알아보도록 하자.
MNIST는 0부터 9까지 숫자 손글씨로 이루어진 데이터셋으로 되어 있다.
28X28사이즈의 60000의 훈련 데이터와 10000개의 테스트 데이터로 구성되어 있다.
x_train.shape == (60000, 28, 28)
x_test.shape == (10000, 28, 28)
y_train.shape == (60000,)
y_test.shape == (10000,)
# 인공지능 학습에 필요한 라이브러리 tensorflow 설치
# 코랩환경에서 불필요
'''
!pip install tensorflow
!pip install numpy
!pip install matplotlib
'''
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
mnist = tf.keras.datasets.mnist
(train_images, train_labels), (test_images, test_labels) = mnist.load_data()
train_images[2025]
train_labels[2025]
plt.imshow(train_images[1033],cmap='gray')
print(train_labels[1033],'입니다.')
np.min(train_images), np.max(train_images)
train_images = train_images / 255.0
test_images = test_images / 255.0
print('최소값:',np.min(train_images))
print('최대값:',np.max(train_images))
input_shape = (4, 28, 28, 3)
x = tf.random.normal(input_shape)
# 3x3 필터 2개 사용, ReLU 활성화 적용 2D 합성곱층
y = tf.keras.layers.Conv2D(filters=2, kernel_size=3, activation='relu')(x)
print(y.shape)
input_shape = (4, 28, 28, 3)
x = tf.random.normal(input_shape)
# 2x2 필터 2개 사용, ReLU 활성화 적용 2D 합성곱층
y = tf.keras.layers.Conv2D(filters=2, kernel_size=2, activation='relu')(x)
print(y.shape)
input_shape = (4, 28, 28, 3)
x = tf.random.normal(input_shape)
# 3x3 필터 2개 사용, 스텝사이즈 2, ReLU 활성화 적용 2D 합성곱층
y = tf.keras.layers.Conv2D(filters = 2, kernel_size = 3, activation = 'relu')(x)
print(y.shape)
input_shape = (4, 28, 28, 3)
x = tf.random.normal(input_shape)
# 3x3 필터 2개 사용, 스텝사이즈 2, ReLU 활성화 적용 2D 합성곱층
y = tf.keras.layers.Conv2D(filters = 2, kernel_size = 3, strides = 2, activation = 'relu')(x)
print(y.shape)
input_shape = (4, 28, 28, 3)
x = tf.random.normal(input_shape)
# 3x3 필터 2개 사용, 패딩 적용, ReLU 활성화 적용 2D 합성곱층
y = tf.keras.layers.Conv2D(filters = 2, kernel_size = 3, activation = 'relu', padding = 'same')(x)
print(y.shape)
AlexNet
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import (
Input, Resizing, Conv2D, MaxPooling2D, Flatten, Dense, Dropout
)
# 모델 아키텍처 정의
def build_alexnet_light_mnist(input_shape=(28,28,1), num_classes=10):
model = Sequential([
# 입력층
Input(shape=(28,28,1)),
Resizing(227,227),
# 합성곱층 * 5
Conv2D(filters = 48, kernel_size = 11, strides = 4, activation = 'relu'),
MaxPooling2D(pool_size = 3, strides = 2),
Conv2D(128, 5, padding = 'same', activation = 'relu'),
MaxPooling2D(pool_size = 3, strides = 2),
Conv2D(192, 3, padding = 'same', activation = 'relu'),
Conv2D(192, 3, padding = 'same', activation = 'relu'),
Conv2D(128, 3, padding = 'same', activation = 'relu'),
MaxPooling2D(pool_size = 3, strides = 2),
# 분배층
Flatten(),
Dense(512, activation = 'relu'),
Dropout(0.5),
Dense(512, activation = 'relu'),
Dropout(0.5),
# 출력층
Dense(10, activation = 'softmax')
])
return model
model = build_alexnet_light_mnist()
model.summary()
케라스 모델을 학습하기 전에,
model.compile(optimizer = 'adam',
loss = tf.keras.losses.SparseCategoricalCrossentropy(from_logits=False),
metrics = ['accuracy'],
)
model.fit(train_images, train_labels, epochs = 5)
test_loss, test_acc = model.evaluate(test_images, test_labels, verbose=2)
print('테스트 loss:', test_loss, '테스트 정확도:', test_acc)
predictions = model.predict(test_images)
num_rows = 3
num_cols = 3
num_images = num_rows * num_cols
plt.figure(figsize=(2*num_cols, 2*num_rows))
for i in range(num_images):
plt.subplot(num_rows, num_cols, i+1)
plt.imshow(test_images[i], cmap=plt.cm.binary)
plt.xticks([])
plt.yticks([])
predicted_label = np.argmax(predictions[i])
true_label = test_labels[i]
if predicted_label == true_label:
color = 'green'
else:
color = 'red'
plt.xlabel("{} ({})".format(predicted_label, true_label), color=color)
plt.show()
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import (
Input, Resizing, Conv2D, MaxPooling2D, Flatten,
Dense, Dropout, GlobalAveragePooling2D
)
# 경량 버전
def build_vgg16_mnist_light(input_shape=(28,28,1), num_classes=10):
m = Sequential([
Input(shape=input_shape),
Resizing(224, 224),
Conv2D(32, 3, padding='same', activation='relu'),
Conv2D(32, 3, padding='same', activation='relu'),
MaxPooling2D(2),
Conv2D(64, 3, padding='same', activation='relu'),
Conv2D(64, 3, padding='same', activation='relu'),
MaxPooling2D(2),
Conv2D(128, 3, padding='same', activation='relu'),
Conv2D(128, 3, padding='same', activation='relu'),
Conv2D(128, 3, padding='same', activation='relu'),
MaxPooling2D(2),
Conv2D(256, 3, padding='same', activation='relu'),
Conv2D(256, 3, padding='same', activation='relu'),
Conv2D(256, 3, padding='same', activation='relu'),
MaxPooling2D(2),
Conv2D(256, 3, padding='same', activation='relu'),
Conv2D(256, 3, padding='same', activation='relu'),
Conv2D(256, 3, padding='same', activation='relu'),
MaxPooling2D(2),
# Flatten 대신 GAP로 파라미터 크게 절감
GlobalAveragePooling2D(),
Dense(256, activation='relu'),
Dropout(0.5),
Dense(num_classes, activation='softmax'),
])
return m
model = build_vgg16_mnist_light()
model.summary()
model.compile(optimizer='adam',
loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=False),
metrics=['accuracy'])
model.fit(train_images, train_labels, epochs=5)
test_loss, test_acc = model.evaluate(test_images, test_labels, verbose=2)
print('테스트 loss:', test_loss, '테스트 정확도:', test_acc)
#Keras/TensorFlow Applications로 제공되는 VGG16, VGG19
from keras.applications import VGG16, VGG19
from keras.applications.vgg16 import preprocess_input
from keras import layers, models
import tensorflow as tf
# MNIST 흑백 → RGB 3채널 + 224 리사이즈
inputs = layers.Input((28,28,1))
x = layers.Resizing(224, 224)(inputs)
x = tf.image.grayscale_to_rgb(x) # (H,W,3)
# ① 사전학습 사용 + 내가 만든 분류기
base = VGG16(weights='imagenet', include_top=False, input_tensor=x)
base.trainable = False
x = layers.GlobalAveragePooling2D()(base.output)
outputs = layers.Dense(10, activation='softmax')(x)
model = models.Model(inputs, outputs)