딥러닝 : CNN 코드

hisungmi·2024년 10월 22일

AI

목록 보기
15/15

MNIST

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import random as rd
from sklearn.metrics import accuracy_score
import keras

#Data Loading
(train_x, train_y), (test_x, test_y) = keras.datasets.fashion_mnist.load_data()
print(train_x.shape, train_y.shape, test_x.shape, test_y.shape) #(60000, 28, 28) (60000,) (10000, 28, 28) (10000,)


# X : Min-Max Scaling
# 최소값 0, 최대값 1 로 통일하는 스케일링
# X : Reshape(# of data, 28,28,1)
# 끝에 1을 달아서 그레이스케일을 명시
train_x = train_x.reshape((-1, 28,28, 1))
test_x = test_x.reshape((-1, 28,28, 1))

min_n , max_n = train_x.min(), train_x.max()

train_x = (train_x - min_n) / (max_n - min_n)
test_x = (test_x - min_n) / (max_n - min_n)
train_x.shape, test_x.shape #((60000, 28, 28, 1), (10000, 28, 28, 1))

# Y : One-Hot Encoding
from keras.utios import to_categorical
class_n = len(np.unique(train_y))

train_y = to_categorical(train_y, class_n)
test_y = to_categorical(test_y, class_n)

from keras.callbacks import EarlyStopping
from keras.backend import clear_session
from keras.models import Sequential, Model
from keras.layers import Conv2D, MaxPool2D, Flatten, Dense, Dropout, BatchNormalization

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

# 2. 모델 선언
model = keras.models.Sequential()

# 3. 레이어 조립
model.add( keras.layers.Input(shape=(28,28,1)) )

model.add( keras.layers.Conv2D(filters=32,        # 새롭게 제작하려는 feature map의 수!
                               kernel_size=(3,3), # Conv2D Layer filter의 가로세로 사이즈 (depth는 케라스가 보정!)
                               strides=(1,1),     # Conv2D Layer filter의 이동 보폭
                               padding='same',    # 앞전 feature map의 가로세로 사이즈 유지 | 외곽 정보 더 반영
                               activation='relu', # 빼먹지 않기!
                               ) )
model.add( keras.layers.Conv2D(filters=32,        # 새롭게 제작하려는 feature map의 수!
                               kernel_size=(3,3), # Conv2D Layer filter의 가로세로 사이즈 (depth는 케라스가 보정!)
                               strides=(1,1),     # Conv2D Layer filter의 이동 보폭
                               padding='same',    # 앞전 feature map의 가로세로 사이즈 유지 | 외곽 정보 더 반영
                               activation='relu', # 빼먹지 않기!
                               ) )
model.add( keras.layers.MaxPool2D(pool_size=(2,2), # Maxpooling layer filter의 가로세로 사이즈
                                  strides=(2,2),   # Maxpooling layer filter의 이동 보폭
                                  ) )
model.add( keras.layers.BatchNormalization() )
model.add( keras.layers.Dropout(0.25) )

model.add( keras.layers.Conv2D(filters=64,        # 새롭게 제작하려는 feature map의 수!
                               kernel_size=(3,3), # Conv2D Layer filter의 가로세로 사이즈 (depth는 케라스가 보정!)
                               strides=(1,1),     # Conv2D Layer filter의 이동 보폭
                               padding='same',    # 앞전 feature map의 가로세로 사이즈 유지 | 외곽 정보 더 반영
                               activation='relu', # 빼먹지 않기!
                               ) )
model.add( keras.layers.Conv2D(filters=64,        # 새롭게 제작하려는 feature map의 수!
                               kernel_size=(3,3), # Conv2D Layer filter의 가로세로 사이즈 (depth는 케라스가 보정!)
                               strides=(1,1),     # Conv2D Layer filter의 이동 보폭
                               padding='same',    # 앞전 feature map의 가로세로 사이즈 유지 | 외곽 정보 더 반영
                               activation='relu', # 빼먹지 않기!
                               ) )
model.add( keras.layers.MaxPool2D(pool_size=(2,2), # Maxpooling layer filter의 가로세로 사이즈
                                  strides=(2,2),   # Maxpooling layer filter의 이동 보폭
                                  ) )
model.add( keras.layers.BatchNormalization() )
model.add( keras.layers.Dropout(0.25) )

model.add( keras.layers.Flatten() )
model.add( keras.layers.Dense(10, activation='softmax') )

# 4. 컴파일
model.compile(optimizer='adam', loss='categorical_crossentropy',
              metrics=['accuracy'])

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

