이거 새 게시물을 추가하는 법이 독특하네요.. 한참 찾았습니다..ㅠㅠ

 

저의 두 번째 게시물은 "MNIST 데이터를 CNN에 적용하여 분류하기"입니다.

 

MNIST 데이터는 [그림 1]처럼 손으로 쓴 숫자 이미지로 구성되어 있습니다.

 

[그림 1] MNIST 데이터 시각화

 

저는 이 데이터를 이용해서 실제 숫자를 예측해보겠습니다. 

 

MNIST 데이터는 Kaggle에서 다운로드하였습니다.

 

링크: https://www.kaggle.com/c/digit-recognizer/data

 

Digit Recognizer | Kaggle

 

www.kaggle.com

 

train, test, sample_submission 데이터로 구성되어 있으며 sample_submission 데이터는 제출용이니 생략합니다.

 

우선 train 데이터의 관측값은 0-9 중 숫자 하나를 손으로 적은 이미지로, 42000개의 관측값을 갖습니다.

 

이 이미지는 높이 28, 너비 28 픽셀로 총 784 픽셀입니다. 각 픽셀에는 하나의 픽셀 값이 연결되어 해당 픽셀의 밝기 또는 어두움을 나타내며 숫자가 높을수록 어두워집니다. 이 픽셀 값은 0에서 255(포함) 사이의 정수입니다.

 

train 데이터의 맨 앞 열은 이미지에 있는 숫자를 나타내고 나머지 784개의 열은 해당 이미지가 갖고 있는 784개의 픽셀을 의미합니다.

 

따라서 맨 앞 열은 label 변수로 0-9 값을 갖고 나머지 784개의 열은 0에서 255 값을 갖습니다.

 

test 데이터는 label을 제외한 변수를 갖고 있으며 28000개의 관측값을 갖습니다.

 


MNIST 데이터 실습은 아래 항목으로 구성됩니다.

 

1. Colab으로 파일 불러오기

 

 1-1. 구글 마운트 하기

 1-2. 파일 불러오기

 

2. 데이터가 어떻게 생겼을까

 

3. 데이터를 전처리 하기

 

 3-1. train에서 label은 target, 나머지는 x_train으로 분리합니다.

 3-2. 데이터 표준화를 합니다.

 3-3. CNN모델 입력 형태로 차원을 변환합니다.

 

4. 모델 형성하기

 

5. 전체 코드

 


 

 

그럼 시작하겠습니다.

 

저는 Google Colaboratory를 이용하기 때문에 Colab 환경에 맞춰서 진행하겠습니다.

 

1. Colab으로 파일 불러오기

 

Colab으로 파일을 불러오는 방식은 다양합니다. 저는 Google Mount를 평소에 사용하기 때문에 이걸로 가겠습니다.

 

1-1. 구글 마운트 하기

 

 

위와 같이 코드를 치면 authorization code를 입력하는 란이 나옵니다. 위의 파란색 url에 접속하면 code를 받을 수 있습니다. code를 복사하여 입력란에 붙여 넣고 Enter를 치면 됩니다.

 

1-2. 파일 불러오기

 

위와 같이 입력하면 csv파일을 불러올 수 있습니다.

 

 

2. 데이터가 어떻게 생겼을까

 

train, test 데이터의 size를 알 수 있습니다. 

 

이번에는 train 데이터 42000개 중 0부터 3번째 데이터를 이미지로 직접 나타내 보겠습니다.

 

 

 

3. 데이터를 전처리하기

 

3-1. train에서 label은 target, 나머지는 x_train으로 분리합니다.

 

 

3-2. 데이터 표준화를 합니다.

 

 

픽셀이 0~255의 정수 값을 갖기 때문에 255로 나눠서 표준화하였습니다.

 

3-3. CNN모델 입력 형태로 차원을 변환합니다.

 

 

 

4. 모델 형성하기

 

[그림 2]에서는 이번 실습 때 사용하는 CNN 모델 프로세스를 자세히 보여줍니다.

 

[그림 2] CNN 프로세스

 

직접 코드로 구현해봅시다.

 

아래의 코드를 봅시다.

 

우선 모델 형성에 필요한 패키지를 설치하고요.

 

 

모델 층을 쌓는 코드에는 중간중간 설명을 적겠습니다. (하단에 정리한 코드 올려놓았습니다.)

 

