끄적이는 기록일지

[머신러닝] 07.다양한 신경망_(1) 이미지 처리를 위한 전처리, 딥러닝 모델 본문

AI실무

[머신러닝] 07.다양한 신경망_(1) 이미지 처리를 위한 전처리, 딥러닝 모델

시시나브로 2021. 11. 26. 01:22
728x90
 

[머신러닝] 06.텐서플로와 신경망_(1) 딥러닝 모델의 학습 방법

1. 딥러닝 모델 전 시간 다층 퍼셉트론까지 이야기했습니다. 모델 안에 은닉층이 많아진다면, 깊은 신경망이라는 의미의 Deep Learning이란 단어를 사용하였습니다. 2. 딥러닝 모델의 학습방법 Loss fu

kcy51156.tistory.com

 

이미지 처리와 자연어 처리를 위한 데이터 전 처리와 딥러닝 모델을 알아보도록 하겠습니다.

1. 이미지 처리를 이용한 예시

2021 NIPA AI 온라인 교육 AI(인공지능) 실무 심화 (elice.io)

- 이미지에 있는 어떤 동물인지 분류하고자 할 때,

- 컴퓨터에게 이미지는 각 픽셀 값을 가진 숫자 배열로 인식하게 합니다.

2. 이미지 전 처리

- 모두 같은 크기를 갖는 이미지로 통일

1) 가로 세로 픽셀 사이즈를 표현하는 해상도 통일

2) 표현하는 방식 통일(RGB, HSV, Gray-scale, Binary, ...)

MNIST 데이터 이미지 전 처리

3. 이미지 처리 딥러닝 모델

1) 기존 다층 퍼셉트론 기반 신경망의 이미지 처리 방식

- 극도로 많은 수의 파라미터가 필요하다.

2) 합성곱 신경망(Convolution Neural Network)

- 작은 필터를 순환시키는 방식

- 이미지의 패턴이 아닌 특징을 중점으로 인식

3) 합성곱 신경망 구조 

 

합성곱층 → 풀링층 → 완전연결층

- 입력 이미지의 특징을 추출, 분류하는 과정으로 동작이다.

- 이미지에서 어떠한 특징이 있는지를 구하는 과정.

- 필터가 이미지를 이동하며 새로운 이미지(피쳐맵)생성.

4) 피쳐맵의 크기 변형

- Padding : 원본 이미지의 상하좌우에 한 줄씩 추가

- String : 필터를 이동시키는 거리 설정(ex) 1칸씩 이동)

5) Pooling Layer(풀링층) : 이미지의 왜곡의 영향(노이즈)축소하는 과정.

- 최대풀링 : 가장 큰 값만 나오는 과정

- 평균풀링 : 4개의 숫자의 평균 값으로 축소하는 과정

6) Fully Connected Layer(완전연결층) : 추출된 특징을 사용하여 이미지를 분류.

 

7) 분류를 위한 Softmax활성화함수

- 마지막 계층에 Softmax활성화함수 사용

a+b+c+d+e+f= 1, a,b,c,d,e,f>=0

8) 정리

- Convolution Layer특징을 찾아내고, PoolingLayer처리할 (이미지) 크기를 줄여준다. 이를 N반복한다.

- 반복할 때마다 줄어든 영역에서의 특징을 찾게 되고, 영역의 크기는 작아졌기 때문에 빠른 학습이 가능해진다

사물 인식과 화질 개선

4. 실습

1. MNIST 분류 CNN 모델 - 데이터 전 처리, 모델 구현, 평가 및 예측

- 손글씨로 된 사진을 모아 둔 데이터이다.

- MNIST 데이터는 이미지 데이터이지만 가로 길이와 세로 길이만 존재하는 2차원 데이터입니다. CNN 모델은 채널(RGB 혹은 흑백)까지 고려한 3차원 데이터를 입력으로 받기에 채널 차원을 추가해 데이터의 모양(shape)을 바꿔줍니다. 결과는 아래와 같습니다.

[데이터 수, 가로 길이, 세로 길이] -> [데이터 수, 가로 길이, 세로 길이, 채널 수]

1. 학습용 및 평가용 데이터를 CNN 모델의 입력으로 사용할 수 있도록 (샘플개수, 가로픽셀, 세로픽셀, 1) 형태로 변환합니다.

