[딥러닝_기초] 3. CNN

PurinYun·2023년 12월 5일
0

AIffel

목록 보기
44/75

CNN이란?

convolution

Operator(연산자)
[2 3] * [1 1] = [2 5 3]

convolution_mask/filter

: 영상의 특징(세로선, 가로선, 대각선 등)을 찾을 수 있다.
결합법칙이 성립한다는 특징이 있다.

convolutional Neural Network

서로 다른 크기의 영상 feature를 만드는 검출 두 가지 방법은
첫 번째는 필터 사이즈를 점점 크게 만드는 것이고,
두 번째는 영상 사이즈를 점점 작게 만드는 것입니다.
→ 그렇기에 한 이미지에 여러 번의 CNN을 실시하기도 한다.

이 두가지를 모두 넣은게 convolutional Neural Network 이다.

이미지의 데이터 구조

  • RED, GREEN, BLUE의 정도 데이터인 0~255의 숫자(RGB)로 이루어진 3가지 행렬의 묶음

CNN의 작동 원리

필터 사이즈

입력 영상이 들어오면 convolution을 여러 번 해준다.

Q. 서로 다른 크기의 feature를 추출하려면 어떻게 하면 되나요?
A. Convolution layer를 여러 개 쌓으면 큰 크기가 추출

영상 사이즈

Q. 영상 사이즈를 점점 작게 만드는 방법에는 무엇이 있나요?
A. Pooling layer를 CNN의 중간 중간에 넣어줍니다.

Max pooling을 설명하고, Max pooling을 주로 사용하는 이유를 적어보세요.
A. Max pooling은 4개의 픽셀 중 가장 큰 값만 남기고 버리는 방법입니다. Max pooling을 많이 사용하는 이유는 Vanishing Gradient 문제 때문입니다. weight가 학습될 때, ‘학습되는 양 = 미분값 x 출력값’인데, 학습되는 양이 작으면 학습이 잘 안 되므로 출력값을 최대로 만들기 위해서 가장 큰 값만 사용합니다.

CNN의 구조

CNN = feature extraction(convolution + Maxpooing) + Neural Network
feature를 추출하기 위해 Convolution layer와 pooling layer를 쌓았고, 영상에서 추출된 feature를 한 줄로 세워 Neural Network로 분류합니다.

CNN은 feature extraction과 Neural Network로 이루어집니다.
feature를 추출하기 위해 Convolution layer와 pooling layer를 쌓았고,
영상에서 추출된 feature를 한 줄로 세워 Neural Network로 분류합니다.

Input 되면 convolution과 Maxpooing을 몇 번 반복
(즉, Feature extraction) 한 후에
그 결과를 Neural Network(판단)을 하여 활성화 함수를 통과시킨다.

그냥 Input 값을 그대로 통과시키기 보다
Feature extraction(convolution + Maxpooing) 을 하면
머신러닝의 성능이 향상된다.

함수 h는 Gram matrix라고 부르며 feature간 곱하기를 의미합니다. 이 Gram matrix를 사용해 영상의 스타일 정보를 추출할 수 있습니다.

pooling layer

영상 사이즈를 조절하기 위해 하는 것은 풀링을 합니다. 풀링(Pooling)은 컨볼루션 레이어의 출력을 다운샘플링하는 과정으로, 이미지의 공간적 크기를 감소시키고, 계산량을 줄이며, 특징의 공간적 변동에 대한 모델의 불변성을 증가시킵니다.

  • Max Pooling:
    이 방법은 풀링 영역에서 가장 큰 값을 선택합니다. 이는 특징 맵의 각 부분에서 가장 두드러진 특징을 캡쳐하는 데 유용합니다.

  • Average Pooling:
    이 방법은 풀링 영역의 평균 값을 계산합니다. 이는 특징 맵의 각 부분에서 전체적인 특징을 캡쳐하는 데 사용됩니다.

  • Global Pooling:
    이 방법은 풀링 영역을 전체 특징 맵으로 설정하고, 전체 특징 맵의 최대값(Max Global Pooling) 또는 평균값(Average Global Pooling)을 계산합니다. 이는 공간적 차원을 완전히 제거하고, 각 특징 맵의 전체적인 통계를 캡쳐하는 데 사용됩니다.

Convolution 레이어 구조 (1)

업로드중..

그런데 실제로 사용되는 Convolution 레이어에는 여러 개의 Convolution 필터가 있습니다. 왜냐하면 한 개짜리 필터로는 한 종류의 feature만 추출할 수 있기 때문이에요.

여러 종류의 feature를 추출하는 것이 학습에 큰 도움이 되기 때문에 여러 개의 필터를 준비합니다.

업로드중..

