본문 바로가기
파이썬 프로그래밍/Numpy 딥러닝

26. [CNN기초] CNN 개요

by Majestyblue 2023. 1. 1.

오랜만입니다. 2022년은 많이 바빠서 개인 연구 포스팅을 거의 못했네요. 2021년에는 선형 회귀, 분류, 기초적인 완전연결 인공신경망 Neural Net, 경사하강법, 데이터 전처리를 포스팅 하였고, 2022년에는 CNN을 천천히 하자 다짐했건만...

 

솔직히, CNN을 라이브러리없이 구현하는 것이 상당히 어려운 작업이었습니다. 올해는 또 둘째까지 돌보았기 때문에 애기들 자는 밤 10시에 같이 자는 경우가 많았죠...(ㅜㅜ) 결국 공부하고 완성하는데 1년이란 시간이 필요했습니다. 

 

각설하고 CNN이 무엇인지, 1차원 CNN, 2차원 CNN(image to column), pooling을 구현하고 마지막으로 라이브러리 없이 도형(세모,네모,원)을 구별해 보는 내용을 연재합니다.

 

1. 합성곱(CNN)을 사용하는 이유

간단하게 이야기하자면, 이미지 그 자체를 인식해야 하기 때문이다. 

https://slideplayer.com/slide/14119395/

 

 

 

 

우리들은 모두 같은 X, O로 인식한다. 하지만

컴퓨터는 이미지의 이동(translation), 확대/축소(scaling), 회전(rotation), 가중(weight)을 모두 다르게 인식한다.

https://slideplayer.com/slide/14119395/

 

 

빨간색 X 부분이 일치하지 않으므로 컴퓨터는 둘을 다르게 인식한다.

https://slideplayer.com/slide/14119395/

 

 

 

하지만 합성곱을 사용한다면 모두 같게 인식할 수 있다. 어떤 이유에서일까? 그것은 바로 필터(filter)를 이용하기 때문이다. 그렇다면 필터는 무엇이고, 어떤 역할을 할까?

 

 

 

 

 

2. 필터(Filter)

필터의 역할은 간단하다. 바로 특정 성분만 통과시키는 것이다.

공기 청정기 필터를 생각하면 쉽다. 아래와 같이 HVAC 필터는 먼지, 박테리아, 바이러스등을 막고

'공기만 통과' 시킨다.

https://www.freudenberg-filter.com/en/world-of-industrial/hvac/

 

 

 

 

 선그라스를 생각해보자.

선그라스는 자외선과 같은 고에너지를 차단하고 가시광선의 눈부심을 줄이는 역할도 한다.

 

https://livealoha.mauijim.com/polarized-tech/why-choose-polarized-sunglasses/ , https://www.apioptics.com/about-api/resources/visible-light-linear-polarizer/

 

여기서 선그라스의 중요한 특징이 나오는데, 특정 성분에 나란한 전자기장만 통과시켜 빛 세기를 줄일 수 있다는 것이다.

 

https://www.codixx.de/en/knowledge-corner/polarization

 

 

 

 

 

 

3. X 모양의 특징

X모양의 특징은 모양이 조금 달라져도, 대각선 성질이 있다는 사실이다. 

 

https://slideplayer.com/slide/14119395/

 

 

만약, 대각선 선분만 통과시키는 필터를 두었을 때, 어떤 이미지가 잘 통과한다면, 그 이미지는 X에 가깝다고 생각해 볼 수 있지 않을까? 이는 모형 O도 마찬가지다.

 

https://slideplayer.com/slide/14119395/

 

 

 

 

그렇다면 어떤 이미지에 필터를 씌워 잘 통과하는지 아닌지 어떻게 판별할 수 있을까? 간단하다. 필터와 필터 크기의 이미지 부분의 요소끼리 곱하고 전부 더하면 된다. 

 

https://indoml.com

 

 

 

 

4. 합성곱으로 확인하기

아래와 같이 간단한 예제로 확인해 보자.

 

import numpy as np

a = np.array([[1., 0., 0.],
              [0., 1., 0.],
              [0., 0., 1.]])

b = np.array([[1., 0., 1.],
              [0., 0., 0.],
              [1., 0., 1.]])

c = np.array([[0., 1., 0.],
              [1., 0., 1.],
              [0., 1., 0.]])

filter = np.array([[1., 0., 0.],
                   [0., 1., 0.],
                   [0., 0., 1.]])
                   
import matplotlib.pyplot as plt

fig, ax = plt.subplots(2, 3, figsize=(8, 5))

ax[0][0].imshow(a, cmap='gray')
ax[0][1].imshow(b, cmap='gray')
ax[0][2].imshow(c, cmap='gray')
ax[1][1].imshow(filter, cmap='gray')
plt.show()

 

 

