본문 바로가기

AI_딥 러닝_시각지능

AI_파이썬_시각지능_CNN_exercise_CIFAR10_2024

My First Convolutional Neural Network : CIFAR-10


실습목표

  1. CNN의 기본 아이디어를 안다.
  2. CNN의 구조를 그리고, 코드로 옮길 수 있다.

Keras Upgrade


!pip install keras-nightly
Collecting keras-nightly
  Downloading keras_nightly-3.7.0.dev2024123003-py3-none-any.whl.metadata (5.8 kB)
Requirement already satisfied: absl-py in /usr/local/lib/python3.10/dist-packages (from keras-nightly) (1.4.0)
Requirement already satisfied: numpy in /usr/local/lib/python3.10/dist-packages (from keras-nightly) (1.26.4)
Requirement already satisfied: rich in /usr/local/lib/python3.10/dist-packages (from keras-nightly) (13.9.4)
Requirement already satisfied: namex in /usr/local/lib/python3.10/dist-packages (from keras-nightly) (0.0.8)
Requirement already satisfied: h5py in /usr/local/lib/python3.10/dist-packages (from keras-nightly) (3.12.1)
Requirement already satisfied: optree in /usr/local/lib/python3.10/dist-packages (from keras-nightly) (0.13.1)
Requirement already satisfied: ml-dtypes in /usr/local/lib/python3.10/dist-packages (from keras-nightly) (0.4.1)
Requirement already satisfied: packaging in /usr/local/lib/python3.10/dist-packages (from keras-nightly) (24.2)
Requirement already satisfied: typing-extensions>=4.5.0 in /usr/local/lib/python3.10/dist-packages (from optree->keras-nightly) (4.12.2)
Requirement already satisfied: markdown-it-py>=2.2.0 in /usr/local/lib/python3.10/dist-packages (from rich->keras-nightly) (3.0.0)
Requirement already satisfied: pygments<3.0.0,>=2.13.0 in /usr/local/lib/python3.10/dist-packages (from rich->keras-nightly) (2.18.0)
Requirement already satisfied: mdurl~=0.1 in /usr/local/lib/python3.10/dist-packages (from markdown-it-py>=2.2.0->rich->keras-nightly) (0.1.2)
Downloading keras_nightly-3.7.0.dev2024123003-py3-none-any.whl (1.3 MB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 1.3/1.3 MB 19.8 MB/s eta 0:00:00
Installing collected packages: keras-nightly
Successfully installed keras-nightly-3.7.0.dev2024123003

Real Game : CNN on CIFAR-10


'''
라이브러리들을 불러오자.
'''
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

import random as rd
from sklearn.metrics import *

import keras

Data Loading


(train_x, train_y), (test_x, test_y) = keras.datasets.cifar10.load_data()
Downloading data from https://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz
170498071/170498071 ━━━━━━━━━━━━━━━━━━━━ 5s 0us/step

print(train_x.shape, train_y.shape, test_x.shape, test_y.shape)
(50000, 32, 32, 3) (50000, 1) (10000, 32, 32, 3) (10000, 1)

labels = {0 : 'Airplane',
          1 : 'Automobile',
          2 : 'Bird',
          3 : 'Cat',
          4 : 'Deer',
          5 : 'Dog',
          6 : 'Frog',
          7 : 'Horse',
          8 : 'Ship',
          9 : 'Truck' }

print(labels)
{0: 'Airplane', 1: 'Automobile', 2: 'Bird', 3: 'Cat', 4: 'Deer', 5: 'Dog', 6: 'Frog', 7: 'Horse', 8: 'Ship', 9: 'Truck'}

'''
Ctrl+Enter를 이용하여
반복 실행 해보자!
'''

id = rd.randrange(0,10000)

print(f'id = {id}')
print(f'다음 그림은 {labels[test_y[id][0]]} 입니다.')
plt.imshow(test_x[id])
plt.show()


X : 표준화 Scaling (standardization)


  • Choose 1. 한꺼번에 Standardization 적용

train_x.shape, test_x.shape
((50000, 32, 32, 3), (10000, 32, 32, 3))

mean = np.mean(train_x, axis=0)
std = np.std(train_x, axis=0)

train_x = (train_x - mean) / std

mean = np.mean(test_x, axis=0)
std = np.std(test_x, axis=0)

test_x = (test_x - mean) / std

train_x.mean(), train_x.std()
(7.94919685631612e-18, 0.9999999999999998)

  • Choose 2. 채널별로 Standardization 적용

print(train_x[:,:,:,0].mean(), train_x[:,:,:,0].std())
print(train_x[:,:,:,1].mean(), train_x[:,:,:,1].std())
print(train_x[:,:,:,2].mean(), train_x[:,:,:,2].std())
-7.713829575095588e-18 0.9999999999999998
2.5224267119483557e-18 0.9999999999999986
2.2026824808563106e-18 1.0000000000000029

# train_x[:,:,:,0] = (train_x[:,:,:,0] - train_x[:,:,:,0].mean()) / train_x[:,:,:,0].std()
# train_x[:,:,:,1] = (train_x[:,:,:,1] - train_x[:,:,:,1].mean()) / train_x[:,:,:,1].std()
# train_x[:,:,:,2] = (train_x[:,:,:,2] - train_x[:,:,:,2].mean()) / train_x[:,:,:,2].std()

# test_x[:,:,:,0] = (test_x[:,:,:,0] - test_x[:,:,:,0].mean()) / test_x[:,:,:,0].std()
# test_x[:,:,:,1] = (test_x[:,:,:,1] - test_x[:,:,:,1].mean()) / test_x[:,:,:,1].std()
# test_x[:,:,:,2] = (test_x[:,:,:,2] - test_x[:,:,:,2].mean()) / test_x[:,:,:,2].std()

# for channel in range(train_x.shape[-1]):  # 채널 수에 따라 반복
#     train_x[:,:,:,channel] = (train_x[:,:,:,channel] - train_x[:,:,:,channel].mean()) / train_x[:,:,:,channel].std()
#     test_x[:,:,:,channel] = (test_x[:,:,:,channel] - test_x[:,:,:,channel].mean()) / test_x[:,:,:,channel].std()

Y : One-Hot Encoding


train_y.shape, test_y.shape, np.unique(test_y)
((50000, 1), (10000, 1), array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], dtype=uint8))