model=keras.Sequential([

 

Sequential은 신경망 층을 쌓을 때 사용합니다.

앞으로 나오는 각 코드를 우리는 하나의 계층이라고 하겠습니다.

 

keras.layers.Conv2D(32, kernel_size=(3,3), input_shape=(28,28,1), padding='SAME', activation=tf.nn.relu)

 

첫 번째 층은 컨볼루션층입니다

맨 앞(32): Kernel(Filter) 수입니다.

kerel_size: Kernel의 크기를 지정합니다.

input_shape: 샘플 수를 제외한 입력 형태를 정의합니다. (행, 열, 채널 수)로 정의합니다.

                   (채널은 색상(R, G, B)을 의미하고 사용하는 데이터는 흑백 이미지이기 때문에 채널 수가 1입니다.)

Padding: padding이 'SAME'이면 출력 데이터 사이즈와 입력 데이터 사이즈가 동일합니다.

Activation: 활성화 함수를 설정합니다.

 

keras.layers.MaxPool2D(pool_size=(2,2), strides=(2,2), padding='SAME')

 

다음은 MaxPooling 계층입니다.

pool_size: Pooling 영역의 크기입니다.

strides: Pooling 영역이 이동하는 간격을 의미합니다.

 

keras.layers.Conv2D(64, kernel_size=(3,3), padding='SAME', activation=tf.nn.relu),

keras.layers.MaxPool2D(pool_size=(2,2), strides=(2,2), padding='SAME')

 

위의 코드를 반복합니다. (본 실습에서는 컨볼루션층을 두 번 거칩니다.)

 

keras.layers.Flatten()

 

앞에서는 Image data의 Feature Maps를 추출했습니다. 이번에는 실제 숫자로 분류하는 작업을 해보겠습니다.

Flatten 계층을 이용하여 3차원의 데이터를 1차원으로 변환합니다.

 

keras.layers.Dense(1024, activation='relu')

 

이후 완전 연결 계층 (Dense)를 적용합니다.

units: 1024는 완전 연결 계층을 거친 후 나오는 출력 데이터의 수를 의미합니다. 

 

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

 

마지막 완전 연결 계층은 units이 10이고 활성화 함수가 Softmax 입니다.

 

0에서 9 사이의 숫자를 예측하기 때문에 10개의 클래스로 분리됩니다.

따라서 이 계층을 지난 후 나오는 출력 데이터의 수가 10이 되어야 하구요.

 

활성화 함수로 Softmax를 쓰면 각 클래스로 예측될 확률을 알 수 있습니다.

예를 들면, 1로 분류될 확률이 0.1, 2로 분류될 확률이 0.3 등 (확률의 전체 합은 1이겠죠?!)

 

keras.layers.Dropout(0.25)

 

마지막으로 Dropout 계층입니다.

Dropout 계층은 과적합(over-fitting)을 막기 위한 방법으로 신경망이 학습 중일 때, 무작위로 신경망을 빼서 모델 학습을 방해함으로써, 과적합을 방지합니다.

 

[그림 3] CNN 모델 계층 정보

 

[그림 3]는 형성한 모델의 각 계층을 지나면서 출력되는 Output의 차원을 보여줍니다.

(Output Shape에서 확인 가능합니다.)

 

5. 전체 코드

 

다음과 같습니다.

 

from google.colab import drive
drive.mount('/content/drive')

import pandas as pd
test=pd.read_csv('/content/drive/MyDrive/test.csv')
train=pd.read_csv('/content/drive/MyDrive/train.csv')
sample_sub=pd.read_csv('/content/drive/MyDrive/sample_submission.csv')

print("Train Data Size: ", train.shape)
print("Test Data Size: ", test.shape)

import matplotlib.pyplot as plt
import numpy as np
plt.style.use('seaborn')
fig, ax = plt.subplots(1,4, figsize=(10,10))
fig.tight_layout(pad=0.0)

for col in range(4):
    im_0 = np.array(train.drop("label", axis=1). iloc [col]). reshape(28,28)
    ax [col]. imshow(im_0, cmap="gray")
    ax [col]. axis("off")

target = train ['label']
x_train = train.drop('label', axis = 1)

x_train=x_train/255
test=test/255

x_train = np.array(x_train). reshape((-1,28,28,1)) 
x_train.shape

test = np.array(test). reshape((-1,28,28,1))
test.shape

from tensor flow.keras.utils import to_categorical
target = to_categorical(target, num_classes = 10)
target.shape

import tensorflow as tf
from tensorflow import keras

model=keras.Sequential([
keras.layers.Conv2D(32, kernel_size=(3,3), input_shape=(28,28,1), padding='SAME', activation=tf.nn.relu),
keras.layers.MaxPool2D(pool_size=(2,2), strides=(2,2), padding='SAME'),
keras.layers.Conv2D(64, kernel_size=(3,3), padding='SAME', activation=tf.nn.relu),
keras.layers.MaxPool2D(pool_size=(2,2), strides=(2,2), padding='SAME'),
keras.layers.Flatten(),
keras.layers.Dense(1024, activation='relu'),
keras.layers.Dense(10, activation='softmax'),
keras.layers.Dropout(0.25)])

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

 

model.summary() #각 계층별 출력 데이터의 차원을 확인하실 수 있습니다.

 

model.fit(x_train, target, epochs=5) #모델 학습

 

pred=np.argmax(model.predict(x_train), axis=-1) #분류한 결과를 확인하실 수 있습니다.

 


 

출처 1: https://www.kaggle.com/mhmdsyed/digital-recognizer-simple-cnn-model

 

Digital Handwriting Recognizer ✍️ |

Explore and run machine learning code with Kaggle Notebooks | Using data from Digit Recognizer

www.kaggle.com

출처 2: https://dsbook.tistory.com/71?category=780563 

 

합성곱 신경망, Convolutional Neural Network (CNN)

완전 연결 계층, Fully connected layer (JY) Keras 사용해보기 1. What is keras? 케라스(Keras)는 텐서플로우 라이버러리 중 하나로, 딥러닝 모델 설계와 훈련을 위한 고수준 API이다. 사용자 친화적이고 모델의

dsbook.tistory.com

제가 블로그가 처음이라서 출처를 어떻게 남기는지, 직접 말씀드려야 하는지 잘 모르겠습니다.. 

만약 이 방법이 틀렸음 알려주신다면 감사드리겠습니다!

피드백, 질문 언제든지 환영입니다!!

 

다음은 RNN 이론을 올리겠습니다!

CNN은 Convolutional Neural Networks의 줄임말로 알다가도 모르는 기법이다.

그래서 이론을 확실히 하기 위해서 CNN 개념 및 원리를 올려본다.

 

최대한 알기 쉽게 설명하도록 하겠다. 피드백은 언제나 환영이다. 댓글도 Welcome이다.

 

이 글의 항목은 아래와 같다.

 

 

1. CNN의 NN, Neural Networks(신경망) 이란 무엇인가?

2. CNN이란 무엇인가?

 

 

 

1. CNN의 NN, Neural Networks(신경망) 이란 무엇인가?

 

 

  [그림 1]은 신경망의 원리를 잘 보여주는 예시로, 이 예시를 바탕으로 신경망을 설명하겠다.

 

[그림1] Neural Network 원리

 

  Step.1 Inputs은 데이터를 넣는 곳으로 만약 데이터 [1,2,3,4,5]를 신경망에 넣고 싶으면 Inputs에 [1,2,3,4,5]를 할당하면 된다. (x1=1, x2=2,..., x5=5) 

 

  Step.2 w1부터 w5는 가중치이다. 가중치와 Inputs의 각 원소를 곱한다.

     (x1*w1, x2*w2,..., x5*w5)

 

  Step.3 Step.2에서 구한 가중치와 원소의 곱을 모두 합한다.

     (x1*w1+x2*w2+...+x5*w5)

 

  Step.4 Step.3에 활성화 함수를 씌워서 출력한다. 활성화 함수는 Activation Function이며, 시그모이드, 렐루, 소프트 맥스 등이 사용된다.   

 

 

 

2. CNN이란 무엇인가?

 

 

2번 섹션은 세 개의 항목으로 나눴다.

 

2-1. 합성곱(Convolution)을 알아보자

2-2. CNN의 프로세스를 통째로 알아보자

2-3. CNN의 프로세스를 세부적으로 알아보자

 

1번 섹션에서는 1차원 데이터를 신경망에 적용했다. 그렇다면 이미지와 같은 2차원 데이터는 어떻게 신경망에 적용할까? 

 

정답은 지금부터 알아볼 CNN이다.

 

CNN은 Convolutional Neural Networks의 약자로, 핵심은 신경망에서 사용된 연산을 합성곱으로 교체한 것이다.

 

새로운 개념이 나왔다.

 

합성곱이 무엇일까? 2-1 섹션에서 차근차근 알아보자.

 

 

2-1. 합성곱(Convolution)을 알아보자

 

 

합성곱은 곱셈과 덧셈으로 이루어진 연산이다.

 

[그림 2]에서 행렬 A와 행렬 B를 합성곱 하여 행렬 C를 만들었다.

 

행렬 A와 행렬 B의 차원이 다른데 어떻게 곱셈이 가능할까?

 

정답: 행렬 A 위에서 행렬 B를 이동시키며 겹치는 원소들끼리 곱하고 더한다.

 

[그림2] 합성곱의 원리

 

[그림 2]를 단계별로 설명해보겠다.

 

Step 0. 행렬 A 위에 행렬 B를 올려놓는다.([그림 2]의 빨간색 네모 위에 행렬 B를 올려놓는다)

 

Step 1. 행렬 A의 빨간색 네모와 행렬 B의 각 원소를 곱하고 모두 더하면 행렬 C의 첫 번째 원소 7이 나온다.

(실제 계산: 1*1+0*0+2*0+0*2+2*1+1*3+0*0+2*0+1*1=7)

 

Step 2. 이제 행렬 B를 오른쪽으로 이동시킨다.

행렬 A와 겹치는 부분의 각 원소를 곱하고 모두 더한다. 행렬 C의 두 번째 원소 6이 나온다.

 

Step 3. 이번에는 행렬 B를 대각선 아래로 이동시킨다.

행렬 A와 겹치는 부분의 각 원소를 곱하고 모두 더한다. 행렬 C의 세 번째 원소 7이 나온다.

 

Step 4. 마지막으로 행렬 B를 왼쪽으로 이동시킨다.

[그림 2]에서 행렬 A의 파란색 네모와 행렬 B의 각 원소를 곱하고 모두 더하면 행렬 C의 네 번째 원소 10이 나온다.

 

Step 5. 이렇게 행렬 B가 행렬 A 위를 다 돌고 나면 행렬 C가 완성된다. 이 과정에서 사용된 연산이 바로 합성곱이다.

 

 

2-2. CNN의 프로세스를 통째로 알아보자

 

 

[그림 3]은 CNN의 원리로, 컴퓨터에서 CNN을 통해 이미지를 숫자 2로 분류하는 과정을 보여준다.

 

[그림 3]으로 CNN의 프로세스를 설명해보겠다.

 

우선 Input Data에 들어간 이미지 데이터가 가진 특징들을 추출하는 Feature Extraction 작업을 거친다.

이후 자동차 이미지면 자동차, 숫자 2 이미지이면 숫자 2 등으로 분류하는 Classification 작업을 거친다.

 

[그림 3]은 이미지를 0에서 9 사이의 숫자 중 하나로 분류하는 과정이다.

 

[그림 3] CNN의 원리

 

좀 더 알아보자.

 

Step 1. Image Data에 Padding을 하여 Input Data에 넣는다. 여기서 Padding은 '덧댄다'는 의미로, 합성곱 작업을 거치면 결과의 차원이 줄어드는 문제를 방지하기 위하여 Input Data의 모서리에 0이나 다른 숫자를 덧대는 작업을 한다.

(Padding 은 2-3 섹션에서 자세히 알아보자)

 

Step 2. 특성 맵(Feature map)을 추출하기 위하여 Input Data와 Filter를 합성곱(Convolution) 한 후 Relu라는 활성화 함수를 씌운다. [그림 3]에는 네 개의 Filter가 있다. Input Data와 네 개의 Filter를 각각 합성곱 한 후 활성화 함수를 적용하면 네 개의 특성 맵(Feature Maps)이 나온다.

 

Step 3. Feature Maps의 차원의 복잡성을 줄이면서 유의미한 정보는 유지하기 위해 Max Pooling을 이용한다.

(Pooling은 2-3 섹션에서 자세히 알아보자)

 

Step 4. Flatten을 통하여 3차원의 Feature Maps(Step 3의 결과)를 1차원의 형태로 변형시킨다.

 

Step 5. Step 4의 결과를 완전 연결 신경망에 적용한 후 0에서 9 사이의 숫자일 확률을 구하기 위해 Softmax 함수를 적용한다. CNN에 입력한 이미지 데이터가 0일 확률부터 9일 확률까지 알 수 있다.

 

Step 6. Step5의 결과에 최대의 확률을 가진 값을 구하는 argmax함수를 적용한다. [그림 3]의 Output에서 2로 분류된 것을 알 수 있다.

 

 

2-3. CNN의 프로세스를 세부적으로 알아보자

 

 

1) Padding

 

CNN에서 이미지의 특징을 추출하기 위하여 Filter와 합성곱 하는 과정을 거친다.

이후 차원이 축소되면서 정보가 손실되는 경향을 보이는데, 차원이 줄어드는 것을 예방하기 위해 사전 작업으로 이미지 데이터에 Padding(덧대기)를 한다. 

 

[그림 4]는 Padding 예시이다.

 

[그림4] Padding 예시

 

Padding은 두 가지 방법이 있다. 하나는 [그림 4]와 같이 데이터의 테두리에 0을 덧대는 방법, 다른 하나는 데이터의 테두리 값을 복사하여 덧대는 방법이 있다. 

 

[그림 4]처럼 테두리에 0을 덧대면 합성곱 이후에도 차원이 유지됨을 알 수 있다.

 

 

2) Filters

 

