기록하는삶

[딥러닝/DL Basic] CNN (1) _ 기초 개념 및 용어 정리 본문

AI/DL Basic

[딥러닝/DL Basic] CNN (1) _ 기초 개념 및 용어 정리

mingchin 2022. 2. 8. 21:08
728x90
반응형

CNN(Convolutional Neural Network)을 이해하기 위한 기초 개념 및 용어들을 정리해본다.

1) Convolution

수학적 정의의 '합성곱'을 말한다. 합성곱 연산은 두 함수 f, g 가운데 하나의 함수를 반전(reverse), 전이(shift)시킨 다음, 다른 하나의 함수와 곱한 결과를 적분하는 것을 의미하는데, f, g가 연속이냐 이산이냐에 따라 아래 두 가지 표현이 가능하다.

cross-correlation
출처: 위키백과

기계학습에서 다루게 되는 CNN은 주로 이미지의 픽셀을 다루기 때문에 'Discrete convolution'이라 이해하면 되겠고, 사실 아주 정확히는 convolution이라기보다 cross-correlation 연산을 하는 것이라 표현해야 맞다고 한다. 그러나 f를 적당히 조작한 함수와 g의 cross-correlation은 f,g 사이의 cross-correlation과 동일한 의미를 가지기도 하고(즉, 큰 틀에서 보면 같은 말이다.), 범용적으로 convolution이라 표현한다.

 

2) 기계학습에서의 Convolution과 filter(kernel)

이 글에서는 기계학습에서 말하는 convolution, 그 중에서도 이미지에 한해 그 의미를 살펴본다. convolution layer를 통해 결국 하고 싶은 것은, 픽셀로 표현된 이미지의 형상은 어느정도 유지하면서, 의미있는 feature들을 추출하는 것이다. 이를 가능하게 해주는 것이 filter와 convolution 연산이다.

7*7 이미지에 3*3 filter를 (padding, stride x _ 아래에 설명) 적용한 2D convolution의 예시이다. 특정 크기를 갖는 n*n filter를 이용해 원본 이미지에서의 픽셀값들과의 합성곱을 계산하고, 이를 output의 하나의 픽셀 값에 저장한다. 즉, 3*3 filter를 적용하는 경우에는 원본 이미지에서의 9개의 픽셀과 filter의 9개 픽셀로 합성곱을 연산, 하나의 결과물을 만들어 새로운 픽셀에 저장하게 되며, 이는 곧 9개의 픽셀이 차지하던 영역을 대표하는 feature가 저장된 픽셀이 되는 것이다. 한 이미지에 대해 동일한 filter를 이용하되 그 위치를 옮겨가며 이러한 연산을 반복수행하여 output을 만들어내면, 이 결과물이 바로 feature map이 된다. filter는 kernel이라 칭하기도 하며, 여기서 중요하게 기억해야 하는 것은 해당 연산을 수행할 때 filter의 weights(파라미터)를 고정하여 동일하게 사용하기 때문에, 단 9개의 파라미터로 이것이 가능하다는 점이다.

 

2-1) filter(kernel)의 종류와 기능

이러한 filter의 종류와 기능에는 다양한 것들이 있지만, 간단한 예시로 이해해보면 아래와 같다.

엠보싱은 필터링은 물체의 윤곽을 뚜렷하게 볼 수 있도록 해주며, 블러링은 스무딩(smoothing)이라고도 불리는, 평균값 필터를 이용해 영상을 부드러운 느낌으로 만드는 방법이다. 이렇게 단순한 convolution 연산을 통한 filtering 외에도 가우시안 필터, 잡음 제거 필터, 미디언 필터 등의 방법이 있다. 사용한 코드는 아래.

def kernel(src,filter_name):
    filters = {'embosing': np.array([[-1,-1,0],[-1,0,1],[0,1,1]]),
              'blurring': np.ones((3, 3))/9}
    kernel = filters[filter_name]
    src = cv2.imread(src, cv2.IMREAD_GRAYSCALE)
    if src is None:
        print('image load failed!')
        return
    dst = cv2.filter2D(src, -1, kernel)
    fig = plt.figure(figsize=(12, 5))
    ax1 = fig.add_subplot(131,aspect=1)
    ax2 = fig.add_subplot(132)
    ax3 = fig.add_subplot(133)
    for i in range(4):
        ax1.plot((i,i),(0,3),color='black')
        ax1.plot((0,3),(i,i),color='black')
    for ax in [ax1,ax2,ax3]:
        ax.get_xaxis().set_visible(0)
        ax.get_yaxis().set_visible(0)

    for i in range(3):
        for j in range(3):
            ax1.text(i+0.5,j+0.5,np.round(kernel[2-j][i],2),va='center',ha='center',fontsize=25)
    ax2.imshow(src)
    ax3.imshow(dst)
    
    ax1.set_title(f'filter name: {filter_name}')
    ax2.set_title('original')
    ax3.set_title('filter applied')
    
    plt.show()
    
image = './image/lenna.jpg'
kernel(image,'embosing')

kernel(image,'blurring')

위 예시들이 channel이 1개인 grayscale의 이미지에 대한 예시였다면, channel이 3인 RGB 이미지 역시 마찬가지 방법을 따른다. 