from keras.utils import to_categorical

train_y = to_categorical(train_y, 10)
test_y = to_categorical(test_y, 10)

train_y.shape, test_y.shape, len(np.unique(test_y))
((50000, 10), (10000, 10), 2)

코드를 완성해주세요! FC 구조

  • 조건
    • model.fit( ) 을 history 에 담아서 학습 과정의 로그를 남길 것.
    • EarlyStopping 의 옵션도 조절해보자.

  • 자유롭게 먼저 해보는 것을 추천

  • 구조를 따라서 코딩을 한다면
    1. Functional, Sequential 중 택일
    2. 인풋레이어
    3. Convolution : 필터수 32개, 사이즈(3, 3), same padding
    4. Convolution : 필터수 32개, 사이즈(3, 3), same padding
    5. BatchNormalization
    6. MaxPooling : 사이즈(2,2) 스트라이드(2,2)
    7. DropOut : 25% 비활성화
    8. Convolution : 필터수 64개, 사이즈(3, 3), same padding
    9. Convolution : 필터수 64개, 사이즈(3, 3), same padding
    10. BatchNormalization
    11. MaxPooling : 사이즈(2,2) 스트라이드(2,2)
    12. DropOut : 25% 비활성화
    13. Flatten( )
    14. Fully Connected Layer : 노드 1024개
    15. BatchNormalization
    16. DropOut : 35% 비활성화
    17. 아웃풋레이어

import keras

from keras.utils import clear_session, plot_model
from keras.models import Sequential, Model
from keras.layers import Input, Dense, Flatten, Conv2D, MaxPool2D, BatchNormalization, Dropout

from keras.callbacks import EarlyStopping

train_x.shape
(50000, 32, 32, 3)

Sequential API


#Sequential
clear_session()

# 인풋레이어
model = Sequential()

model.add( Input(shape=(32,32,3)) )