CNN에서 Input Data와 Filter를 합성곱 한 후 Input Data의 특성 맵(Feature Map)이 추출된다.

 

Filter가 어떤 값을 가지느냐에 따라서 추출되는 특성 맵이 달라지고 Input Data를 얼마큼의 간격으로 이동하느냐에 따라서도 달라지는데 이 간격을 'Stride'라고 한다. 또한 n개의 Filter를 이용하면 n개의 특성 맵이 추출된다. 

 

참고로 CNN에서 Filter와 Kernel은 같은 의미이다.

 

 

이해를 돕기 위해 [그림 5]를 보며 설명하겠다.  

 

[그림 5] Filter 적용 예시

 

[그림 5]는 Padding을 씌운 Input Data와 Filter의 합성곱을 나타낸다. 이때 Filter의 수는 한 개라서 하나의 특성 맵이 추출되고 Filter가 Input Data 위를 이동하는 간격은 2이다. 

 

[그림 5]에서 Input Data의 빨간색 네모와 Filter와 연산하여 Feature Map의 빨간 부분이 계산되고 2칸을 이동한 Input Data의 주황색 네모와 Filter와 연산하여 Feature Map의 주황색 부분이 계산된다. 이런 식으로 반복하면 하나의 Feature Map이 완성된다. 

 

 

