데이터분석/Tensorflow

Tensorflow : 합성곱신경망(CNN)

이규승 2022. 5. 24. 11:18
728x90

https://untitledtblog.tistory.com/150

 

[머신 러닝/딥 러닝] 합성곱 신경망 (Convolutional Neural Network, CNN)과 학습 알고리즘

1. 이미지 처리와 필터링 기법 필터링은 이미지 처리 분야에서 광범위하게 이용되고 있는 기법으로써, 이미지에서 테두리 부분을 추출하거나 이미지를 흐릿하게 만드는 등의 기능을 수행하기

untitledtblog.tistory.com

http://taewan.kim/post/cnn/

 

CNN, Convolutional Neural Network 요약

Convolutional Neural Network, CNN을 정리합니다.

taewan.kim

 

# MNIST dataset을 사용한 CNN (흑백) > COLAB사용

# CNN : 이미지의 특징을 뽑아 크기를 줄인 후 마지막에 1차원 배열로 만든 후 Dense에 전달하는 방식
# MNIST dataset을 사용
# Sequential api 방법
import tensorflow as tf
from keras import datasets, layers, models

# mnist 데이터를 train / test 나눈다.
(x_train, y_train), (x_test, y_test) = datasets.mnist.load_data()
print(x_train.shape, y_train.shape, x_test.shape, y_test.shape)

ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
(60000, 28, 28) (60000,) (10000, 28, 28) (10000,)

 

3차원 데이터를 4차원으로 변경

# CNN은 Channel을 사용하기 때문에 3차원 데이터를 4차원으로 변경해 준다.
x_train = x_train.reshape((60000, 28, 28, 1)) # channel = 1 > color는 channel = 3
x_test = x_test.reshape((10000, 28, 28, 1))

 

정규화를 해준다

# 정규화
x_train = x_train / 255.0
x_test = x_test / 255.0

 

모델을 정의해준다

# model : Sequential api
input_shape = (28, 28, 1) # 입력

model = models.Sequential()

# filters = 16개 준비한다, Conv : 자연어1D 사진2D 동영상3D, padding = valid, same(원본이미지 밖은 0으로 채우겠다) # stride = 1 이면 1칸씩 이동, 2이면 2칸씩 이동하여 합성곱
model.add(layers.Conv2D(filters=16, kernel_size=(3,3), strides=(1,1), padding='valid', activation='relu', input_shape=input_shape)) 
model.add(layers.MaxPool2D(pool_size=(2,2))) # Conv 레이어에서 출력된 이미지를 축소하는 기능 
model.add(layers.Dropout(rate = 0.2)) # CNN은 오버피팅이 많이 발생한다. 20% 작업에 참여못한다.

model.add(layers.Conv2D(filters=32, kernel_size=(3,3), strides=(1,1), padding='valid', activation='relu')) 
model.add(layers.MaxPool2D(pool_size=(2,2))) 
model.add(layers.Dropout(rate = 0.2))

model.add(layers.Conv2D(filters=64, kernel_size=(3,3), strides=(1,1), padding='valid', activation='relu')) 
model.add(layers.MaxPool2D(pool_size=(2,2))) 
model.add(layers.Dropout(rate = 0.2))

model.add(layers.Flatten()) # FCLayer(Full Connected Layer) : 이미지를 1차원으로 변경

 

분류기(Dense)로 전달

# 분류기(Dense)로 전달
model.add(layers.Dense(64,activation='relu'))
model.add(layers.Dropout(rate = 0.2))
model.add(layers.Dense(32,activation='relu'))
model.add(layers.Dropout(rate = 0.2))
model.add(layers.Dense(units = 10, activation='softmax'))

print(model.summary())
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
Model: "sequential"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 conv2d (Conv2D)             (None, 26, 26, 16)        160       
                                                                 
 max_pooling2d (MaxPooling2D  (None, 13, 13, 16)       0         
 )                                                               
                                                                 
 dropout (Dropout)           (None, 13, 13, 16)        0         
                                                                 
 conv2d_1 (Conv2D)           (None, 11, 11, 32)        4640      
                                                                 
 max_pooling2d_1 (MaxPooling  (None, 5, 5, 32)         0         
 2D)                                                             
                                                                 
 dropout_1 (Dropout)         (None, 5, 5, 32)          0         
                                                                 
 conv2d_2 (Conv2D)           (None, 3, 3, 64)          18496     
                                                                 
 max_pooling2d_2 (MaxPooling  (None, 1, 1, 64)         0         
 2D)                                                             
                                                                 
 dropout_2 (Dropout)         (None, 1, 1, 64)          0         
                                                                 
 flatten (Flatten)           (None, 64)                0         
                                                                 
 dense (Dense)               (None, 64)                4160      
                                                                 
 dropout_3 (Dropout)         (None, 64)                0         
                                                                 
 dense_1 (Dense)             (None, 32)                2080      
                                                                 
 dropout_4 (Dropout)         (None, 32)                0         
                                                                 
 dense_2 (Dense)             (None, 10)                330       
                                                                 
=================================================================
Total params: 29,866
Trainable params: 29,866
Non-trainable params: 0
_________________________________________________________________

 

컴파일

from keras import callbacks
model.compile(optimizer = 'adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])

from keras.callbacks import EarlyStopping
es = EarlyStopping(monitor = 'val_loss', patience=3) # 일반적으로 patience=10정도 준다.
history = model.fit(x_train, y_train, batch_size=128, epochs=1000, verboes=2, validation_split = 0.2, callbacks=[es])

 

저장

# 모델 학습 후 모델 저장. 그런데 history 값도 계속 참조하고 싶은 경우 pickle로 저장함
import pickle
history = history.history
with open('his_data.pickle', 'wb') as f:
  pickle.dump(history, f)

print(history)

 

너무느리면 > colab 런타임을 gpu로 바꿔준다.

 

모델 평가

# 모델 평가 (train / test)
train_loss, train_acc = model.evaluate(x_train, y_train)
test_loss, test_acc = model.evaluate(x_test, y_test)
print('train_loss, train_acc:', train_loss, train_acc)
print('test_loss, test_acc:', test_loss, test_acc)
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
train_loss, train_acc: 0.03097345307469368 0.9912833571434021
test_loss, test_acc: 0.047314662486314774 0.9871000051498413

 

모델 저장 / 불러오기

# model save
model.save('tf28.h5')

model2 = tf.keras.models.load_model('tf28.h5')

 

예측

# predict
import numpy as np
print('예측값:', np.argmax(model2.predict(x_test[:1])))
print('실제값:', y_test[0])
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
예측값: 7
실제값: 7

 

시각화

# 시각화
import matplotlib.pyplot as plt
with open('his_data.pickle', 'rb') as f:
  hitsory = pickle.load(f)

def plot_acc():
  plt.plot(history['accuracy'], label='accuracy') 
  plt.plot(history['val_accuracy'], label='val_accuracy')
  plt.title('accuracy') 
  plt.xlabel('epochs')
  plt.ylabel('acc')
  plt.legend()

plot_acc()
plt.show()

def plot_loss():
  plt.plot(history['loss'], label='loss') 
  plt.plot(history['val_loss'], label='val_loss')
  plt.title('loss') 
  plt.xlabel('epochs')
  plt.ylabel('loss')
  plt.legend()

plot_loss()
plt.show()

728x90