model.add( Flatten() )
# Fully Connected Layers
# Fully Connected Layer : 노드 1024개
model.add(Dense(512, activation='relu'))   # 첫 번째 FC 레이어
# BatchNormalization
model.add(BatchNormalization())
model.add(Dropout(0.25))
# DropOut : 25% 비활성화
model.add(Dense(256, activation='relu'))   # 두 번째 FC 레이어
# BatchNormalization
# DropOut : 25% 비활성화
model.add(BatchNormalization())
model.add(Dropout(0.35))

# 아웃풋레이어
model.add(Dense(10, activation='softmax')) # 출력 레이어 (10 클래스)

model.summary()


Functional API


clear_session()

il = Input(shape = (32,32,3))
hl = Flatten()(il)

hl = Dense(512, activation='relu')(hl)
hl = BatchNormalization()(hl)
hi = Dropout(0.25)(hl)

hl = Dense(256, activation='relu')(hl)
hl = BatchNormalization()(hl)
hi = Dropout(0.25)(hl)

hl = Dense(128, activation='relu')(il)
hl = BatchNormalization()(hl)
hi = Dropout(0.25)(hl)

ol = Dense(10, activation='softmax')(hl)

model = Model(il, ol)

model.summary()


모델 학습


model.compile(optimizer=('Adam'), loss = 'categorical_crossentropy', metrics=['accuracy'])

es = EarlyStopping( min_delta = 0, patience=3, verbose=1, restore_best_weights=True)

history = model.fit(train_x, train_y, validation_split=0.2, epochs=1000, callbacks = [es], verbose=1)
Epoch 1/1000
1250/1250 ━━━━━━━━━━━━━━━━━━━━ 10s 4ms/step - accuracy: 0.3033 - loss: 2.1199 - val_accuracy: 0.4396 - val_loss: 1.5791
Epoch 2/1000
1250/1250 ━━━━━━━━━━━━━━━━━━━━ 5s 4ms/step - accuracy: 0.4189 - loss: 1.6260 - val_accuracy: 0.4676 - val_loss: 1.4767
Epoch 3/1000
1250/1250 ━━━━━━━━━━━━━━━━━━━━ 5s 4ms/step - accuracy: 0.4556 - loss: 1.5269 - val_accuracy: 0.4923 - val_loss: 1.4272
Epoch 4/1000
1250/1250 ━━━━━━━━━━━━━━━━━━━━ 5s 3ms/step - accuracy: 0.4793 - loss: 1.4660 - val_accuracy: 0.4935 - val_loss: 1.4241
Epoch 5/1000
1250/1250 ━━━━━━━━━━━━━━━━━━━━ 6s 4ms/step - accuracy: 0.4975 - loss: 1.4140 - val_accuracy: 0.5190 - val_loss: 1.3697
Epoch 6/1000
1250/1250 ━━━━━━━━━━━━━━━━━━━━ 5s 4ms/step - accuracy: 0.5102 - loss: 1.3690 - val_accuracy: 0.5248 - val_loss: 1.3371
Epoch 7/1000
1250/1250 ━━━━━━━━━━━━━━━━━━━━ 5s 4ms/step - accuracy: 0.5295 - loss: 1.3160 - val_accuracy: 0.5322 - val_loss: 1.3250
Epoch 8/1000
1250/1250 ━━━━━━━━━━━━━━━━━━━━ 5s 4ms/step - accuracy: 0.5364 - loss: 1.3038 - val_accuracy: 0.5372 - val_loss: 1.3114
Epoch 9/1000
1250/1250 ━━━━━━━━━━━━━━━━━━━━ 5s 4ms/step - accuracy: 0.5476 - loss: 1.2709 - val_accuracy: 0.5318 - val_loss: 1.3178
Epoch 10/1000
1250/1250 ━━━━━━━━━━━━━━━━━━━━ 5s 4ms/step - accuracy: 0.5534 - loss: 1.2433 - val_accuracy: 0.5431 - val_loss: 1.2846
Epoch 11/1000
1250/1250 ━━━━━━━━━━━━━━━━━━━━ 4s 3ms/step - accuracy: 0.5657 - loss: 1.2152 - val_accuracy: 0.5514 - val_loss: 1.2823
Epoch 12/1000
1250/1250 ━━━━━━━━━━━━━━━━━━━━ 5s 4ms/step - accuracy: 0.5768 - loss: 1.1820 - val_accuracy: 0.5496 - val_loss: 1.2793
Epoch 13/1000
1250/1250 ━━━━━━━━━━━━━━━━━━━━ 5s 4ms/step - accuracy: 0.5866 - loss: 1.1603 - val_accuracy: 0.5524 - val_loss: 1.2718
Epoch 14/1000
1250/1250 ━━━━━━━━━━━━━━━━━━━━ 4s 3ms/step - accuracy: 0.5961 - loss: 1.1406 - val_accuracy: 0.5481 - val_loss: 1.2666
Epoch 15/1000
1250/1250 ━━━━━━━━━━━━━━━━━━━━ 5s 4ms/step - accuracy: 0.5974 - loss: 1.1282 - val_accuracy: 0.5497 - val_loss: 1.2772
Epoch 16/1000
1250/1250 ━━━━━━━━━━━━━━━━━━━━ 5s 4ms/step - accuracy: 0.6064 - loss: 1.0933 - val_accuracy: 0.5569 - val_loss: 1.2676
Epoch 17/1000
1250/1250 ━━━━━━━━━━━━━━━━━━━━ 4s 3ms/step - accuracy: 0.6164 - loss: 1.0846 - val_accuracy: 0.5675 - val_loss: 1.2538
Epoch 18/1000
1250/1250 ━━━━━━━━━━━━━━━━━━━━ 5s 4ms/step - accuracy: 0.6229 - loss: 1.0671 - val_accuracy: 0.5668 - val_loss: 1.2394
Epoch 19/1000
1250/1250 ━━━━━━━━━━━━━━━━━━━━ 5s 4ms/step - accuracy: 0.6262 - loss: 1.0480 - val_accuracy: 0.5624 - val_loss: 1.2620
Epoch 20/1000
1250/1250 ━━━━━━━━━━━━━━━━━━━━ 5s 4ms/step - accuracy: 0.6364 - loss: 1.0219 - val_accuracy: 0.5644 - val_loss: 1.2542
Epoch 21/1000
1250/1250 ━━━━━━━━━━━━━━━━━━━━ 6s 5ms/step - accuracy: 0.6349 - loss: 1.0149 - val_accuracy: 0.5631 - val_loss: 1.2608
Epoch 21: early stopping
Restoring model weights from the end of the best epoch: 18.

