37. ConvNet의 Conv 레이어 만들기 (lec 11-1)


여기부터 Deep Learning의 후반부라고 볼 수 있다. 전체 동영상을 공부한 이후에도 할게 많지만, 이전까지는 기초, 여기부터는 중급이 된다.


이렇게 어려운 내용을 1959년부터 누가 연구했다. 고양이가 사물을 볼 때의 뇌를 연구해 보니까, 뇌 전체가 아닌 일부만 활성화된다는 사실을 발견했다.


CNN(Convolutional Neural Network)이 얼마나 복잡한지 보여주셨다. CONV와 RELU가 한 쌍으로 구성되고 중간중간 POOL이 들어가 있다. 마지막에는 FC가 있다. POOL은 pooling(sampling, resizing)을 말하고, FC는 fully connected network을 말한다. 이렇게 여러 장의 layer를 연결하고 나니까, deep learning처럼 보인다.


몇 장의 비슷한 그림이 계속 등장한다. 그림 크기는 32x32이고 색상을 갖고 있기 때문에 3(red, green, blue)을 곱했다. 픽셀(pixel, 화소) 1개는 흑백의 경우 1바이트를 사용하기 때문에 256단계의 gray scale을 표현할 수 있고, 컬러의 경우 RGB에 1바이트씩 할당하기 때문에 256x256x256만큼의 색상을 표현할 수 있다.


그림 일부를 덮는 필터가 있다. 여기서 중요한 것은 색상에 해당하는 3은 항상 같아야 한다는 점이다. 색상을 1로 지정하는 것은 RGB 중에서 빨강에 해당하는 요소만 처리하겠다는 뜻이다. 특별한 경우에는 필요하겠지만, 일반적으로는 달라야 할 이유가 없으니까, 항상 똑같은 값으로 지정한다. 뒤에서 나오는데, input layer의 색상은 hidden layer의 filter와 같은 개념이다. 그래서, "filter가 3개 있다"라고 얘기해도 된다.


필터가 차지하는 영역으로부터 읽어온 값을 공식을 통해 하나의 값으로 변환한다. Wx+b는 지속적으로 등장하는 공식인데, 여기서 W와 x는 누구를 가리키는 것일까?

W는 weight에 해당하는 값으로 여기서는 필터(filter)에 해당한다. W를 찾는 것이 deep learning의 목표라고 한다면, 올바른 필터를 찾는 것이 CNN의 목표라고 할 수 있다. x는 외부에서 읽어온 값으로 이 값은 바뀌지 않는다. 여기서는 이미지에 해당한다.

one number에 해당하는 값을 얻기 위해 Wx+b의 결과를 ReLU에 전달한다. sigmoid가 아니니까, 음수가 아닌 값을 1개 얻게 된다. 그렇다면, 5x5x3에 대해서 1개의 값을 얻었다면, 전체에 대해서는 몇 개의 값이 나올지 궁금할 것이다. 조금만 참자!


동일한 필터를 사용해서 다른 영역도 조사한다. 5x5x3 크기의 필터를 수평과 수직으로 움직인다. Wx에서 W는 동일한 layer에 대해 같은 값으로 계속 사용하고, x의 값을 모두 읽게 되면 layer 하나가 끝나게 된다. 그래서, 제목에 same filter(W)라고 되어 있다.


앞에 나온 그림과 똑같은데, 필터가 가리키는 곳이 바뀌었다.


수평과 수직에 대해 모두 반복해서 처리한다. 필터 영역에 대해 하나의 값으로 변환하는 작업. 그렇다면, 모두 반복했을 때 얻게 되는 값은 몇 개일까? 수평과 수직으로 움직이는 규칙을 알아야 계산할 수 있다. 지금은 모른다.

수평으로 4번, 수직으로 7번 이동했다면 4x7만큼의 숫자를 얻게 된다. 이 때, 32x32x3에 들어가 있는 3은 반영되지 않는다. 4x7x3이 되어야 한다고 생각할 수도 있다. 5x5x3으로 계산해서 one number를 얻기 때문에 3이 나올 수가 없다. 그리고, 색상(filter)의 갯수는 생략하면 계산이 쉽기 때문에 생략할 때도 있다.

5x5로 계산한다면 3번 계산해야 하므로 4x7x3이 되는 것이 맞지만, 우리는 5x5x3으로 계산했다. 계산에 사용한 4와 7은 몇 개가 나오는지 알려주기 위해 고른 숫자일 뿐이다. 의미를 부여하지 말자.


필터가 움직이는 규칙을 살펴보려고 한다. 필터의 크기는 그림에 있는 것처럼 3x3이다. 필터를 적용할 그림의 크기는 7x7이다. 색상 갯수는 무시한다.


만약에 필터를 한 칸씩 이동시킨다면 출력의 결과는 5x5가 된다. 왼쪽 끝에서 5번 이동하면 오른쪽 끝에 닿기 때문에 5번까지만 이동할 수 있다.


그러나, 굳이 한 칸씩 움직일 필요는 없다. 두 칸씩 움직여보자. 출력 크기는 3x3이 된다. 필터가 이동하는 크기를 stride라고 부른다. 잘 이해가 안 되면, 잠시 읽는 것을 멈추고 손으로 그려보길 바란다. 그러면 된다.

3x3의 출력이라는 것은 말그대로 가로세로 3픽셀 크기의 결과를 얻었다는 뜻이다. 필터의 크기 때문에 원본보다 작아질 수밖에 없는 구조다. 1x1 크기의 필터를 사용하면 크기는 줄지 않겠지만, 이미지의 특성을 추출하기 어려울 수 있다. 뒤에서 1x1 크기의 필터를 사용하는 것과 비슷한 효과를 주는 방법이 나온다.


