인공지능 응용 공학

Colab에서 CNN을 사용한 CIFAR10 이미지 인식 Keras 코드 작성

coding art 2023. 1. 23. 10:30
728x90

MNIST 수기문자 이미지는 텍스트가 아니라 흑백 이미지이다. 일종의 흑백 상형문자로 보고 학습하는 것이다. tensorflow.keras를 사용한 MNIST cnn 알고리듬은 일반적인 컬러 이미지에 대한 학습이 가능하도록 알고리듬을 조금 수정하도록 하자.

 

참조: Convolutional Neural Network(CNN)

https://www.tensorflow.org/tutorials/images/cnn

 

MNIST 수기문자 판독의 경우 Keras 전용 데이터세트를 다운로드하여 사용했듯이 이미지 판독의 경우에도 이와 유사하게 준비된 CIFAR10 데이터 세트를 이용하자. MNIST와는 조금 다르게 10종의 50,000개의 학습용 이미지와 검증 테스트용 10,000개 컬러 이미지로 구성된다.

MNIST cnn 흑백 이미지의 shape(28,28,1)이며 마지막 값을 채널(channel) 값이 1 임에 유의하자. 컬러 섹상 이미지의 경우 이 채널 값이 3으로 설정된다.

 

컬러 이미지 처리 코드가 MNIST 처리 코드와 얼마나 유사한지 살펴보자. 아울러 이 코드도 Colab에서 반드시 하드웨어 가속기 GPU를 설정하고 실행시켜 보기 바란다.

 

tensorflow.keras를 상속하는 datasets, layers, modles, losses 라이브러리를 선언한다. 이들은 tensorflow.keras에서 제공하는 메서드(method)이다. 이 선언을 사용하면 tf.keras.layers.⦁⦁⦁를 간단하게 layers.⦁⦁⦁로 쓸 수 있는 장점이 있다. 아울러 그래프 작도를 지원하기 위해 matplotlib.pyplot을 약어 plt로 두자.

1 import tensorflow as tf
print("TensorFlow version:", tf.__version__)
from tensorflow.keras import datasets, layers, models, losses
import matplotlib.pyplot as plt

Kerasclassdatasets.cifar10의 메서드인 load_data()를 사용하여 60,000개의 이미지 학습 데이터와 10,000개의 검증용 테스트 데이터를 업로딩 하여 255.0으로 나누어 정규화 하자. MNIST 변수명 x_traintrain_images, 정답 라벨 값인 y_traintarin_labels로 변경하였다. 읽은 후 정규화하도록 한다.

2 (train_images, train_labels), (test_images, test_labels) = datasets.cifar10.load_data()
# Normalize pixel values to be between 0 and 1
train_images, test_images = train_images / 255.0, test_images / 255.0

머신러닝 이전에 읽어들인 10종의 이미지에 무엇이 들어 있는지 출력해서 확인해 보자.

5X5 로 구성된 이미지 출력을 볼 수 있다.

3 class_names = ['airplane', 'automobile', 'bird', 'cat', 'deer',
'dog', 'frog', 'horse', 'ship', 'truck']
plt.figure(figsize=(10,10))
for i in range(25):
plt.subplot(5,5,i+1) ; plt.xticks([]) ; plt.yticks([]) ; plt.grid(False)
plt.imshow(train_images[i])
plt.xlabel(class_names[train_labels[i][0]])
plt.show()

이미지 입력 데이터의 shape을 살펴보자. 32X32 크기의 컬러이므로 채널값이 3이며 총 50,000개이다. MNIST 정답 라벨값의 경우 (60000,) shape이 일차원적이다. 반면에 CIFAR10에서는 shape 값이 하나 더 있는 2차원 구조이다. 따라서 (50,000,1)0~4999번까지 50,000개의 리스트 데이터 각각에 추가된 1차원에 class_names에 나열된 이미지 종류를 지정할 수 있게 된다. 2차원 어레이 3번 항의 train_labels[i][0]를 참고하자.

 

4 print(train_images.shape)
print(train_labels.shape)
print(test_images.shape)
(50000, 32, 32, 3)
(50000, 1)
(10000, 32, 32, 3)

 

input_shape MNIST(28,28,1)에서 CIFAR10(32,32,3) 으로 변경된다..

파라메터 수는 896 = 9(필터의 성분수)X32(필터수)X3(채널수) + 32(편향수) 으로 계산 된다.

첫 번째 Conv2D 작업에서 valid 조건으로 작업 후 shpae=(30,30,3)이 된다.

pooling 작업 후 이미지 크기는 30X30에서 15X15로 줄어든다.

2번째 은닉층에서의 필터수는 64개로 2배 증가시킨다. 2번째 Conv2D에서는 padding 에 대한 언급이 없으므로 Defaultpadding=’valid’ 로 처리되어, 15X1513X13으로 처리되며, pooling 작업을 실행하면 6X6 이 얻어진다.

학습과제: 가로 세로 홀수 shape인 경우에 Max Pooling 작업이 어떻게 진행되는지 근거를 검색해 보자.