train_y.shape, test_y.shape, len(np.unique(test_y))
((50000, 10), (10000, 10), 2)

# 성능평가

performance_test = model.evaluate(test_x, test_y)

print( f'Test Loss : {performance_test[0]:.6f}, Test Accuracy : {performance_test[1]*100:.3f}%' )
313/313 ━━━━━━━━━━━━━━━━━━━━ 1s 2ms/step - accuracy: 0.5702 - loss: 1.2237
Test Loss : 1.233831, Test Accuracy : 56.780%

코드를 완성해주세요! CNN 구조

  • 조건
    • model.fit( ) 을 history 에 담아서 학습 과정의 로그를 남길 것.
    • EarlyStopping 의 옵션도 조절해보자.

  • 자유롭게 먼저 해보는 것을 추천

  • 구조를 따라서 코딩을 한다면
    1. Functional, Sequential 중 택일
    2. 인풋레이어
    3. Convolution : 필터수 32개, 사이즈(3, 3), same padding
    4. Convolution : 필터수 32개, 사이즈(3, 3), same padding
    5. BatchNormalization
    6. MaxPooling : 사이즈(2,2) 스트라이드(2,2)
    7. DropOut : 25% 비활성화
    8. Convolution : 필터수 64개, 사이즈(3, 3), same padding
    9. Convolution : 필터수 64개, 사이즈(3, 3), same padding
    10. BatchNormalization
    11. MaxPooling : 사이즈(2,2) 스트라이드(2,2)
    12. DropOut : 25% 비활성화
    13. Flatten( )
    14. Fully Connected Layer : 노드 1024개
    15. BatchNormalization
    16. DropOut : 35% 비활성화
    17. 아웃풋레이어

import keras

Sequential API


## Sequential API
## 1. 세션 클리어
clear_session()

