jblog
CNN 이론과 실습
AI

CNN 이론과 실습

Convolutional Neural Network의 핵심 개념인 Convolution, ReLU, Pooling, Flattening부터 TensorFlow로 직접 구현까지.

2025-07-317 min readcnn, deep-learning, tensorflow, keras, python, computer-vision

#CNN 이론 요약

  1. Convolution Operation
  2. ReLU Layer
  3. Pooling
  4. Flattening
  5. Full Connection
  6. Softmax & Cross-Entropy

CNN의 대가 Yann Lecun 논문 참고.

Feature Detector = Kernel = Filter

결과 메트릭스에 값이 적기 때문에 당연히 어떤 정보는 잃어버리게 된다. 그러나 특징을 감지하는 것이 중요하다. 가장 높은 숫자가 의미하는 것은 특징이 완벽하게 일치할 때 나온다.

특징은 우리가 사물을 보는 방식이자 인식하는 방식이다. 우리가 이미지를 보거나 실생활을 하면서 모든 픽셀을 살펴보는 것이 아니라 특징들을 찾는다.

#ReLU Layer

Rectifier를 사용하는 이유는 비선형을 높이기 위해서이다. 비선형을 높이려는 이유는 이미지 자체는 굉장히 비선형적이기 때문이다. 그러나 Convolution 연산을 하게 되면 선형을 만들 위험이 생긴다. 그래서 선형성을 끊어야 한다.

#Max Pooling

신경망은 공간적 불변성이라는 특성이 있는지 확인해야 한다. 특징이 이미지의 어디에 있는지는 중요하지 않다는 것이다. 특징이 약간 기울어져 있다든지, 질감이 좀 다르다든지 조금 더 가깝거나 서로 더 떨어져 있는지는 상관없다. 특징 자체가 약간 왜곡되었다면 신경망이 그 특징을 찾을 수 있을 정도의 융통성을 가지고 있어야 한다. 이것이 Pooling이다.

2x2 Matrix로 이 안에 있는 최댓값을 저장한다. 최대 숫자가 특징과의 최대 유사성을 의미하기에 여전히 특징을 보존할 수 있다. 게다가 이 특징들을 풀링하면서 특징이 아닌 정보를 75% 제거하게 되었다.

또 다른 풀링의 장점으로는:

  • 크기가 줄어든다
  • 매개 변수의 수가 줄어들어 과적합을 방지한다.

#Full Connection

Flatten의 과정까지 끝난 값은 이렇게 신경망에 연결된다. 여기서 Hidden Layer는 Fully Connected Layer라고 불린다.

역전파 과정에서 가중치가 조정되는 것뿐만 아니라 Feature Detector도 조정된다. Dog, Cat 뉴런도 학습을 통해 그 전 Layer에서의 뉴런에 가중치를 부여한다.

#Softmax & Cross Entropy

결과를 출력했을 때 두 개의 최종 뉴런이 서로 연결되어 있지 않은데, 어떻게 상대 뉴런의 값을 알고 총합이 1이 되게 했을까?

유일한 방법은 Softmax라는 함수를 제공하는 것이다. 또 소프트맥스 함수는 Cross-entropy 함수와 함께 제공된다.

CNN에서는 손실함수로 MSE보다 소프트맥스 함수를 적용하고 크로스 엔트로피 함수가 더 나은 선택지이다.

  • 출력값이 아주 작아서 경사 하강법의 경사도 낮을거라 올바른 방향으로 나아가기 어려울 것이다.
  • 반면에 크로스 엔트로피를 사용하면 안에 로그가 있어서 이런 작은 오류도 평가해서 조치할 수 있다.

크로스 엔트로피는 분류할 때만 선호하는 방법이다. 회귀 같은 것은 MSE 평균 제곱 오차가 낫다.

#CNN 실습

0. Importing the libraries

import tensorflow as tf
from tensorflow.keras.preprocessing.image import ImageDataGenerator

1. Data processing

Preprocessing the Training set

train_datagen = ImageDataGenerator(
    rescale=1./255,
    shear_range=0.2,
    zoom_range=0.2,
    horizontal_flip=True
)
 
training_set = train_datagen.flow_from_directory(
    'dataset/training_set',
    target_size=(64,64),
    batch_size=32,
    class_mode='binary'
)

rescale은 RGB의 값이 0255의 값을 가지므로, 01까지의 값을 갖도록 변환하는 것이다. shear_range, zoom_range, horizontal_flip은 이미지를 변환하는 것으로, 이미지를 변환하는 과정을 통해 과적합을 피할 수 있다.

CNN은 약한 수준의 위치 불변성만을 자동으로 학습해낼 수 있고, 크고 복잡한 변형에는 불변하지 않는다. 그래서 학습 데이터의 다양화를 위해서 데이터를 변형하고 이것을 데이터 증강이라고 부른다.

class_mode출력층 설정출력 형태손실 함수
binaryactivation=sigmoid0~1 사이 실수binary_crossentropy
categoricalactivation=softmax[1, 0] 또는 [0, 1]categorical_crossentropy

categorical은 가능하지만 비효율적이다.

Preprocessing the Test set

test_datagen = ImageDataGenerator(rescale=1./255)
test_set = test_datagen.flow_from_directory(
    'dataset/test_set',
    target_size=(64,64),
    batch_size=32,
    class_mode='binary'
)

2. Building the CNN

Initialize the CNN

cnn = tf.keras.models.Sequential()

Convolution

cnn.add(tf.keras.layers.Conv2D(filters=32, kernel_size=3, activation='relu', input_shape=[64, 64, 3]))

CNN 필터는 처음엔 랜덤한 값으로 초기화 된다. 그러나 학습을 반복하면서 유용한 형태로 변형된다.

Pooling

cnn.add(tf.keras.layers.MaxPool2D(pool_size=2, strides=2, padding='valid'))

Adding a second convolutional layer

cnn.add(tf.keras.layers.Conv2D(filters=32, kernel_size=3, activation='relu'))
cnn.add(tf.keras.layers.MaxPool2D(pool_size=2, strides=2, padding='valid'))

Flattening

cnn.add(tf.keras.layers.Flatten())

Full connection

cnn.add(tf.keras.layers.Dense(units=128, activation='relu'))

Output Layer

cnn.add(tf.keras.layers.Dense(units=1, activation='sigmoid'))

3. Training the CNN

Compiling the CNN

cnn.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])

Training the CNN on the Training set and evaluating it on the Test set

cnn.fit(x = training_set, validation_data= test_set, epochs = 25)

4. Making a single prediction

import numpy as np
from keras.preprocessing import image
test_image = image.load_img('dataset/single_prediction/cat_or_dog_1.jpg', target_size = (64, 64))
test_image = image.img_to_array(test_image)
test_image = np.expand_dims(test_image, axis = 0)
result = cnn.predict(test_image)
training_set.class_indices
if result[0][0] == 1:
  prediction = 'dog'
else:
  prediction = 'cat'

댓글

댓글을 불러오는 중...