3번째 은닉층 필터수는 128개이며, Conv2D 처리결과는 4X4가 된다.

4X4에서 2X2 pooling을 하면 결국 2X2가 얻어진다.

5 model = models.Sequential()
model.add(layers.Conv2D(filters=32, kernel_size=(3, 3), activation='relu', padding='same',input_shape=(32, 32, 3)))
model.add(layers.MaxPooling2D(pool_size=(2, 2)))
model.add(layers.Conv2D(64, (3, 3), activation='relu'))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Conv2D(128, (3, 3), activation='relu'))
model.add(layers.MaxPooling2D((2, 2)))
model.summary()

필터수 128개의 shape(2,2)인 신경망을 Flatten() 명령을 사용하여 일차원 신경망 shape(1024,) 로 변환하자.

Dense를 사용하여 1024->256->10으로 줄인다. 10CIFAT10 이미지의 종류수이다.

Dropout을 적용하여 Overfitting을 방지한다.

model.summary()를 실행하면 업데이트 된 전체 신경망 구조를 볼 수 있다.

6 model.add(layers.Flatten())
model.add(layers.Dense(256, activation='relu'))
model.add(layers.Dropout(0.2))
model.add(layers.Dense(10))
model.summary()

아래 그림에서 업데이트 된 신경망 부분을 살펴보자.

신경망이 완료되었으면 옵티마이저와 Cost 함수 그리고 인식률 척도 metric을 설정하자.

여기까지가 텐서플로우 graph 단계에 해당한다고 보면 된다.

7 model.compile(optimizer='adam',
loss=losses.SparseCategoricalCrossentropy(from_logits=True),
metrics=['accuracy'])

하이퍼 파라메터 epochs = 5 로 학습을 시키자.

8 history = model.fit(train_images, train_labels, epochs=10,
validation_data=(test_images, test_labels))

학습 결과 인식률이 0.863이 얻어진다. MNIST 흑백 이미지 보다 학습이 어렵다고 볼 수 있다. 이때 얻은 가중치를 사용하여 검증용 데이터의 인식율은 0.71 수준이다.

학습 결과 인식률 수렴 상황을 그래프로 작도해 보자.

9 plt.plot(history.history['accuracy'], label='accuracy')
plt.plot(history.history['val_accuracy'], label = 'val_accuracy')
plt.xlabel('Epoch')
plt.ylabel('Accuracy')
plt.ylim([0.5, 1])
plt.legend(loc='lower right')


test_loss, test_acc = model.evaluate(test_images, test_labels, verbose=2)



검증용 테스트 데이터의 인식률을 출력해 보자.

10 print(test_acc) 0.7178999781608582

직접 셀별로 타이핑 하든지 아니면 블로그에서 첨부된 코드를 다운받아 실행해 보자.

kerascnncifar.ipynb

 

 

참조: Convolutional Neural Network(CNN)

https://www.tensorflow.org/tutorials/images/cnn

 

MNIST 수기문자 판독의 경우 Keras 전용 데이터세트를 다운로드하여 사용했듯이 이미지 판독의 경우에도 이와 유사하게 준비된 CIFAR10 데이터 세트를 이용하자. MNIST와는 조금 다르게 10종의 50,000개의 학습용 이미지와 검증 테스트용 10,000개 컬러 이미지로 구성된다.

MNIST cnn 흑백 이미지의 shape(28,28,1)이며 마지막 값을 채널(channel) 값이 1 임에 유의하자. 컬러 섹상 이미지의 경우 이 채널 값이 3으로 설정된다.

 

컬러 이미지 처리 코드가 MNIST 처리 코드와 얼마나 유사한지 살펴보자. 아울러 이 코드도 Colab에서 반드시 하드웨어 가속기 GPU를 설정하고 실행시켜 보기 바란다.

 

tensorflow.keras를 상속하는 datasets, layers, modles, losses 라이브러리를 선언한다. 이들은 tensorflow.keras에서 제공하는 메서드(method)이다. 이 선언을 사용하면 tf.keras.layers.⦁⦁⦁를 간단하게 layers.⦁⦁⦁로 쓸 수 있는 장점이 있다. 아울러 그래프 작도를 지원하기 위해 matplotlib.pyplot을 약어 plt로 두자.

1 import tensorflow as tf
print("TensorFlow version:", tf.__version__)
from tensorflow.keras import datasets, layers, models, losses
import matplotlib.pyplot as plt

Kerasclassdatasets.cifar10의 메서드인 load_data()를 사용하여 60,000개의 이미지 학습 데이터와 10,000개의 검증용 테스트 데이터를 업로딩 하여 255.0으로 나누어 정규화 하자. MNIST 변수명 x_traintrain_images, 정답 라벨 값인 y_traintarin_labels로 변경하였다. 읽은 후 정규화하도록 한다.

2 (train_images, train_labels), (test_images, test_labels) = datasets.cifar10.load_data()
# Normalize pixel values to be between 0 and 1
train_images, test_images = train_images / 255.0, test_images / 255.0

머신러닝 이전에 읽어들인 10종의 이미지에 무엇이 들어 있는지 출력해서 확인해 보자.