## 2. 모델 발판 생성
model = Sequential()

## 3. 모델 블록 조립
# 인풋 레이어
model.add( Input(shape=(32,32,3)) )
# Convolution : 필터수 32개, 사이즈(3, 3), same padding
model.add( Conv2D(filters=32,        ## 새롭게 제작하려는 feature map의 수 (서로 다른 필터를 32개 사용)
                  kernel_size=(3,3), ## Conv2D filter의 가로세로 사이즈
                  strides=(1,1),     ## Conv2D filter의 이동 보폭
                  padding='same',    ## 앞전 feature map 사이즈 유지 및 외곽 정보 더 반영
                  activation='relu'
                  ))
# Convolution : 필터수 32개, 사이즈(3, 3), same padding
model.add( Conv2D(filters=32,        ## 새롭게 제작하려는 feature map의 수 (서로 다른 필터를 32개 사용)
                  kernel_size=(3,3), ## Conv2D filter의 가로세로 사이즈
                  strides=(1,1),     ## Conv2D filter의 이동 보폭
                  padding='same',    ## 앞전 feature map 사이즈 유지 및 외곽 정보 더 반영
                  activation='relu'
                  ))
# BatchNormalization
model.add( BatchNormalization() )
# MaxPooling : 사이즈(2,2) 스트라이드(2,2)
model.add( MaxPool2D(pool_size=(2,2),## Pooling filter의 가로세로 사이즈
                     strides=(2,2),  ## Pooling filter의 이동 보폭
                     ) )
# DropOut : 25% 비활성화
model.add( Dropout(0.25) )
# Convolution : 필터수 64개, 사이즈(3, 3), same padding
model.add( Conv2D(filters=64,        ## 새롭게 제작하려는 feature map의 수 (서로 다른 필터를 32개 사용)
                  kernel_size=(3,3), ## Conv2D filter의 가로세로 사이즈
                  strides=(1,1),     ## Conv2D filter의 이동 보폭
                  padding='same',    ## 앞전 feature map 사이즈 유지 및 외곽 정보 더 반영
                  activation='relu'
                  ))
# Convolution : 필터수 64개, 사이즈(3, 3), same padding
model.add( Conv2D(filters=64,        ## 새롭게 제작하려는 feature map의 수 (서로 다른 필터를 32개 사용)
                  kernel_size=(3,3), ## Conv2D filter의 가로세로 사이즈
                  strides=(1,1),     ## Conv2D filter의 이동 보폭
                  padding='same',    ## 앞전 feature map 사이즈 유지 및 외곽 정보 더 반영
                  activation='relu'
                  ))
# BatchNormalization
model.add( BatchNormalization() )
# MaxPooling : 사이즈(2,2) 스트라이드(2,2)
model.add( MaxPool2D(pool_size=(2,2),## Pooling filter의 가로세로 사이즈
                     strides=(2,2),  ## Pooling filter의 이동 보폭
                     ) )
# DropOut : 25% 비활성화
model.add( Dropout(0.25) )
# Flatten
model.add( Flatten() )
# Fully Connected Layer : 노드 1024개
model.add( Dense(1024, activation='relu') )
# BatchNormalization
model.add( BatchNormalization() )
# 아웃풋 레이어
model.add( Dense(10, activation='softmax') )

## 요약
model.summary()


Functional API


## Functional API
## 1. 세션 클리어
clear_session()

## 2. 레이어 엮기
# 인풋 레이어
il = Input(shape=(32,32,3))

# Convolution : 필터수 32개, 사이즈(3, 3), same padding
hl = Conv2D(32, 3, 1, 'same', activation='relu')(il)
# Convolution : 필터수 32개, 사이즈(3, 3), same padding
hl = Conv2D(32, 3, 1, 'same', activation='relu')(hl)
# BatchNormalization
hl = BatchNormalization()(hl)
# MaxPooling : 사이즈(2,2) 스트라이드(2,2)
hl = MaxPool2D(2)(hl)
# DropOut : 25% 비활성화
hl = Dropout(0.25)(hl)