a, b, c 그림에서 흰색은 1이고 검은색은 0이다. 

흰색은 빛이 들어오는 것이라고 쉽게쉽게 생각해 보자.

 

filter를 대었을 때 a, b, c 중 빛이 가장 많이 통과하는 것은 어느 것일까? 

합성곱을 시켜서 확인해 보자. 

 

간단하다, filter와 a, b, c를 각각 요소곱 한 후 더하면 된다.

 

out_a = np.sum(a * filter)
out_b = np.sum(b * filter)
out_c = np.sum(c * filter)
print(out_a)
print(out_b)
print(out_c)

3.0

2.0

0.0

 

a는 filter와 일치하여 3군데 빛이 통과하므로 3.0

b는 가운데가 filter를 통과하지 못하므로 2군데 빛이 통과하므로 2.0

c는 전혀 filter를 통과할 수 없으므로 0.0 이다.

 

 

 

 

5. 남자와 여자 구분하기

아래 남자와 여자의 사진이 있다. 쉽게 구분 가능할 것이다. 왼쪽이 남자, 오른쪽이 여자다.

 

질문,

남자와 여자를 구분할 수 있는 특징은 무엇일까?

일반적으로 인식하기로는

 

긴 머리일 수록 여자, 짧은 머리일 수록 남자

몸 굴곡이 부드럽고 곡선의 느낌이 들면 여자, 직각이고 단단해 보인다면 남자

 

이렇게 쉽게 볼 수 있다.

 

그렇다면, 수직(Vertical)을 검출할 수 있는 필터를 통과시킨다면 어떤 일이 일어날까?

 

방법은 이렇다. 이미지를 흑백으로, (100, 100) 사이즈로 줄이고 수직을 검출하는 (3,3)크기의 필터를 준비한다.

필터를 이용하여 이미지를 '훑는' 느낌으로 왼쪽 상단부터 시작해 오른쪽 하단까지 이동하면서 통과하는 양을 측정한다.

 

from google.colab import drive
import cv2
from google.colab.patches import cv2_imshow

drive.mount('/content/drive')

man = '...여러분들의 경로.../man.jpg'
woman = '...여러분들의 경로.../woman.jpg'

img_man = cv2.resize(cv2.imread(man, cv2.IMREAD_GRAYSCALE), (100, 100))
img_woman = cv2.resize(cv2.imread(woman, cv2.IMREAD_GRAYSCALE), (100, 100))

cv2_imshow(img_man)
cv2_imshow(img_woman)

 

 

 

 

 

 

아래 코드에 제시된 필터는 sobel 필터라고하여 x 방향의 기울기를 측정하여 수직 경계를 검출한다. 

(필터 이론은 추후에...시간이 된다면... 연재해 보겠습니다.)

여자가 남자보다 수평 성분(예를 들어 긴 머리)가 많으니 여성이 더 많이 통과하지 않을까?

 

 

sobel_vertical = np.array([[-1., 0., 1.],
                           [-2., 0., 2.],
                           [-1., 0., 1.]])

vertical_man = cv2.filter2D(img_man, -1, sobel_vertical)
vertical_woman = cv2.filter2D(img_woman, -1, sobel_vertical)

cv2_imshow(vertical_man)
cv2_imshow(vertical_woman)

print('vertical_man sum :', np.sum(vertical_man))
print('vertical_woman sum :', np.sum(vertical_woman))

 

 

 

 

예상대로다, 여성이 남성보다 수직 성분이 많아 더 많이 검출되었다. 

그런데 문제가 있다. 중성적 느낌의 사람이라면? 대표적으로 아래 사진과 같이 그룹 fx의 엠버가 있다.

다들 아시겠지만, 처음 보는 사람이라면 정말 헷갈린다. 수직 성분 검출 결과는 어떨까?

엠버, https://www.discogs.com/ko/artist/4236018-Amber-31

 

 

 

amber = '...여러분의 경로.../amber.jpg'
img_amber = cv2.resize(cv2.imread(amber, cv2.IMREAD_GRAYSCALE), (100, 100))
vertical_amber = cv2.filter2D(img_amber, -1, sobel_vertical)
cv2_imshow(vertical_amber)
print('vertical_amber sum :', np.sum(vertical_amber))

 

예상 그대로다. 수직 성분으로 남자와 여자를 판별하기 힘들다.

-> 이는 더 많은 필터가 필요함을 의미한다. 

 

 

 

정리하자면!

필터를 이미지에 합성곱한다는 것은 필터의 특징(feather)이 이미지 속에 존재한다면 통과시킨다는 뜻이고 일치율이 높을 수록 값이 크다. 이는 정량적 판단이 가능함을 의미한다! 

이를 이용해 그림의 특성을 추출할 수 있다. 

그림의 구분이 힘들다면 더 많은 필터가 필요하다