5X5 로 구성된 이미지 출력을 볼 수 있다.

3 class_names = ['airplane', 'automobile', 'bird', 'cat', 'deer',
'dog', 'frog', 'horse', 'ship', 'truck']
plt.figure(figsize=(10,10))
for i in range(25):
plt.subplot(5,5,i+1) ; plt.xticks([]) ; plt.yticks([]) ; plt.grid(False)
plt.imshow(train_images[i])
plt.xlabel(class_names[train_labels[i][0]])
plt.show()

이미지 입력 데이터의 shape을 살펴보자. 32X32 크기의 컬러이므로 채널값이 3이며 총 50,000개이다. MNIST 정답 라벨값의 경우 (60000,) shape이 일차원적이다. 반면에 CIFAR10에서는 shape 값이 하나 더 있는 2차원 구조이다. 따라서 (50,000,1)0~4999번까지 50,000개의 리스트 데이터 각각에 추가된 1차원에 class_names에 나열된 이미지 종류를 지정할 수 있게 된다. 2차원 어레이 3번 항의 train_labels[i][0]를 참고하자.

 

4 print(train_images.shape)
print(train_labels.shape)
print(test_images.shape)
(50000, 32, 32, 3)
(50000, 1)
(10000, 32, 32, 3)

 

input_shape MNIST(28,28,1)에서 CIFAR10(32,32,3) 으로 변경된다..

파라메터 수는 896 = 9(필터의 성분수)X32(필터수)X3(채널수) + 32(편향수) 으로 계산 된다.

첫 번째 Conv2D 작업에서 valid 조건으로 작업 후 shpae=(30,30,3)이 된다.

pooling 작업 후 이미지 크기는 30X30에서 15X15로 줄어든다.

2번째 은닉층에서의 필터수는 64개로 2배 증가시킨다. 2번째 Conv2D에서는 padding 에 대한 언급이 없으므로 Defaultpadding=’valid’ 로 처리되어, 15X1513X13으로 처리되며, pooling 작업을 실행하면 6X6 이 얻어진다.

학습과제: 가로 세로 홀수 shape인 경우에 Max Pooling 작업이 어떻게 진행되는지 근거를 검색해 보자.

3번째 은닉층 필터수는 128개이며, Conv2D 처리결과는 4X4가 된다.

4X4에서 2X2 pooling을 하면 결국 2X2가 얻어진다.

5 model = models.Sequential()
model.add(layers.Conv2D(filters=32, kernel_size=(3, 3), activation='relu', padding='same',input_shape=(32, 32, 3)))
model.add(layers.MaxPooling2D(pool_size=(2, 2)))
model.add(layers.Conv2D(64, (3, 3), activation='relu'))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Conv2D(128, (3, 3), activation='relu'))
model.add(layers.MaxPooling2D((2, 2)))
model.summary()

필터수 128개의 shape(2,2)인 신경망을 Flatten() 명령을 사용하여 일차원 신경망 shape(1024,) 로 변환하자.

Dense를 사용하여 1024->256->10으로 줄인다. 10CIFAT10 이미지의 종류수이다.

Dropout을 적용하여 Overfitting을 방지한다.

model.summary()를 실행하면 업데이트 된 전체 신경망 구조를 볼 수 있다.

6 model.add(layers.Flatten())
model.add(layers.Dense(256, activation='relu'))
model.add(layers.Dropout(0.2))
model.add(layers.Dense(10))
model.summary()

아래 그림에서 업데이트 된 신경망 부분을 살펴보자.

 

신경망이 완료되었으면 옵티마이저와 Cost 함수 그리고 인식률 척도 metric을 설정하자.

여기까지가 텐서플로우 graph 단계에 해당한다고 보면 된다.

7 model.compile(optimizer='adam',
loss=losses.SparseCategoricalCrossentropy(from_logits=True),
metrics=['accuracy'])

하이퍼 파라메터 epochs = 5 로 학습을 시키자.

8 history = model.fit(train_images, train_labels, epochs=10,
validation_data=(test_images, test_labels))

학습 결과 인식률이 0.863이 얻어진다. MNIST 흑백 이미지 보다 학습이 어렵다고 볼 수 있다. 이때 얻은 가중치를 사용하여 검증용 데이터의 인식율은 0.71 수준이다.

 

학습 결과 인식률 수렴 상황을 그래프로 작도해 보자.

9 plt.plot(history.history['accuracy'], label='accuracy')
plt.plot(history.history['val_accuracy'], label = 'val_accuracy')
plt.xlabel('Epoch')
plt.ylabel('Accuracy')
plt.ylim([0.5, 1])
plt.legend(loc='lower right')


test_loss, test_acc = model.evaluate(test_images, test_labels, verbose=2)
 

검증용 테스트 데이터의 인식률을 출력해 보자.

10 print(test_acc) 0.7178999781608582

직접 셀별로 타이핑 하든지 아니면 블로그에서 첨부된 코드를 다운받아 실행해 보자.

kerascnncifar10.ipynb
0.46MB