# Convolution : 필터수 64개, 사이즈(3, 3), same padding
hl = Conv2D(64, 3, 1, 'same', activation='relu')(hl)
# Convolution : 필터수 64개, 사이즈(3, 3), same padding
hl = Conv2D(64, 3, 1, 'same', activation='relu')(hl)
# BatchNormalization
hl = BatchNormalization()(hl)
# MaxPooling : 사이즈(2,2) 스트라이드(2,2)
hl = MaxPool2D(2)(hl)
# DropOut : 25% 비활성화
hl = Dropout(0.25)(hl)

# Flatten
hl = Flatten()(hl)
# Fully Connected Layer : 노드 1024개
hl = Dense(1024, activation='relu')(hl)
# BatchNormalization
hl = BatchNormalization()(hl)
# 아웃풋 레이어
ol = Dense(10, activation='softmax')(hl)

## 3. 모델의 시작과 끝 지정
model = Model(il, ol)

## 요약
model.summary()


모델 학습


model.compile(optimizer=('Adam'), loss = 'categorical_crossentropy', metrics=['accuracy'])

es = EarlyStopping( min_delta = 0, patience=3, verbose=1, restore_best_weights=True)

history = model.fit(train_x, train_y, validation_split=0.2, epochs=1000, callbacks = [es], verbose=1)
Epoch 1/1000
1250/1250 ━━━━━━━━━━━━━━━━━━━━ 16s 8ms/step - accuracy: 0.4076 - loss: 1.8306 - val_accuracy: 0.6278 - val_loss: 1.0846
Epoch 2/1000
1250/1250 ━━━━━━━━━━━━━━━━━━━━ 14s 6ms/step - accuracy: 0.6358 - loss: 1.0451 - val_accuracy: 0.6573 - val_loss: 1.0026
Epoch 3/1000
1250/1250 ━━━━━━━━━━━━━━━━━━━━ 8s 6ms/step - accuracy: 0.7032 - loss: 0.8483 - val_accuracy: 0.6971 - val_loss: 0.8818
Epoch 4/1000
1250/1250 ━━━━━━━━━━━━━━━━━━━━ 7s 6ms/step - accuracy: 0.7453 - loss: 0.7380 - val_accuracy: 0.7194 - val_loss: 0.8129
Epoch 5/1000
1250/1250 ━━━━━━━━━━━━━━━━━━━━ 11s 6ms/step - accuracy: 0.7792 - loss: 0.6296 - val_accuracy: 0.7421 - val_loss: 0.7549
Epoch 6/1000
1250/1250 ━━━━━━━━━━━━━━━━━━━━ 10s 6ms/step - accuracy: 0.8149 - loss: 0.5292 - val_accuracy: 0.7708 - val_loss: 0.7025
Epoch 7/1000
1250/1250 ━━━━━━━━━━━━━━━━━━━━ 11s 6ms/step - accuracy: 0.8501 - loss: 0.4313 - val_accuracy: 0.7763 - val_loss: 0.7045
Epoch 8/1000
1250/1250 ━━━━━━━━━━━━━━━━━━━━ 10s 6ms/step - accuracy: 0.8661 - loss: 0.3811 - val_accuracy: 0.7642 - val_loss: 0.7322
Epoch 9/1000
1250/1250 ━━━━━━━━━━━━━━━━━━━━ 11s 7ms/step - accuracy: 0.8885 - loss: 0.3177 - val_accuracy: 0.7766 - val_loss: 0.7631
Epoch 9: early stopping
Restoring model weights from the end of the best epoch: 6.

성능 평가


performance_test = model.evaluate(test_x, test_y)

print( f'Test Loss : {performance_test[0]:.6f}, Test Accuracy : {performance_test[1]*100:.3f}%' )
313/313 ━━━━━━━━━━━━━━━━━━━━ 1s 3ms/step - accuracy: 0.7668 - loss: 0.7024
Test Loss : 0.700860, Test Accuracy : 76.830%

if not isinstance(history, dict):
    history = history.history

plt.plot(history['accuracy'])
plt.plot(history['val_accuracy'])
plt.title('Accuracy : Training vs Validation')
plt.ylabel('Accuracy')
plt.xlabel('Epoch')
plt.legend(['Training', 'Validation'], loc=0)
plt.show()


if not isinstance(history, dict):
    history = history.history