# 2. 레이어 사슬처럼 엮기
il = Input(shape=(28,28,1))
hl = Conv2D(filters=32,        # 새롭게 제작하려는 feature map의 수
            kernel_size=(3,3), # Conv2D Layer filter 사이즈 (depth는 케라스가 보정)
            strides=(1,1),     # Conv2D Layer filter 이동 보폭
            padding='same',    # 이전 feature map 사이즈 유지 | 외곽 정보 더 반영!
            activation='relu'  # 빼먹지 않기!
            )(il)
hl = Conv2D(filters=32,        # 새롭게 제작하려는 feature map의 수
            kernel_size=(3,3), # Conv2D Layer filter 사이즈 (depth는 케라스가 보정)
            strides=(1,1),     # Conv2D Layer filter 이동 보폭
            padding='same',    # 이전 feature map 사이즈 유지 | 외곽 정보 더 반영!
            activation='relu'  # 빼먹지 않기!
            )(hl)
hl = MaxPool2D(pool_size=(2,2), # Maxpooling Layer filter 사이즈
               strides=(2,2),   # Maxpooling Layer filter 이동 보폭
               )(hl)
hl = BatchNormalization()(hl)
hl = Dropout(0.25)(hl)

hl = Conv2D(filters=64,        # 새롭게 제작하려는 feature map의 수
            kernel_size=(3,3), # Conv2D Layer filter 사이즈 (depth는 케라스가 보정)
            strides=(1,1),     # Conv2D Layer filter 이동 보폭
            padding='same',    # 이전 feature map 사이즈 유지 | 외곽 정보 더 반영!
            activation='relu'  # 빼먹지 않기!
            )(hl)
hl = Conv2D(filters=64,        # 새롭게 제작하려는 feature map의 수
            kernel_size=(3,3), # Conv2D Layer filter 사이즈 (depth는 케라스가 보정)
            strides=(1,1),     # Conv2D Layer filter 이동 보폭
            padding='same',    # 이전 feature map 사이즈 유지 | 외곽 정보 더 반영!
            activation='relu'  # 빼먹지 않기!
            )(hl)
hl = MaxPool2D(pool_size=(2,2), # Maxpooling Layer filter 사이즈
               strides=(2,2),   # Maxpooling Layer filter 이동 보폭
               )(hl)
hl = BatchNormalization()(hl)
hl = Dropout(0.25)(hl)

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

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

# 4. 컴파일
model.compile(optimizer=keras.optimizers.Adam(), loss=keras.losses.categorical_crossentropy,
              metrics=['accuracy'])

model.summary()

## Early Stopping
from keras.callbacks import EarlyStopping

es = EarlyStopping(monitor='val_loss',       # 얼리스토핑을 적용할 관측 지표
                   min_delta=0,              # 임계값. monitor에서 지정한 지표가 min_delta의 값보다 크게 변해야 성능 개선으로 간주
                   patience=5,               # 성능 개선이 발생하지 않을 때, 얼마나 더 지켜볼 것인지.
                   verbose=1,                # 얼리스토핑 적용 문구
                   restore_best_weights=True,# 최적의 가중치를 가진 epoch 시점으로 되돌림!
                   )

hist = model.fit(train_x, train_y, validation_split=0.2,
                 verbose=1, epochs=10000,
                 callbacks=[es]
                 )
                 
performance_test = model.evaluate(test_x, test_y)

print(f'Test Loss : {performance_test[0]:.6f} | Test Accuracy : {performance_test[1]*100:.2f}%')

그래프

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

plt.figure(figsize=(10, 5))
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(hist, dict) :
    history = hist.history

plt.figure(figsize=(10, 5))
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()
#예측값 생성
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)

train_y_arg = train_y.argmax(axis=1)
test_y_arg = test_y.argmax(axis=1)

logi_train_accuracy = accuracy_score(train_y_arg, single_pred_train)
logi_test_accuracy = accuracy_score(test_y_arg, single_pred_test)

print('CNN')
print(f'트레이닝 정확도 : {logi_train_accuracy*100:.2f}%' )
print(f'테스트 정확도 : {logi_test_accuracy*100:.2f}%' )

숫자 이미지 시각화

id = rd.randrange(0,10000)

print(f'id = {id}')
print(f'다음 그림은 숫자 {test_y_arg[id]} 입니다.')
print(f'모델의 예측 : {single_pred_test[id]}')
print(f'모델의 카테고리별 확률 : {np.floor(pred_test[id]*100)}')

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

plt.imshow(test_x[id].reshape([28,-1]), cmap='gray')
plt.show()
------------------
#틀린 것만 관찰해보자!

true_false = (test_y_arg==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'다음 그림은 숫자 {test_y_arg[id]} 입니다.')
print(f'모델의 예측 : {single_pred_test[id]}')
print(f'모델의 카테고리별 확률 : {np.floor(pred_test[id]*100)}')

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

plt.imshow(test_x[id].reshape([28,-1]), cmap='gray')
plt.show()
profile
난 성미다.

0개의 댓글