5 x 5 크기의 필터가 16개 있다고 하면 16 x 5 x 5 처럼 표기하고 이것을 하나의 텐서라고 나타낼 수 있습니다. 5 x 5 크기까지는 행렬이었지만 16 x 5 x 5 크기는 텐서라고 부릅니다.

16개 필터를 가진 Convolution 레이어는 16가지 종류의 feature를 추출할 수 있습니다.

이미지에는 채널이 여러 개!!

이제 이미지에 실제로 Convolution 레이어를 적용해 보고 싶은데요. 이미지 파일에 대해 약간의 배경지식이 필요합니다.

이미지 해상도가 1920 x 1080 라는 이야기는 많이 들어보셨죠? 이미지 데이터가 1920 x 1080 크기의 행렬로 이루어졌다는 이야기예요. 그런데 여기에 숨겨진 정보가 하나 더 있습니다. 바로 채널이라는 겁니다.

색상을 구성하는 3요소 - 빨강, 초록, 파랑에 대해서 들어본 적이 있으시죠? 이미지 파일도 빨강, 초록, 파랑 색상 값을 각각 따로 저장합니다. 이렇게 세 가지 색상으로 저장할 때 채널이 세 개 있다고 합니다. 물론 빨강, 초록, 파랑, 투명도의 네 개 채널로 저장할 수도 있고, 흑백 이미지처럼 단일 채널로 저장할 수도 있습니다. 일반적인 이미지는 채널이 세 개이고, 하나의 픽셀을 나타내기 위해서는 3개의 값이 필요합니다.

Q. 그렇다면 1920 x 1080 크기의 3채널 이미지를 나타내기 위해서는 얼마나 많은 값이 필요할까요?
A. 1920 x 1080 x 3 개(6220800개)의 값이 필요합니다. 계산을 직접 하지 않으셔도 좋습니다. 중요한 점은 이미지 정보는 1920 x 1080 x 3 크기의 텐서로 표현된다는 것이에요.

이제 이미지에 대한 배경지식과 Convolution 레이어를 가지고 코드로 구현해 봅시다.

import tensorflow as tf

# 1장 x 가로 1920 픽셀 x 세로 1080 픽셀 x 3채널(빨, 초, 파)
pic = tf.zeros((1, 1920, 1080, 3))
print("입력 이미지 데이터:", pic.shape)
pic_flatten_out = tf.keras.layers.Flatten()(pic)
print("이미지 데이터 값 개수: ", pic_flatten_out.shape)
print("\n")

single_conv_layer = tf.keras.layers.Conv2D(filters=1, # 1개 필터
                                    kernel_size=(5, 5),    # 5 x 5 크기
                                    use_bias=False)    # bias에 대해서는 여기서는 설명하지 않습니다.
single_conv_out = single_conv_layer(pic)
print("단일 필터 Convolution 레이어:", single_conv_layer.weights[0].shape)
print("단일 필터 Convolution 레이어의 파라미터 수:", single_conv_layer.count_params())
print("단일 필터 Convolution 결과 이미지:", single_conv_out.shape)
single_flatten_out = tf.keras.layers.Flatten()(single_conv_out)
print("단일 필터 Convolution 결과 이미지 데이터 수: ", single_flatten_out.shape)
print("\n")

multiple_conv_layer = tf.keras.layers.Conv2D(filters=16, # 16개 필터
                                    kernel_size=(5, 5),    # 5 x 5 크기
                                    use_bias=False)    # bias에 대해서는 여기서는 설명하지 않습니다.
multiple_conv_out = multiple_conv_layer(pic)
print("16개 필터 Convolution 레이어:", multiple_conv_layer.weights[0].shape)
print("16개 필터 Convolution 레이어의 파라미터 수:", multiple_conv_layer.count_params())
print("16개 필터 Convolution 결과 이미지:", multiple_conv_out.shape)
multiple_flatten_out = tf.keras.layers.Flatten()(multiple_conv_out)
print("16개 필터 Convolution 결과 이미지 데이터 수:", multiple_flatten_out.shape)

입력 이미지 데이터: (1, 1920, 1080, 3)
이미지 데이터 값 개수: (1, 6220800)

단일 필터 Convolution 레이어: (5, 5, 3, 1)
단일 필터 Convolution 레이어의 파라미터 수: 75
단일 필터 Convolution 결과 이미지: (1, 1916, 1076, 1)
단일 필터 Convolution 결과 이미지 데이터 수: (1, 2061616)

16개 필터 Convolution 레이어: (5, 5, 3, 16)
16개 필터 Convolution 레이어의 파라미터 수: 1200
16개 필터 Convolution 결과 이미지: (1, 1916, 1076, 16)
16개 필터 Convolution 결과 이미지 데이터 수: (1, 32985856)