plt.plot(history['loss'])
plt.plot(history['val_loss'])
plt.title('Loss : Training vs Validation')
plt.ylabel('Loss')
plt.xlabel('Epoch')
plt.legend(['Training', 'Validation'], loc=0)
plt.show()


# 원핫 인코딩 해제
train_y = train_y.argmax(axis=1)
test_y = test_y.argmax(axis=1)

pred_train = model.predict(train_x)
pred_test = model.predict(test_x)

single_pred_train = pred_train.argmax(axis=1)
single_pred_test = pred_test.argmax(axis=1)

logi_train_accuracy = accuracy_score(train_y, single_pred_train)
logi_test_accuracy = accuracy_score(test_y, single_pred_test)

print('CNN')
print(f'트레이닝 정확도 : {logi_train_accuracy*100:.2f}%')
print(f'테스트 정확도 : {logi_test_accuracy*100:.2f}%')
print(confusion_matrix(test_y, single_pred_test))
print(classification_report(test_y, single_pred_test))
1563/1563 ━━━━━━━━━━━━━━━━━━━━ 5s 3ms/step
313/313 ━━━━━━━━━━━━━━━━━━━━ 1s 2ms/step
CNN
트레이닝 정확도 : 87.23%
테스트 정확도 : 76.83%
[[830   8  21  20  11   4   4  13  48  41]
 [ 17 825   1   5   2   2   4   2  42 100]
 [ 96   2 615  42  86  67  34  29  22   7]
 [ 31   4  49 581  55 175  43  29  16  17]
 [ 18   2  49  46 763  36  18  52  12   4]
 [ 12   3  39 154  33 696  11  40   8   4]
 [  4   4  55  61  46  35 776   5   9   5]
 [  7   1  22  24  41  49   4 840   4   8]
 [ 72  11   4  11   4   6   3   5 870  14]
 [ 20  30   4  15   2   2   2   7  31 887]]
              precision    recall  f1-score   support

           0       0.75      0.83      0.79      1000
           1       0.93      0.82      0.87      1000
           2       0.72      0.61      0.66      1000
           3       0.61      0.58      0.59      1000
           4       0.73      0.76      0.75      1000
           5       0.65      0.70      0.67      1000
           6       0.86      0.78      0.82      1000
           7       0.82      0.84      0.83      1000
           8       0.82      0.87      0.84      1000
           9       0.82      0.89      0.85      1000

    accuracy                           0.77     10000
   macro avg       0.77      0.77      0.77     10000
weighted avg       0.77      0.77      0.77     10000

'''
성능 확인을 위해
Ctrl+Enter를 이용하여
반복 실행 해보자!
'''

id = rd.randrange(0,10000)

print(f'id = {id}')
print(f'다음 그림은 {labels[test_y[id]]} 입니다.')
print(f'모델의 예측 : {labels[single_pred_test[id]]}')

prob = np.floor(pred_test[id]*100).tolist()
prob_dict = {}

for idx, prob in enumerate(prob) :
    prob_dict[ labels[idx] ] = prob

print('모델의 카테고리별 확률 : ')
print(prob_dict)

if test_y[id] == single_pred_test[id] :
    print('정답입니다')
else :
    print('틀렸어요')

plt.imshow(test_x[id].reshape([32,32,-1]))
plt.show()


'''
틀린 것만 관찰해보자!

Ctrl+Enter를 이용하여
반복 실행 해보자!
'''

true_false = (test_y == single_pred_test)
f_id = np.where(true_false == False)[0]
f_n = len(f_id)

id = f_id[rd.randrange(0,f_n)]


print(f'id = {id}')
print(f'다음 그림은 {labels[test_y[id]]} 입니다.')
print(f'모델의 예측 : {labels[single_pred_test[id]]}')

prob = np.floor(pred_test[id]*100).tolist()
prob_dict = {}

for idx, prob in enumerate(prob) :
    prob_dict[ labels[idx] ] = prob

print('모델의 카테고리별 확률 : ')
print(prob_dict)

if test_y[id] == single_pred_test[id] :
    print('정답입니다')
else :
    print('틀렸어요')

plt.imshow(test_x[id].reshape([32,32,-1]))
plt.show()