- tf.expand_dims 함수를 활용하여 train_images, test_images 데이터의 형태를 변환하고 각각 train_images, test_images에 저장합니다.

tf.expand_dims(data, axis)

- Tensor 배열 데이터에서 마지막 축(axis)에 해당하는 곳에 차원 하나를 추가할 수 있는 코드입니다. ( axis에 -1을 넣으면 어떤 data가 들어오던 마지막 축의 index를 의미합니다.)

 

2. keras를 활용하여 CNN 모델을 설정합니다.

- 분류 모델에 맞게 마지막 레이어의 노드 수는 10개, activation 함수는 ‘softmax’로 설정합니다.

#CNN 레이어
tf.keras.layers.Conv2D(filters, kernel_size, activation, padding)

: 입력 이미지의 특징, 즉 처리할 특징 맵(map)을 추출하는 레이어입니다.

  • filters : 필터(커널) 개수
  • kernel_size : 필터(커널)의 크기
  • activation : 활성화 함수
  • padding : 이미지가 필터를 거칠 때 그 크기가 줄어드는 것을 방지하기 위해서 가장자리에 0의 값을 가지는 픽셀을 넣을 것인지 말 것인지를 결정하는 변수. ‘SAME’ 또는 ‘VALID’
#Maxpool 레이어
tf.keras.layers.MaxPool2D(padding)

 : 처리할 특징 맵(map)의 크기를 줄여주는 레이어입니다.

  • padding : ‘SAME’ 또는 ‘VALID’
#Faltten 레이어
tf.keras.layers.Flatten()

: Convolution layer 또는 MaxPooling layer의 결과는 N차원의 텐서 형태입니다. 이를 1차원으로 평평하게 만들어줍니다.

#Dense 레이어
tf.keras.layers.Dense(node, activation)
  • node : 노드(뉴런) 개수
  • activation : 활성화 함수

3. evaluate 메서드와 평가용 데이터를 사용하여 모델을 평가합니다.

- loss와 accuracy를 계산하고 loss, test_acc에 저장합니다.

model.evaluate(X, Y)
  • evaluate() 메서드는 학습된 모델을 바탕으로 입력한 feature 데이터 X와 label Y의 loss 값과 metrics 값을 출력합니다.

4. predict_classes 메서드를 사용하여 평가용 데이터에 대한 예측 결과를 predictions에 저장합니다

model.predict_classes(X)
  • .X 데이터의 예측 label 값을 출력합니다.
import numpy as np
np.seterr(divide='ignore', invalid='ignore')
import tensorflow as tf
from tensorflow.keras import models
import matplotlib.pyplot as plt

import logging, os
logging.disable(logging.WARNING)
os.environ["TF_CPP_MIN_LOG_LEVEL"] = "3"

# 동일한 실행 결과 확인을 위한 코드입니다.
np.random.seed(123)
tf.random.set_seed(123)


# MNIST 데이터 세트를 불러옵니다.
mnist = tf.keras.datasets.mnist

# MNIST 데이터 세트를 Train set과 Test set으로 나누어 줍니다.
(train_images, train_labels), (test_images, test_labels) = mnist.load_data()    

# Train 데이터 5000개와 Test 데이터 1000개를 사용합니다.
train_images, train_labels = train_images[:5000], train_labels[:5000]
test_images, test_labels = test_images[:1000], test_labels[:1000]


print("원본 학습용 이미지 데이터 형태: ",train_images.shape)
print("원본 평가용 이미지 데이터 형태: ",test_images.shape)
print("원본 학습용 label 데이터: ",train_labels)

# 첫 번째 샘플 데이터를 출력합니다.
plt.figure(figsize=(10, 10))
plt.imshow(train_images[0], cmap=plt.cm.binary)
plt.colorbar()
plt.title("Training Data Sample")
plt.savefig("sample1.png")
elice_utils.send_image("sample1.png")

# 9개의 학습용 샘플 데이터를 출력합니다.
class_names = ['zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine']
for i in range(9):
    plt.subplot(3,3,i+1)
    plt.xticks([])
    plt.yticks([])
    plt.grid(False)
    plt.imshow(train_images[i], cmap=plt.cm.binary)
    plt.xlabel(class_names[train_labels[i]])
plt.savefig("sample2.png")
elice_utils.send_image("sample2.png")