input, output, stride 사이에는 쉬운 규칙이 있다.

  출력 크기 = 1 + (입력 크기 - 필터 크기) / stride 크기

여기서 중요한 것은 나누어 떨어져야 한다는 점. 그림에서 stride 3을 적용한 공식은 2.33이 나오기 때문에 사용할 수 없다. 왼쪽 경계에서 시작해서 오른쪽 경계로 끝나야 사용할 수 있다. 자투리가 조금 있어도 될 수 있을 것 같은데, 허용하지 않는다. 미세한 차이지만, 정확도를 높일 수 있는 확실한 방법이라고 생각한다.


실전에서는 convolutinal layer를 거칠 때마다 크기가 작아지는 문제가 발생한다. stride 크기에 상관없이 최소한 (필터 크기-1)만큼 줄어들 수밖에 없다. 이번 그림에서는 원본 이미지의 크기가 줄어들지 않도록 padding을 얼마나 넣을지 설명한다. padding을 넣는 이유는 원본 이미지 크기를 유지하기 위함이다.

보통은 stride를 1로 하기 때문에 padding의 크기 또한 1이 된다. 그런데, 테두리 전체에 대해 추가되기 때문에 크기는 2만큼 증가한다.

padding의 두께는 정해져 있지 않다. 출력 결과가 원본과 같은 크기를 만들 수 있다면 얼마든지 가능하다. 그림을 보면 필터 크기가 3, 5, 7일 때 각각 1, 2, 3픽셀의 padding을 넣는다고 되어 있다. 3픽셀 padding을 넣으면, 양쪽으로 추가되기 때문에 결과적으로는 6픽셀이 추가된다.

필터 크기가 7이고 원본 크기가 7인 경우라면, padding을 포함한 전체 크기는 13이 된다. 7픽셀의 필터가 움직일 수 있는 횟수는 7번이 되고, 출력 결과의 크기는 7x7이 되어서 원본 크기와 같다. padding은 한쪽만을 얘기하므로 2로 나누었고, 양쪽으로 2개 들어가니까 2를 곱했다. 그래도 2로 나누었다 2로 다시 곱하니까 어색한 부분이 있다.

  출력 크기 = 원본 + (필터-1)/2 * 2 = 7 + (7-1)/2 * 2 = 13


32x32 그림 전체에 대해 출력을 계산한다. 그런데, 출력 결과를 하나가 아니라 여러 개로 중첩시킬 수 있다. 출력 결과는 필터를 거친 결과를 의미하므로, 결국 여러 개의 필터를 사용한다는 말이 된다.

처음에 이 부분이 매우 어려웠다. 5x5x3 크기의 필터를 수평과 수직으로 이동시켜서 전체를 순회하면 필터 1개가 만들어진다. 그런데, 필터라는 단어가 너무 무분별하게 쓰이는 것처럼 보인다. 5x5x3에서도 나오고 출력 결과에서도 나온다. 뒤에서 잠깐 언급하고 있는데, 5x5x3은 필터라고 하고 결과물은 채널(channel)이라고 부른다. 필터 1개에 채널 1개가 만들어진다. 여기서는 2개의 채널이 있으니까, 필터를 2개 사용했다. 필터는 weight의 역할을 하고 있으니까, 이 말은 여러 가지 가중치를 사용해서 여러 번의 결과를 만든다는 것과 같은 뜻이 된다. 계속적으로 등장하는 "균형 잡힌 결과"와 같은 맥락이다.


그림이 분명하지 않은데, 여기서는 6개의 필터를 사용하고 있다. 필터를 적용해서 만들어진 새로운 출력 결과를 activation map이라고 한다. 교수님이 28x28x6이라고 써놓으셨는데, 이해할 수 있어야 한다.

이전 그림에서 stride가 1이라고 했고, 필터 크기는 5x5이다. 그렇다면 activation map의 크기는 (32-5)/1 + 1의 공식에 따라서 28이 된다. 여기에 필터의 갯수 6이 들어간다.


convolutional layer를 거칠 때마다 조금씩 작아지고 있다. 앞에서 얘기한 padding을 추가했다면 크기가 작아지지 않았을 것이다. stride가 1이라고 가정하고 결과물에 대해 크기를 계산해 보자.

  (32 - 5)/1 + 1 = 28  (red layer)
  (28 - 5)/1 + 1 = 24  (yellow layer)

이번 동영상 마치기 전에 중요한 거 하나 얘기한다. 그림 상자의 두께가 점점 두꺼워지고 있다. convolutional layer를 거칠수록 크기는 작아지지만 두께는 두꺼워지는 것이 일반적이다. 작아진 크기를 두께로 보강한다고 볼 수도 있을 것 같다.

그런데, 두께는 무엇을 의미할까? 그냥 필터의 갯수라고 말하면 될까? 내 생각에는 색상으로 보면 쉬울 것 같다. TensorFlow 도움말에서는 채널(channel)로 설명한다.

첫 번째 상자에서 32x32x3인데, 3은 Red, Green, Blue의 값을 뜻한다. 같은 관점에서 색상은 아니지만, 두 번째 상자의 28x28x6에서 6은 색상과 같은 개념이다. 6개의 값이 모여서 1개의 픽셀을 구성하는 것이다.

이것이 색상이 아니어도 되는 것이 다른 필터에 있는 값들과 비교할 수만 있으면 된다. 중요한 것은 비용(cost)을 계산해서 얼마나 가까운지 판단하기만 하면 된다. 꼭 기억하자!