위 예시는 32*32*3 이미지를 5*5*3 filter를 이용해 convolution을 반복 수행하는 것으로, 이때 아래의 사항에 유의해서 이해해야한다. (하이라이트 부분은 각 layer의 channel의 수, 이미지의 깊이라고 생각하면 된다.)

convolution이 수행되기 위해서는 input의 channel과 일치하는 channel을 갖는 filter가 필요하며, 그 width와 height는 모두 홀수이어야한다.

-> 즉, 위의 예시에서는 처음에는 5*5*3 filter가, 그 다음에는 5*5*4 filter가, 그 다음에는 5*5*10 filter가 필요한 상황

② 알맞은 size의 filter를 사용해 convolution이 수행되면, 그 결과는 output featuremap의 1개의 channel을 형성한다. output featuremap의 channel이 k가 되도록 설계하고 싶다면, k개의 서로 다른 filter를 사용해야한다.

-> 위의 예시에서는 5*5*3 filter가 4개, 5*5*4 filter가 10개, 5*5*10 filter가 k개 사용되는 상황이다.

 

어떤 'width*height*channel'을 갖는 filter를 몇 개 사용할 것인지는 필요한 파라미터의 수와 연결되는 문제이므로, 명확히 이해할 필요가 있다.

 

2-2) Stride & Padding

convolution을 진행하는 동안 filter를 움직여가며 연산을 반복한다고 했는데, 한 번에 몇 칸씩 옮길지, 그 간격이 stride다. 위의 예시들은 모두 stride=1인 예에 해당한다. 또한 convolution 연산은 여러 개의 픽셀들로 하나의 feature값을 생성하기 때문에, 위 예시처럼 활용하면 이미지의 크기가 계속해서 줄어들 수밖에 없는데, 이를 방지하기 위한 방법이 padding으로, 원본 이미지의 가장자리에 tensor를 임의로 추가하는 것을 말한다. padding=n이라면 원본 이미지의 width와 height 방향으로 n칸의 픽셀을 추가하는 것이며, 보통 0의 값으로 추가하는 zero-padding을 실시한다. (padding의 사이즈 = filter의 width//2)로 설정하면 원본 이미지의 width, heght와 output feature map의 width, heght를 같도록 하여 원본 이미지의 크기를 보존할 수 있다.

 

2-3) Pooling

주로 convolution 연산을 통해 얻어진 feature map에 적용하여 그 크기를 줄이는 down sampling 기법으로, 특정 영역에서 최댓값을 갖는 픽셀 하나만 택하는 max pooling과 영역에 있는 모든 픽셀의 평균값을 대표값으로 택하는 average pooling이 있다. convolution처럼 stride 개념을 적용할 수 있다.

출처: 위키독스

위는 stride=2 인 2*2 max pooling의 예시다. pooling 연산은 파라미터를 필요로하지 않으며, 수행하더라도 channel의 수가 변하지 않는다.

3) CNN(Convolutional Neural Network)

위의 예시와 같은 convolution layer가 포함된 뉴럴네트워크를 CNN이라 한다. 전통적인 CNN의 경우 convolution layer, pooling layer를 통해 feature들을 추출하고, 이후 fc(fully connected) layer를 통해 분류, 분할 등의 의사결정을 하는 구조를 가졌으나 이후 fc layer를 fully convolutional layer로 대체하거나, 1*1 convolution을 통해 파라미터의 수를 줄이거나, identity map을 추가하는 등의 기법이 적용된 발전된 모델들이 등장하고 있다. (이후 중요한 내용들은 추가로 정리해본다.)

 

4) Convolution Arithmetic

지금까지 정리한 내용을 바탕으로 하면, padding과 stride, kerner size와 이미지의 width, height, channel이 주어진다면 필요한 파라미터의 수를 구할 수 있다. 이후 추가로 정리하겠지만, 2012년 Alexnet을 시작으로 CNN 모델에 대한 연구와 발전이 이루어지면서 파라미터의 수를 줄이면서도 이미지의 feature들을 잘 추출해내는 것이 모델의 성능을 높이는 방법이라는 것이 알려졌다고 한다. 따라서 CNN 모델을 이해하는데 있어 아키텍쳐를 보고 대략적인 파라미터의 수를 파악할 줄 아는 것이 중요하다.

 

위 예시의 구조에서는 input channel이 128이므로, 3*3*128의 kernel이 필요하고, output channel을 64로 만들고 싶기 때문에 총 64개의 kernel이 필요하다. 따라서 필요한 파라미터의 개수는 3*3*128*64 = 73728개이다.

 

4-1) 1x1 Convolution

이미지의 feature들을 어느정도 유지하면서 필요한 파라미터의 수를 줄일 수 있는 방법 중 하나가 1*1 convolution이다.

input에 사용하는 kernel의 channel의 수가 곧 output의 channel의 수와 같다는 점을 이용해, 그림의 예시처럼 연산을 진행하게 되면 동일한 크기(width & height)를 갖되 channel만 줄어든, 일종의 압축된 결과물을 얻을 수 있다.

이런 방법을 적절히 활용하면, 훨씬 더 적은 파라미터의 연산만으로 동일한 output dimension을 얻을 수 있다.

 

728x90
반응형