"""
1. CNN 모델의 입력으로 사용할 수 있도록 (샘플개수, 가로픽셀, 세로픽셀, 1) 형태로 변환합니다.
* 차원 축소 : tf.expand_dims(data, axis)
"""
train_images = tf.expand_dims(train_images, -1)
test_images = tf.expand_dims(test_images, -1)

print("변환한 학습용 이미지 데이터 형태: ",train_images.shape)
print("변환한 평가용 이미지 데이터 형태: ",test_images.shape)

"""
2. CNN 모델을 설정합니다.
   분류 모델에 맞게 마지막 레이어의 노드 수는 10개, activation 함수는 'softmax'로 설정합니다.
"""
model = tf.keras.Sequential([
    tf.keras.layers.Conv2D(filters = 32, kernel_size = (3,3), activation = 'relu', padding = 'SAME', input_shape = (28,28,1)),
    tf.keras.layers.MaxPool2D(padding = 'SAME'),
    tf.keras.layers.Conv2D(filters = 32, kernel_size = (3,3), activation = 'relu', padding = 'SAME'),
    tf.keras.layers.MaxPool2D(padding = 'SAME'),
    tf.keras.layers.Conv2D(filters = 32, kernel_size = (3,3), activation = 'relu', padding = 'SAME'),
    tf.keras.layers.MaxPool2D(padding = 'SAME'),
    tf.keras.layers.Flatten(),
    tf.keras.layers.Dense(64, activation = 'relu'),
    tf.keras.layers.Dense(10, activation = 'softmax')
])

# CNN 모델 구조를 출력합니다.
print(model.summary())

# CNN 모델의 학습 방법을 설정합니다.
model.compile(loss = 'sparse_categorical_crossentropy',
              optimizer = 'adam',
              metrics = ['accuracy'])
              
# 학습을 수행합니다. 
history = model.fit(train_images, train_labels, epochs = 20, batch_size = 512)

# 학습 결과를 출력합니다.
Visulaize([('CNN', history)], 'loss')

"""
1. 평가용 데이터를 활용하여 모델을 평가합니다.
   loss와 accuracy를 계산하고 loss, test_acc에 저장합니다.
"""
loss, test_acc = model.evaluate(test_images, test_labels, verbose = 0)

"""
2. 평가용 데이터에 대한 예측 결과를 predictions에 저장합니다.
"""
predictions = model.predict_classes(test_images)

# 모델 평가 및 예측 결과를 출력합니다.
print('\nTest Loss : {:.4f} | Test Accuracy : {}'.format(loss, test_acc))
print('예측한 Test Data 클래스 : ',predictions[:10])

# 평가용 데이터에 대한 레이어 결과를 시각화합니다.

def Plotter(test_images, model):

    img_tensor = test_images[0]
    img_tensor = np.expand_dims(img_tensor, axis=0) 
    
    layer_outputs = [layer.output for layer in model.layers[:6]]
    activation_model = models.Model(inputs=model.input, outputs=layer_outputs)

    activations = activation_model.predict(img_tensor)
    
    layer_names = []
    for layer in model.layers[:6]:
        layer_names.append(layer.name)
    
    images_per_row = 16

    for layer_name, layer_activation in zip(layer_names, activations):
        n_features = layer_activation.shape[-1]
    
        size = layer_activation.shape[1]
    
        n_cols = n_features // images_per_row
        display_grid = np.zeros((size * n_cols, images_per_row * size))
    
        for col in range(n_cols):
            for row in range(images_per_row):
                channel_image = layer_activation[0, :, :, col * images_per_row + row]
            
                channel_image -= channel_image.mean() 
                channel_image /= channel_image.std()
                channel_image *= 64
                channel_image += 128
                channel_image = np.clip(channel_image, 0, 255.).astype('uint8')
            
                display_grid[col * size : (col+1) * size, row * size : (row+1) * size] = channel_image
            
        scale = 1. / size
        print('레이어 이름: ', layer_name)
        plt.figure(figsize=(scale * display_grid.shape[1], scale * display_grid.shape[0]))
        plt.grid(False)
        plt.imshow(display_grid, aspect='auto', cmap='viridis')
        plt.savefig("plot.png")
        
    plt.show()
    
Plotter(test_images, model)