위 결과에서 주목해야 할 것은 Convolution layer의 weight가 필터의 개수에 따라서도 달라지고, 입력 이미지의 채널에 따라서도 달라진다는 점입니다. 특히 입력 이미지의 채널에 따라 달라진다는 것은 예상하기 힘들었을 텐데요. 우리가 단일 채널 이미지만 고려해서 그렇습니다. 여러 채널이 있다면 모든 채널의 합성곱 결과를 내놓아야 한다는 점을 놓치지 않아야 합니다.

간단하게 채널이 2개라고 가정하면 아래 이미지처럼 Convolution 필터도 2채널이 필요합니다. 필터가 2개인 것과 필터의 채널이 2인 것이 다르니 혼동하시면 안 됩니다.

이미지 수, 이미지 채널 수, Convolution 필터 크기, 필터 수를 바꿔가며 위 코드를 반복적으로 실행해 보세요. 그리고 머릿속에서 그려지는 Convolution 레이어의 모습이 정확한지 천천히 확인해 보세요!

업로드중..

Convolution 레이어 구조 (2)

업로드중..

업로드중..

일반적으로 max pooling은 그 크기와 stride가 같도록 설정합니다. 2 x 2 max pooling은 stride를 2로 하고, 3 x 3 max pooling은 stride를 3으로 하는 식이에요. 겹쳐서 pooling하지 않도록 하는 것이죠. pooling 크기와 stride에 따라서 결과의 크기가 달라집니다. 보통 줄어들게 되는데요. 2 x 2 max pooling 을 2 stride로 적용하면 가로와 세로가 각각 절반이 됩니다. 면적으로는 1/4가 되죠.

Convolution과 max pooling을 함께 적용하면 아래처럼 코드를 작성할 수 있습니다. 역시 이미지 수, 채널수, convolution 필터 크기, 필터 수, pooling 크기, stride 등을 바꿔가며 스스로 이해하고 있는 내용이 맞는지 확인해 보세요!!

# 1장 x 가로 1920 픽셀 x 세로 1080 픽셀 x 3채널(빨, 초, 파)
pic = tf.zeros((1, 1920, 1080, 3))
print("입력 이미지 데이터:", pic.shape)
print('\n')

conv_layer = tf.keras.layers.Conv2D(filters=16, # 16개 필터
                                    kernel_size=(5, 5),    # 5 x 5 크기
                                    use_bias=False)    # bias에 대해서는 여기서는 설명하지 않습니다.
conv_out = conv_layer(pic)
print("16개 필터 Convolution 결과 데이터:", conv_out.shape)
print('\n')

pool_layer = tf.keras.layers.MaxPool2D(pool_size=(2, 2), strides=(2, 2))
pool_out = pool_layer(conv_out)
print("Pooling 결과 데이터:", pool_out.shape)

입력 이미지 데이터: (1, 1920, 1080, 3)

16개 필터 Convolution 결과 데이터: (1, 1916, 1076, 16)

Pooling 결과 데이터: (1, 958, 538, 16)

CNN(Convolutional Neural Network) 모델을 "Feature extractor(특성 추출기)"라고 부르는 이유는 CNN이 입력 이미지에서 저수준 특성을 추출하고 이를 조합하여 고수준의 추상적인 특성을 학습하기 때문입니다.

일반적으로 이미지 처리 작업에서 CNN은 여러 개의 합성곱(convolution) 레이어와 풀링(pooling) 레이어로 구성됩니다. 이 합성곱 레이어들은 이미지의 작은 부분을 조금씩 이동하면서 특정한 패턴이나 특징을 감지합니다. 예를 들어, 첫 번째 합성곱 레이어는 선, 에지 등과 같은 간단한 특징을 감지하고, 이러한 정보는 뒤이어 나오는 레이어들로 전달됩니다.

이후의 합성곱 레이어들은 점차적으로 더 복잡하고 추상적인 특징을 학습합니다. 예를 들어, 이전 레이어에서 감지된 선과 에지를 조합하여 패턴, 텍스처, 객체의 일부 등과 같은 고수준의 특성을 추출할 수 있습니다.

따라서 CNN은 입력 이미지에서 이러한 다양한 수준의 특성을 추출하여 이를 조합하고 결합함으로써 입력 데이터의 복잡한 구조를 파악하고 학습하는데 도움을 줍니다. 이러한 기능으로 인해 CNN은 주어진 작업에 대해 특성을 추출하는 역할을 하며, 이를 통해 효과적으로 이미지 분류, 객체 검출, 분할 등의 작업을 수행할 수 있게 됩니다.

profile
Fantivation

0개의 댓글