3) Pooling

 

Pooling은 특성 맵을 스캔 하여 최댓값을 고르거나 평균값을 계산하는 것을 의미한다. 보통 연구자들은 최댓값을 고르는 Pooling 방식(Max Pooling)을 선호한다. 그 이유는 Input Data에서 각 Filter가 찾고자 하는 부분은 Feature Map의 가장 큰 값으로 활성화되는데 Max Pooling 방식은 Feature Map의 차원은 줄이면서 유의미한 정보이자, 가장 큰 특징은 유지시키는 성질이 있기 때문이다. 

 

[그림 6]은 Max Pooling의 예시이다.

 

[그림 6] Max Pooling 예시

 

하나의 Feature Map이 있으면 이 위를 풀링 영역이 지나가면서 최댓값을 가져온다. 풀링 영역은 사용자가 지정할 수 있으며 보통 2x2를 크기로 지정한다. 그리고 이동 간격(Stride)은 풀링 영역의 한 모서리 크기로 지정한다.

 

[그림 6]에서 첫 번째 풀링 영역에서 최댓값 5를 뽑아내고 두 칸 이동한 두 번째 풀링 영역에서 최댓값 8을, 왼쪽 대각선 아래로 이동한 세 번째 풀링 영역에서 최댓값 5를, 두 칸 이동한 네 번째 풀링 영역에서 최댓값 4를 뽑아낸다.

 

 

다음 게시물에서는 MNIST DATA가 CNN에서 어떻게 굴러가는지 Python 실습을 통해 알아보자

+ Recent posts