>>> 원본 학습용 이미지 데이터 형태:  (5000, 28, 28)
원본 평가용 이미지 데이터 형태:  (1000, 28, 28)
원본 학습용 label 데이터:  [5 0 4 ... 2 1 2]
변환한 학습용 이미지 데이터 형태:  (5000, 28, 28, 1)
변환한 평가용 이미지 데이터 형태:  (1000, 28, 28, 1)

Model: "sequential_1"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv2d_3 (Conv2D)            (None, 28, 28, 32)        320       
_________________________________________________________________
max_pooling2d_3 (MaxPooling2 (None, 14, 14, 32)        0         
_________________________________________________________________
conv2d_4 (Conv2D)            (None, 14, 14, 32)        9248      
_________________________________________________________________
max_pooling2d_4 (MaxPooling2 (None, 7, 7, 32)          0         
_________________________________________________________________
conv2d_5 (Conv2D)            (None, 7, 7, 32)          9248      
_________________________________________________________________
max_pooling2d_5 (MaxPooling2 (None, 4, 4, 32)          0         
_________________________________________________________________
flatten_1 (Flatten)          (None, 512)               0         
_________________________________________________________________
dense_2 (Dense)              (None, 64)                32832     
_________________________________________________________________
dense_3 (Dense)              (None, 10)                650       
=================================================================
Total params: 52,298
Trainable params: 52,298
Non-trainable params: 0
_________________________________________________________________
None
Epoch 1/20
10/10 [==============================] - 4s 366ms/step - loss: 11.6434 - accuracy: 0.1918
Epoch 2/20
10/10 [==============================] - 4s 411ms/step - loss: 2.8053 - accuracy: 0.4942
Epoch 3/20
10/10 [==============================] - 4s 363ms/step - loss: 1.1313 - accuracy: 0.6814
Epoch 4/20
10/10 [==============================] - 4s 376ms/step - loss: 0.7214 - accuracy: 0.7814
Epoch 5/20
10/10 [==============================] - 4s 398ms/step - loss: 0.5193 - accuracy: 0.8426
Epoch 6/20
10/10 [==============================] - 4s 399ms/step - loss: 0.4148 - accuracy: 0.8766
Epoch 7/20
10/10 [==============================] - 5s 489ms/step - loss: 0.3480 - accuracy: 0.8986
Epoch 8/20
10/10 [==============================] - 4s 448ms/step - loss: 0.2965 - accuracy: 0.9146
Epoch 9/20
10/10 [==============================] - 4s 387ms/step - loss: 0.2565 - accuracy: 0.9272
Epoch 10/20
10/10 [==============================] - 5s 510ms/step - loss: 0.2211 - accuracy: 0.9364
Epoch 11/20
10/10 [==============================] - 5s 539ms/step - loss: 0.1967 - accuracy: 0.9446
Epoch 12/20
10/10 [==============================] - 5s 502ms/step - loss: 0.1722 - accuracy: 0.9504
Epoch 13/20
10/10 [==============================] - 6s 603ms/step - loss: 0.1515 - accuracy: 0.9582
Epoch 14/20
10/10 [==============================] - 5s 468ms/step - loss: 0.1365 - accuracy: 0.9636
Epoch 15/20
10/10 [==============================] - 6s 609ms/step - loss: 0.1204 - accuracy: 0.9670
Epoch 16/20
10/10 [==============================] - 5s 487ms/step - loss: 0.1080 - accuracy: 0.9704
Epoch 17/20
10/10 [==============================] - 6s 552ms/step - loss: 0.0974 - accuracy: 0.9730
Epoch 18/20
10/10 [==============================] - 4s 428ms/step - loss: 0.0861 - accuracy: 0.9766
Epoch 19/20
10/10 [==============================] - 4s 414ms/step - loss: 0.0763 - accuracy: 0.9800
Epoch 20/20
10/10 [==============================] - 4s 443ms/step - loss: 0.0681 - accuracy: 0.9834

Test Loss : 0.1878 | Test Accuracy : 0.9369999766349792
예측한 Test Data 클래스 :  [7 2 1 0 4 1 4 9 5 9]
레이어 이름:  conv2d_6
레이어 이름:  max_pooling2d_6
레이어 이름:  conv2d_7
레이어 이름:  max_pooling2d_7
레이어 이름:  conv2d_8
레이어 이름:  max_pooling2d_8

 

출처 : 2021 NIPA AI 온라인 교육 | AI(인공지능) 실무 심화 (elice.io) 

728x90
Comments