Why Sequence Models?

다섯번째 강의에서는 Sequence model에 대해서 배운다. 딥러닝에서 가장 흥미로운 분야 중 하나이며, Recurrent Neural Network(RNN)같은 모델은 음성 인식, 자연어 처리(NLP) 영역에 영향을 끼쳤다.

아래는 시퀀스 모델이 사용되는 몇 가지 예시들이다.

음성 인식(Speech recognition)의 경우에는 Input X인 오디오가 Text output Y에 매핑된다. 입력과 출력 모두 시퀀스 데이터인데, X는 시간에 따라 재생되는 음성이며, Y는 단어 시퀀스이다.

음악 생성(Music generation)의 경우에는 Output Y만 시퀀스 데이터이고, 입력은 빈 집합이거나 단일 정수, 또는 생성하려는 음악의 장르나 원하는 음악의 처음 몇 개의 음일 수 있다.

감정 분류(Sentiment classification)에서 Input X는 시퀀스 데이터이고, 주어진 문장에 대해서 Output은 별점이 될 수 있다.

 

시퀀스 모델은 DNA Sequence 분석에도 매우 유용한데, DNA 염기 서열을 살펴보고 어떤 부분이 일치하는지 라벨을 붙이는 것과 같은 일들을 할 수 있다.

그 밖에도 기계번역(Machine Translation), 비디오 동작 인식, 이름 인식 등이 있다.

 

Notation

다음으로 RNN에서 사용되는 용어들을 정리한다.

예를 들어서 'Harry Potter and Herimone Granger invented a new spell'이라는 input 가 있고, 이 문장에서 이름을 인식(Name entity recognition)한다고 했을 때, 각 단어마다 output y를 가지며, output값은 이름인지 아닌지에 대한 1/0의 값을 가진다.

이번 예시에서는 입력 시퀀스 x가 총 9개의 단어로 이루어져 있고, 입력은 총 9개의 feature set을 가지게 된다. 시퀀스의 순서를 나타내기 위해서 위첨자로 x^<1>, x^<2>, ..., x^<t>, ..., x^<9>로 나타내어서 순서를 나타낸다. 여기서 위첨자 t를 통해서 순서를 나타내며, t는 time sequence에서 유래한다.

유사하게 output y에 대해서도 로 나타낸다.

시퀀스의 길이는 T에 아래첨자 x를 사용해서 T_x로 나타내며 여기서는 T_x = 9이다.

T_y는 출력 시퀀스의 길이를 의미하며, 여기서는 T_x와 동일한 값을 가지지만, 다른 값을 가질 수도 있다.

 

그리고 여러개의 training data가 있을 때, 이전과 동일하게 (i)를 위첨자에 사용해서 i번째 training data를 나타내서, x^{(i)<t>}로 나타내며, T_x가 한 시퀀스의 길이를 뜻하므로, training set의 서로 다른 데이터의 길이는 다를 수 있고, i번째 트레이닝 데이터의 길이는 로 표기한다.

 

다음으로 NLP, 자연어 처리를 다루는 방법에 대해서 이야기해보자.

NLP에서 먼저 결정해야할 것은 시퀀스의 단어 표현 방법이다. 'Harry'라는 단어를 어떻게 표현해야할까?

시퀀스의 단어를 표현하기 위해서는 먼저 Vocabulary(or Dictionary)를 만들어야 한다.

예를 들어 Voca의 첫번째 단어는 'a'이고, 두번째는 'Aaron', 조금 더 지나가면 'and', 또 더 살펴보다보면 'Harry', 'Potter'가 나오고 마지막에는 'Zulu'가 나올 수 있다.

여기서 'harry'는 4075번째, 'potter'는 6830번째에 나왔다. 보통 상용 어플리케이션용의 사전은 대게 3~5만개의 단어를 포함한다. 여기서는 1만개를 사용한다고 가정한다.(단어를 고르는 방법은 자주 사용하는 단어 1만개를 고르거나, 다른 방법을 사용할 수도 있다)

그 다음에 단어를 one hot encoding을 통해서 표현한다. 

예를 들어, 'harry'를 나타내는 단어 는 4075번째 위치만 1이고 나머지는 0인 벡터이다.(사전의 4075번째 위치가 'harry'이기 때문)

 역시 6830번째만 1이고 나머지는 0인 벡터이다. 

(one hot은 하나만 1이고 나머지는 0이라는 의미에서 유래)

 

단어를 표현했으면, 다음 목표는 이렇게 표현된 input x를 output y로 매핑하는 시퀀스 모델을 학습하는 것이다.

Supervised Learning으로 수행되고, x와 y를 포함하는 데이터를 사용한다.

 

만약에 Voca에 없는 단어가 나오면 어떻게 할까?

그 답은 새로운 Token이나 모르는 단어를 의미하는 가짜 단어를 만들면된다. 즉, <UNK>와 같이 표시해서 Voca에 없는 단어를 나타낼 수 있다.

 

Recurrent Neural Network Model

RNN 모델에 대해서 살펴보기 전에 기본적인 모델에 대해서 이야기해보자.

이전 예제처럼 9개의 입력 단어가 있을 때, 9개의 단어를 입력으로 받는 모델을 그려보도록 하자. 그렇다면 9개의 one-hot 벡터가 모델에 입력된다. 그리고 몇 개의 hidden layer를 통해서 최종적으로 0 혹은 1의 값을 갖는 9개의 output이 나오게 될 것이다.(1은 사람 이름을 뜻함)

하지만 위와 같은 방법은 잘 동작하지 않는다. 

2가지 문제점이 존재하는데,

첫번째는 입력과 출력 데이터의 길이가 트레이닝 데이터마다 다르다. 모든 트레이닝 데이터가 같은 입력 길이 를 가지지 않고, 같은 를 가지지 않는다. 입력에 임의의 값이나 0으로 채워서 최대 길이로 동일하게 맞출 수는 있지만 좋은 방법은 아니다.

두번째는 이런 naive 신경망에서는 텍스트의 서로 다른 위치에 있는 동일한 feature(단어)가 공유되지 않는다. 즉, 이름이 첫번째 위치나 t번째 위치에서 나오거나 동일하게 사람 이름이라고 추론하는 것이 올바르다. 이는 CNN에서 학습한 이미지의 특성을 이미지의 다른 부분에 일반화시키는 것과 유사하다.

또한, 이 경우에 각각의 단어가 1만 차원의 one-hot vector이기 때문에 입력 데이터가 매우 크고, 파라미터의 수가 엄청나게 많아 진다.

 

그렇다면 Recurrent Neural Network(순환신경망)은 무엇일까?

RNN의 기본 구조는 위와 같다. 좌에서 우로 문장을 읽는다면 처음 읽는 단어 를 신경망의 입력으로 사용한다. 그리고 내부 신경망(hidden layer, output layer)를 통해서 사람 이름의 일부인지 예측한다. 

그리고 문장의 두번째 단어 를 읽고, 를 예측할 때, 만 사용하는 것이 아니라, 첫번째 단어로 연산한 정보의 일부를 사용하게 된다. 구체적으로는 첫번째 시점의 activation이 두번째 시점에 전달된다. 

이런 식으로 진행해서 마지막 시점에서 를 예측한다.

(해당 예제에서는 이다.)

 

그리고 RNN 신경망 학습을 시작하기 전에 이 사용되는 것을 볼 수 있는데, 이것은 보통 무작위로 초기화하거나, 0으로 초기화한다. 0으로 초기화하는 경우가 가장 일반적이다.

 

위 이미지 오른쪽처럼 하나의 NN만 표현하고 순환하는 표시로 RNN을 표현하기도 한다. 이는 매 시점에서 파라미터를 공유한다는 것을 의미한다. (가 사용됨)

 

위 기본 RNN 모델의 단점은, 앞서 나온 정보만을 사용해서 예측을 한다는 것이다. 을 예측할 때, 의 정보를 사용하지 않는다. 이는 문제가 될 수 있다.

위와 같은 문장이 주어졌을 때, 첫 두 단어의 정보뿐만 아니라 뒤에 있는 나머지 단어들의 정보를 아는 것도 매우 유용할 것이다. 즉, 첫 두세마디만 고려한다면, Teddy라는 단어가 사람의 이름인지 확실하게 알 수 없다는 것이다.

아래 문장도 마찬가지이다. 첫 두세마디 만으로는 차이를 구별할 수 없다. 이 문제는 양방향으로 반복되는 BRNN을 통해서 해결될 수 있다.

 

RNN의 Forward Propagation

아래는 신경망이 어떻게 계산되는지 보여주고 있다.

초기에 사용되는 는 일반적으로 0 vector로 초기화된다. 

다음으로 을 구하기 위해서 에 activation function을 적용한다.

activation function으로는 tanh나 ReLU가 사용된다.

그리고 첫번째 단어의 예측 hat은 다음과 같이 구할 수 있다.

따라서 일반화하면 다음과 같다.

그리고, 위 식을 조금 단순화시키면 다음과 같이 표현할 수 있다.

Backpropagation Through Time

다음으로 RNN의 Backpropagation(역전파)가 어떻게 동작하는지 대략적으로 살펴보자.

이미 알겠지만, BP는 FP의 반대반향으로 진행된다.

일단 이전 강의 내용에서 살펴봤듯이, 를 통해서 를 구하고, 를 통해서 예측값 hat를 구한다. 

그리고 BP를 계산하고 위해 Loss function을 통해서 실제 결과와 예측값의 Loss(cost)를 계산하고, 총 Loss의 값을 구한다. 

Cross Entropy Loss(Logistic Regression Loss)를 사용할 수 있는데, 각 element의 Loss와 총 Loss는 다음과 같다.

최종 Loss는 시간별 개별 Loss의 합이다. 

그리고 BP를 진행하는데, BP는 오른쪽에서 왼쪽으로 향하는 계산이다.

FP가 시간 순서로 전달하는 것과 반대로 BP는 시간을 거꾸로 가는 것과 같아서 Backpropagation through time(BPTT)라고 부른다.

Different Types of RNNs

지금까지 RNN 아키텍처에서는 와 동일한 경우를 살펴보았다. 는 항상 같지 않을 수 있으며, 다양한 RNN 아키텍처를 살펴보도록 하자.

강의 초기에 보여준 시퀀스 데이터의 예시들이다. x, y가 모두 시퀀스 데이터거나, x가 빈 집합일 수도 있거나, 하나의 입력일 수 있으며, y가 시퀀스가 아닐 수도 있다.

 

이전 예제들처럼, 라면 Many-to-many 아키텍처라고 하고, 아래와 같이 모델링할 수 있다.

만약 Sentiment classification처럼 x는 텍스트이지만, y가 0/1의 값을 갖는 output이라면 Many-to-one 아키텍처로 다음과 같이 모델링 할 수 있다.

물론 one-to-one 아키텍처도 있으며, 단순한 신경망과 동일하다.

 

Music generation과 같은 모델은 입력이 정수일 수도 있고, 어떤 음악 장르나 원하는 음악의 첫 음표일 수도 있으며, 어느 것도 입력하고 싶지 않다면 null 입력일 수도 있고, 항상 0일 수도 있다. 이런 모델은 One-to-many 아키텍처이며, 다음과 같이 하나의 input x와 시퀀스 output y를 가질 수 있는 모델이 된다.

아키텍처는 이렇게 Many-to-many, Many-to-one, One-to-one, One-to-many으로 분류할 수 있는데, Many-to-many에서 다른 아키텍처들도 있다.

 

기계번역(machine translation)는 Many-to-many 아키텍처지만, 입력과 출력의 길이가 다를 수 있다.()

위와 같은 모델에서 입력을 받는 부분은 encoder, 그리고 출력을 내는 부분을 decoder라고 부른다.

 

Language Model and Sequence Generation

Language Modelling은 LNP에서 가장 기본적이고 중요한 작업 중 하나이다. 이번 강의에서 RNN을 사용해서 Language model을 만드는 방법을 배워보도록 할것이다.

 

language modelling(언어 모델)이란 무엇일까?

우리가 음성 인식(Speech recognition) 시스템을 만들고 있다고 가정해보자. 

The apple and pear salad라는 문장을 들었을 때, 위 두 가지 문장이 있다면 두 번째 문장이 더 가능성이 있다고 생각할 것이다. 여기서 두 번째 문장을 선택하는 방법은 두 문장의 확률이 얼마인지 알려주는 언어 모델을 사용하는 것이다.

예를 들어서, 모델이 첫 번째 문장에 대한 확률은 으로 지정하고, 두 번째 문장의 확률은 으로 지정하는 것이다. 따라서 음성 인식 시스템은 두번째 문장을 선택하게 된다.

이러한 언어 모델은 RNN을 사용해서 만들 수 있는데, 이런 모델을 만드려면 large corpus of english text를 포함하는 training set이 필요하다. (corpus라는 단어는 NLP 용어로 큰 영어 문장들을 의미한다.)

 

언어 모델의 기본 작업은 문장을 입력하는 것인데, 이 문장은 로 표현하겠다. 언어 모델에서 문장을 input x가 아닌 output y로 표시하는 것이 유용하다.

위와 같은 'Cats average 15 hours of sleep a day.'라는 문장이 있다고 해보자. 

첫 번째로 해야할 일은 이 문장을 토큰화하는 것이다. 토큰화를 통해서 단어들로 분리하고, 단어들을 Voca의 index를 통해 one-hot vector로 매핑한다. 한 가지 추가 작업으로는 문장이 끝난다는 의미인 라는 토큰을 추가한다.4

(마침표를 토큰으로 사용할 수 있는데, 여기서 마침표는 무시했다.)

만약 아래 문장처럼 Mau라는 단어가 Voca에 없다면 라는 토큰으로 대체할 수 있다.

 

그리고 RNN 아키텍처는 다음과 같다.

첫 번째 } 은 0 vector로 설정하고, hat를 계산한다. 

여기서 haty는 softmax output이며, 첫 번째 단어가 존재할 확률을 의미한다. 이 예제에서는 첫 번째 단어 cats가 될 것이다.

그리고 다음 RNN step이 진행되고 a^{<1>}를 가지고 다음 단계를 진행한다. 여기서 x^{<2>} y^{<1>}가 되며, 우리는 이제 모델에 올바른 첫 단어인 cats를 입력하게 된다. 

그리고 이 단계에서 softmax output에 의해서 다시 예측되고 그 결과는 첫 번째 단어가 cats일 때의 다른 Voca 단어들의 확률이 될 것이다.

그리고 세번째 단계에서 x^{<3>} = y^{<2>}이고, 이전 단어 'cats average'를 가지고 세 번째 단어의 확률을 예측하게 된다. 

그렇게 계속 진행하면 마지막 \hat{y}^{<9>}의 output을 내보내고, 이 값은 EOS가 될 것이다. 

 

이렇게 예측한 후에 Loss를 구하는데, 전체 Loss는 각 output의 Loss의 합이 된다.

 

세 개의 단어를 가지는 문장으로 정리해보자면, 첫 번째 단계에서 softmax output은 y^{<1>}의 확률을 알려주고, 두 번째는 이전 단어가 y^{<1>}일 때, y^{<2>}의 확률, 세 번째는 이전 단어가 y^{<1>}, y^{<2>}일 때, y^{<3>}의 확률을 알려주게 된다. 즉, 은 다음과 같다.

조금 추상적인 내용이 될 수 있지만, 자세한 내용은 실습을 통해서 이해할 수 있을 것이다.

 

Sampling novel sequences

시퀀스 모델을 학습한 후에, 학습한 내용을 비공식적으로 파악할 수 있는 방법 중의 하나는 sample novel sequence를 갖는 것이다.

네트워크는 위와 같은 모델을 가지고 학습이 되었다.

 

그리고 sampling을 진행하는데, 샘플링의 과정은 다음과 같다.

a^{<0>}, x^{<1>}는 0 vector이고, 첫 번째로 softmax output \hat{y}^{<1>}를 출력한다. 이것은 각 단어의 확률이 얼마나 되는지 알려주는데, 이 벡터를 사용해서(numpy의 np.random.choice를 통해) 무작위로 첫 번째 단어를 샘플링 할 수 있다. 그런 다음 두 번째 단계로 넘어간다. 두 번째 단계에서는 샘플링한 값을 x^{<2>}로 사용한다.

이와 같은 과정을 계속 반복하는데, 예측값이 EOS Token이 될 때까지 샘플링을 반복하거나, 또는 정해진 샘플링 횟수를 정하고 그 단계에 도달할 때까지 계속하도록 할 수도 있다. 

이것이 RNN 모델에서 무작위로 선택된 문장을 생성하는 방법이다.

 

지금까지 우리는 단어 수준의 RNN을 만들어 봤지만, 문자 수준의 RNN도 만들 수 있다.

즉, Training set는 개별 문자로 토큰화된다. (a, b, c, ..., A, B, C, ... 등으로)

문자 수준의 언어 모델을 사용하면 알 수 없는 단어에 대해 걱정할 필요가 없다.

하지만, 문자 수준은 입력이 훨씬 더 긴 배열로 이루어지기 때문에 문장의 초기 부분이 문장의 뒷부분에도 영향을 많이 줄 때의 성능이 단어 수준의 언어 모델보다 낮다.

 

다음은 실제 언어 모델의 사례이다.

뉴스 기사로 학습된 시퀀스 모델은 왼쪽과 같은 텍스트를 생성하고, 셰익스피어의 책에 의해 훈련된 모델은 셰익스피어가 쓴 것과 같은 텍스트를 생성한다.

 

Vanishing Gradients with RNNs

Basic RNN 모델의 문제점 중의 하나는 Vanishing gradient 문제가 발생할 수 있다는 것이다. 

아래와 같은 문장을 살펴보자.

'The cat, which already ate ...., was full'

'The cats, which already ate ...., were full'

이 예시는 문장의 단어가 긴 시간동안 의존성을 가지는 예시이다. 즉, 문장 초반부의 단어가 문장 후반부에 영향을 끼칠 수 있다는 것인데, RNN은 이와 같은 장기적인 의존성을 확인하는데 효과적이지 않다.

(긴 시퀀스를 처리하는데 한계가 존재함)

 

즉, cat나 cats처럼 단수/복수 명사가 문장 초반에 존재했다라는 것을 기억하고 있어야 제대로된 예측을 할 수 있는데, RNN의 경우에는 가까이에 있는 것에 영향을 더 많이 받는다. 에 가까이 있는 값(입력)에 영향을 받는다.

이것이 Basic RNN 알고리즘의 약점이다.

 

Deep layer NN에 대해서 언급할 때, gradient가 기하급수적으로 감소해서는 안되고, 또한 기하급수적으로 증가해서도 안된다고 했었다. 여기서는 Vanishing gradient에 대해서 포커스를 맞추고 있지만, Exploding gradient가 최근 더 큰 문제로 대두되고 있는데, gradient가 너무 커져버리면, 네트워크의 매개 변수가 완전히 엉망이 되기 때문이다. 이 경우에는 gradient clipping을 통해서 어느 정도 해결할 수 있다.

 

다음 강의에서 Vanishing gradient를 해결하는 효과적인 해결책과 long-range dependency를 유지하는 방법에 대해서 알아보자.

 

Gated Recurrent Unit (GRU)

앞서 Basic RNN이 어떻게 동작하는지 살펴보았고, 이번에는 GRU라는 조금 더 긴 시퀀스를 잘 캡처(장기의존성 문제)하고, Vanishing Gradient 문제를 해소할 수 있는 GRU에 대해서 살펴보도록 하자.

GRU는 다음에 나오는 LSTM과 유사하지만, 조금 더 간략한 구조를 가지고 있다.

GRU를 간단하게 표현하면 위와 같다. 여기서 새롭게 나타나는 c memory cell을 의미하며 이전 정보들이 저장되는 공간이다. 이전 정보가 를 통해 전달되고, 이전 정보와 현재 input 와 결합하여 다음 time step으로 전달된다.

즉, 이전 예시처럼 문장 앞쪽의 단수/복수 정보가 뒤쪽까지 전달되어서 'was'를 예측하는데 영향을 끼칠 수 있게 된다.

 

여기서 크게 두 가지 연산이 존재하는데, 우선 이전 정보와 현재 입력을 통해서를 연산한다.

이 연산은 현재 time step에서 다음 time step으로 전달할 정보들의 후보군을 업데이트하는 것이다. 

그리고 Update gate \Gamma_u를 통해서 어떤 정보를 업데이트할지 결정하게 되는데, 아래와 같이 계산된다.

그리고 최종적으로 다음 time step으로 전달될 c^{<t>}는 다음과 같이 계산된다.

즉, 현재 time step에서 업데이트할 후보군과 이전 기억 정보들의 가중치합으로 계산된다. 여기서 Gate는 어떤 정보를 더 포함시킬지 결정하는 역할을 하게 되는 것이다. \ast는 element-wise 곱을 의미한다.

 

추후에 LSTM에서 배우겠지만, LSTM의 Forget gate와 Input gate를 합쳐놓은 것과 유사하다.

 

Full GRU에서는 Update gate 외에도 Reset Gate가 존재하며, 이전의 정보를 적당히 리셋시키는 목적으로 sigmoid 함수를 출력으로 사용해 0 ~ 1사이의 값을 이전 정보에 곱해주게 된다.

 

Full GRU는 다음과 같은 구조를 갖는다. 여기서 h는 c=a를 의미한다.

 

Long Short Term Memory (LSTM)

LSTM은 GRU보다 일반적으로 많이 사용되는 장시간 단기 메모리 Unit이다.

GRU보다 조금 더 복잡한데, 우선 이전 time step에서 전달받는 input이 로 추가된다.

그리고 Forget gate, Update gate, Output gate을 통해서 각각의 연산을 수행하고, tanh를 통해서 를 연산하는데, 이전 GRU에서 언급했듯이 이것은 현재 time step에서 다음 time step으로 업데이트할 정보들의 후보군을 의미한다.

 

핵심 아이디어는 현재 time step의 정보를 바탕으로 이전 time step의 정보를 얼마나 잊을지 정해주고(Forget gate), 그 결과에 현재 time step의 정보의 일부(Update gate와의 연산결과)를 더해서 다음 time step으로 정보를 전달한다.

 

LSTM은 다음과 같은 과정을 통해서 계산된다.

 

GRU와 LSTM을 비교했을때, 어느 것이 우월하다고 할 수 없고, 강점을 보이는 분야가 조금 다르다. LSTM이 조금 더 먼저 발견되었고, GRU는 비교적 복잡한 LSTM 모델을 단순화한 것이다. 

GRU의 장점은 LSTM에 비해서 훨씬 단순하고, 따라서 훨씬 더 큰 네트워크를 만드는 것이 쉽다. (두 개의 gate만 존재하기 때문에 연산량이 적다.)

LSTM의 다소 모델이 크지만, 3개의 gate가 존재해서, 보다 성능이 좋고 효과적일 수 있다.

<https://yjjo.tistory.com/17?category=881892>

 

Bidirectional RNN (양뱡향 RNN)

지금까지 RNN의 가장 기본적인 building block들을 살펴보았다.

추가로 훨씬 더 강력한 모델을 만들 수 있는 두 가지 아이디가 있는데, 하나는 Bidirectional RNN(BRNN)이다.

BRNN은 주어진 시퀀스에서 이전 시점과 이후 시점의 모든 정보를 참조할 수 있다.

다른 하나는 deep RNNs이고 잠시 후에 설명하도록 하겠다.

 

전에 살펴본 사람 이름을 찾는 모델에서의 예시이다. 위의 단방향 RNN 모델이 있을 때, 세번째 단어인 Teddy가 이름인지 아닌지 확인해보기 위해서는 첫번째, 두번째 단어만으로는 충분하지 않다. 즉, 더 많은 정보가 필요하다는 것이다. 

 

이런 경우에 BRNN이 위 문제를 해결할 수 있다.

예를 들어 4개의 입력(4개의 단어로 이루어진 문장)이 있다고 가정해보자.

BRNN은 위와 같은 구성을 가질 수 있는데, 보라색 cell들을 통해서 앞에서부터 정보를 읽어나가고, 초록색 cell들은 역방향으로 입력 정보를 읽어나가게 된다. 그리고 두 cell의 결과를 통해서 예측값을 계산한다. 

따라서 과거와 미래 정보를 모두 참조하여 예측하게 된다.

 

여기서 block cell은 RNN, GRU, LSTM 어느 블록이든 상관없다.

 

이처럼 BRNN을 통해서 전체 시퀀스의 정보들을 참조해서 예측할 수 있지만, 단점은 예측을 하기 전에 전체 데이터 시퀀스가 필요하다는 것이다.

예를 들어, 음성 인식 시스템을 만들어서 연설을 입력받을 때, 연설이 끝날 때까지 기다렸다가 그 연설 데이터를 처리해서 예측할 수 있을 것이다. (실제 음성 인식 시스템은 표준의 BRNN보다 조금 더 복잡한 모듈이다.)

 

 

Deep RNN

지금까지 본 RNN은 아마 꽤 잘 동작할 것이다. 그러나 조금 더 복잡한 기능을 학습하는 경우에는 RNN을 여러 layer로 쌓아서 더 깊은 모델을 구현할 수 있다.

여기서는 3개의 layer로 쌓았지만, 더 많이 쌓을 수 있다.

What is Face Recognition

얼굴 인식 분야에서 세부적으로 얼굴 검증(Verification)과 인식(Recognition)으로 분류된다.

Face Verification의 경우에는 사람의 이름이나 ID, 이미지가 주어졌을 때, 이 사람이 맞는가에 대한 여부를 확인한다. 1:1 문제라고도 부르고, 요청한 그 사람이 맞는지 여부를 알게 한다. 

반면에 Face Recognition의 경우에는 1:K 문제라고도 하는데, K 명의 database가 있으면 주어진 이미지를 통해서  K명의 database에 속하는 사람인 지를 판단해야한다. 

얼굴 인식은 얼굴 검증 문제보다 훨씬 어려운데, 99%의 정확성을 갖춘 인식 시스템일지라도 데이터베이스에 100명이 있다면 오차가 생길 확률은 100명 중에 한명꼴로 발생한다. 따라서 허용 가능한 오류를 원한다면 실제로 99.9%이상의 정확성을 갖추어야 할 수 있다.

 

One Shot Learning

얼굴 인식에서의 도전 중에 하나는 One Shot Learning 문제를 해결해야한다는 것이다. 대부분 얼굴인식 application에서 이것이 의미하는 바는 한 사람을 인식하는데, 하나의 이미지만 주어진다는 것이다.

전통적으로, 딥러닝 알고리즘은 one training example을 가지고 있다면 성능이 좋지 않았다. 

위의 예시를 살펴보자. 4명의 등록된 직원이 있고, 사무실 누군가가 게이트를 지난다고 가정해보자. 게이트의 시스템은 각 직원의 사진 하나씩만을 가지고, 게이트를 지나는 사람이 직원인지 아닌지 인식해야 한다. 따라서 One Shot Learning 문제에서는 한 가지 example만을 통해서 그 사람을 다시 인식해야한다. (대부분의 얼굴 인식 시스템에 필요한 성능이다)

그래서 시도해볼 수 있는 방법 중의 하나는 직원 데이터베이스의 이미지를 ConvNet의 입력으로 사용해서 Output Y 레이블을 출력하게 한다. 직원이 4명이기 때문에 인식하지 못하는 경우까지 총 5개의 label의 가진 softmax uint output이 된다. 

하지만, 이 방법은 실제로는 잘 동작하지 않는다. 이렇게 작은 training set으로는 deep neural network를 훈련시키기에 충분하지 않기 때문이다. 

그리고 새로운 직원이 추가된다면 어떻게 될까? 

5개의 output에서 6개의 output으로 바껴야하고, ConvNet을 다시 학습시켜야 할까?

이 방법은 좋은 방법이 아니다. 

 

따라서, 얼굴 인식에서 one shot learning을 수행하기 위해서 할 수 있는 방법은 similarity funcion을 학습하는 것이다.

즉, 두 이미지의 차이 정도를 output으로 출력하는 similarity function를 학습하는데, 이미지가 많이 다르면 값이 크고, 유사하다면 값이 작다. 그래서 어느 정도 이상 크다면 같은 사람으로 인식하고, 작다면 다른 사람으로 인식한다.

따라서 새로운 이미지가 주어진다면, similarity 함수를 사용해서 두 이미지를 비교한다.

위의 경우에는 왼쪽 두번째 이미지와의 similarity 함수 값이 가장 작기 때문에 같다라고 판단한다.

이렇게 similarity 함수를 통해서 새로운 사람이 추가되어도 재학습할 필요없이 잘 동작할 수 있게 된다.

 

Siamese Network

위에서 배웠던 d함수는 두 얼굴 이미지를 입력하고, 두 이미지가 얼마나 유사한지, 얼마나 다른지 알려준다. 이것을 수행하기 좋은 방법은 Siamese network를 사용하는 것이다.

위의 ConvNet에서 x^{(1)}라는 이미지를 입력하면 일련의 convolution, pooling, fc를 통해서 feature vector로 마무리되고, softmax unit으로 분류를 하는 것에 익숙한데, 이번 강의에서는 출력단은 제거하고 feature vector에 초점을 맞출 것이다. 이 feature vector는 fc에 의해서 계산된 값이다.

이 feature vector의 이름을 f(x^{(1)})이라고 부르고, 이 함수는 x^{(1)}의 input 이미지를 encoding하는 것이라고 생각하면 된다. 즉, input 이미지를 취해서 128개의 feature vector로 encoding하는 것이다.

 

이것을 이용해서 얼굴 인식 시스템으로 구축할 수 있는 방법은 두 장의 사진을 동일한 파라미터를 가진 신경망을 통해서 이 128개의 feature vector를 각각 얻어서 비교한다.

따라서 두 이미지 x^{(1)}, x^{(2)}를 신경망을 통해서 인코딩된 f^{(1)}, f^{(2)}를 얻을 수 있다. 

이렇게 인코딩된 값이 두 이미지를 잘 나타낸다고 생각한다면, x^{(1)} x^{(2)} 사이의 거리 d를 구할 수 있는데, 거리 d는 두 이미지의 인코딩된 값 차이의 norm으로 정의할 수 있다.

 

이렇게 두 개의 서로 다른 인풋을 동일한 ConvNet을 통해서 인코딩된 값을 얻어서 비교하는 개념을 Siamese Neural Network Architecture라고 부르기도 한다.

이 아이디어는 DeepFace 논문에서 비롯되었다.

정리하자면,

  • 신경망의 파라미터를 f(x^{(i)})의 인코딩으로 정의하고,
  • 같은 두 사람의 이미지 x^{(i)}, x^{(j)}가 있다면, 이 인코딩 사이의 norm을 최소화하는 것이다. 만약 두 이미지가 다르다면, 인코딩 사이의 norm이 커야한다.

다음으로 d함수를 학습하기 위해서 loss function을 어떻게 정의해야되는지 살펴보자.

 

Triplet Loss

신경망의 파라미터를 학습해서 얼굴 인식을 위한 좋은 인코딩을 학습하는 방법은 triplet loss function을 적용한 GD를 정의하는 것이다.

Triplet Loss를 적용하려면, 이미지 쌍을 서로 비교해야한다. 위의 예시처럼 동시에 여러 이미지를 살펴봐야하는데, 왼쪽의 이미지 쌍은 같은 사람이기 때문에 인코딩이 유사해야되고, 오른쪽 이미지 쌍은 다른 사람이기 때문에 인코딩이 꽤 차이가 나야한다. 

여기서 Triplet Loss는 하나의 Anchor 이미지를 두고, Positive와 Negative와의 사이의 거리를 동시에 살펴본다.

즉 Anchor-Positive의 인코딩과 Anchor-Negative의 인코딩 차이를 같이 살펴본다는 것이다.

(Anchor는 A, Positive는 P, Negative는 N으로 축약한다.)

 

위 내용을 공식으로 나타내면 다음과 같다.

A와 P는 같은 사람이기 때문에 d(A, P)가 작고, A와 N은 다른 사람이기 때문에 d(A, N)이 크다. 따라서 d(A, P)가 d(A, N)보다 작도록 하는 것이 목표이다.

하지만 주의해야할 점이 있는데 모든 이미지의 인코딩이 같아지면 안된다. 모든 이미지의 인코딩이 같아진다면, d(A, P)와 d(A, N)이 모두 0이 되어서 위 공식을 항상 만족하게 된다. 

위와 같은 상황을 방지하기 위해서 \alpha라는 하이퍼 파라미터를 추가하는데, margin이라고 부르기도 한다.

 

margin의 역할은 다음과 같다.

d(A, P) = 0.5 / d(A, N) = 0.51 이라면 margin이 없을 때에는 공식이 만족하게 된다(다른 사람임에도 불구하고 d(A,N)이 더크다). 하지만, \alpha = 0.2가 존재한다면, d(A, N)이 0.7이 되거나 d(A, P)가 0.31이 되는 식으로 학습을 가능하도록 만들어 준다.

즉, A-P와 A-N이 서로 더 멀어질 수 있도록 하는 역할을 한다.

 

Triplet Loss Function을 정의하면 다음과 같다.

\mathscr{L}(A,P,N) = \text{max}(\| f(A) - f(P) \|^2 - \| f(A) - f(N) \|^2 + \alpha, 0)

0보다 작다면, 같은 사람이라고 판단하고 0으로 설정한다.

Cost는 

J = \sum_{i=1}^{m}\mathscr{L}(A^{(i)},P^{(i)},N^{(i)})

로 정의된다.

 

training set으로는 1,000명의 사람들의 사진 10,000장으로 위와 같이 triplet을 생성하고 GD를 사용해서 학습시키면 된다. 한 사람당 평균 10장의 사진을 가지고 데이터를 구성하는데, 각 사람의 사진이 하나뿐이라면 이 시스템을 실제로 훈련할 수는 없다.

물론, 학습이 완료된 후에는 얼굴 인식 시스템을 위한 One Shot Learning에 적용할 수는 있다. 하지만, 학습할 때 training set에서는 Anchor / Positive의 쌍을 이룰 수 있도록 몇몇 사람들만이라도 동일한 사람의 이미지가 여러 개가 있는지 확인하는 것이 필요하다.

 

그리고, A-P는 같은 사람이고 A-N은 다른 사람이기 때문에 무작위로 고를 때, A-N의 데이터가 매우 많이 뽑힐 확률이 높다. 따라서 training set를 구성할 때는 훈련하기 어려운 A,P,N 중의 하나를 선택하는 것이 중요하다.

같은 사람이지만 d(A,P) 값은 낮고, 다른 사람이지만 d(A,N)의 값이 높은 set로 구성을 한다면 학습에 더욱 도움이 될 것이다.

 

정리를 하면,

  • Triplet Loss를 가지고 학습하기 위해서는 training set에서 A-P와 A-N의 쌍을 매핑해야 하고,
  • 이 training set를 가지고 Cost J를 최소화하기 위해 GD를 사용한다.
  • 학습은 같은 사람일 경우에는 d가 최소가 되고, 다른 사람일 경우에 d가 최대가 되도록 최적화된다.

 

Face Verification and Binary Classification

Triplet Loss는 얼굴 인식을 위한 ConvNet의 파라미터 학습에 좋은 방법 중의 하나이다.

또 다른 방법으로는 얼굴 인식을 Binary Classification 문제로 변형해서 사용할 수 있는데, 한 번 살펴보도록 하자.

이미지를 128개의 feature vector로 나타내기 위해서 ConvNet을 통과시켜 embeding(encoding)시키고, 128개의 feature vector를 Logistic Regression을 통해서 예측하도록 한다. 목표 output은 두 이미지가 같다면 1을 출력하고, 다른 사람이라면 0이 된다. 

따라서, 얼굴 인식을 Binary Classification 문제로 취급하는 것이다.

output \hat{y}는 sigmoid 함수이고, 인코딩된 값들 사이에서 차이점을 알아내서 예측한다.

 

공식으로 나타낸다면 다음과 같이 나타낼 수 있다.

인코딩된 값의 차이를 구하는 수식에는 다양한 방법이 있으며, 초록색으로 나타낸

\[\frac{(f(x^{(i)})_k - f(x^{(j)})_k)^2}{f(x^{(i)})_k - f(x^{(j)})_k}\]

으로 사용할 수도 있다. 이는 카이 제곱 유사도라고 불린다.

 

그리고, 이 방법을 사용할 경우에 유용한 방법이 하나 있는데, database에서 이미지가 입력으로 사용된다고 한다면, 매번 embeding을 다시 할 필요없이, embeding된 값을 저장해서 ConvNet을 통과시킬 필요없이 바로 예측에 사용할 수 있다.이 방법을 사용하면 이미지를 저장할 필요가 없고, 데이터베이스가 매우 큰 경우에도 매번 모든 사원의 인코딩을 계산할 필요가 없기 때문에 효율이 높아진다.

 

What is Neural Style Transfer?

Neural Style Transfer는 Convnet으로 구현할 수 있는 흥미로운 어플리케이션 중의 하나이다. 이 네트워크를 통해서 자신만의 예술 작품을 만들 수 있다.

이미지를 새로운 Style로 변형하는 것인데, 원본 이미지(Content)와 변형할 스타일(Style)을 가지고 새로운 Style의 이미지(Generated Image)를 합성하는 것이다.

 

Neural Style Transfer를 구현하려면 ConvNet의 다양한 layer들을 살펴보고 그 layer들에 의해서 추출된 feature들을 살펴보아야 한다.

 

What are deep ConvNets Learning?

Neural Style Transfer에 대해서 알아보기 전에, Deep ConvNet이 무엇을 학습하는지에 대해서 이야기해보자.

우리가 위와 같은 ConvNet을 학습할 때, 각 layer에서 추출하는 feature들의 시각화를 통해서 각 layer의 unit들을 최대로 활성화하는 특징이 무엇인지 파악할 수 있다. 그리고, shallow layer에서는 명암과 같은 단순한 feature를 출력하고, deep layer로 갈수록 더욱 복잡한 패턴을 감지하기 시작한다.

 

'Visualizing and understanding convolutional networks' 논문에 ConvNet layer를 시각화하는 정교한 방법에 대해서 설명하고 있다.

 

Cost Function

Neural Style Transfer를 구현하기 위해서 생성된 이미지(Generated Image)에 대한 Cost Function을 정의해보자. 이 Cost Function을 최소화함으로써 우리는 원하는 이미지를 생성할 수 있게 된다.

비용함수는 다음과 같이 정의할 수 있다.

J(G) = \alpha J_{\text{content}}(C, G) + \beta J_{\text{style}}(S, G)

여기서 J_{\text{content}}(C, G)는 Content Cost라고 하며, J_{\text{style}}(S, G)는 Style Cost라고 하며, 두 이미지가 얼마나 비슷한지에 대한 Cost이다.

\alpha, \beta는 content cost와 style cost의 상대적인 가중치를 의미하고, 이것 또한 선택해야하는 하이퍼파라미터이다.(하나의 파라미터로 충분하지만, 논문에 따라 두개의 파라미터로 설명함)

 

그리고 최적화 알고리즘이 수행되는 방식은 다음과 같다.

처음에는 이미지 G를 무작위로 초기화해서 백색 노이즈의 이미지로 만들고, Cost Function을 통해 Gradient Descent를 수행해서 Cost Function을 최소화하고 G를 업데이트한다. 이 과정은 이미지 G의 픽셀 값을 업데이트하는 것이고, 학습이 진행될 수록 style로 렌더링된 content 이미지를 얻을 수 있을 것이다.

 

Content Cost Function

우선 Content cost function에 대해서 알아보자.

만약 layer l을 사용해서 content cost를 계산한다고 했을 때, hidden layer 1을 선택한다면 생성된 이미지가 content image와 매우 비슷한 픽셀값을 가지도록 할 것이고, layer가 깊다면 content와 너무 동떨어진 이미지가 생성될 것이다. 따라서 layer l은 너무 얕지도, 깊지도 않은 layer로 선택해야 한다.

 

그리고 pre-trained ConvNet을 사용해서, content image와 generated image가 주어지면 이 두 이미지가 얼마나 유사한지 측정하면 된다.

즉, a[l](C), a[l](G)를 구해서, 두 activation이 유사하다면 두 이미지가 비슷하다라는 것을 의미한다.

그래서 Content Cost는 다음과 같이 구할 수 있고, 우리는 이 Cost를 최소화하도록 최적화하면 된다.

 

[Style Cost Function]

 

이미지의 style이 의미하는 것은 무엇일까? 

Style Image의 측정방법을 정의하기 위해서 우리고 한 layer L을 선택했다고 가정해보자. 

그렇다면 우리는 channel들 사이에서 분포하는 activation들의 상관 관계로 style을 정의할 수 있다.

한 layer L을 통해서 n_H, n_W, n_C =5 의 block이 output으로 나왔을 때, 각 channel들의 쌍을 서루 비교해서 어떤 상관관계를 가지고 있는지 확인하는 것이다. 

따라서, 만약 빨간색 channel과 노란색 channel이 있을 때, 빨간색 채널은 수직 텍스쳐를 나타내고, 노란색 채널은 주황빛 계열의 색을 나타낸다고 하자. 만약 두 채널이 서로 상관관계가 높다면 수직 텍스쳐가 있을 때, 주황빛 계열을 가지게 된다는 뜻이고, 상관관계가 없다면 수직 텍스쳐가 있더라도 주황 계열이 아닐 수도 있다는 것이다. 

 

이렇게 상관관계의 정도로 생성된 이미지와 Input Style 이미지의 유사한 정도를 측정할 수 있다. 

위 아이디어를 공식으로 표현하면 다음과 같다.

G_{k{k}'}^{[l](G)}의 식에서 마지막 activation의 아래첨자 k에 '가 빠져있음

Style matrix로 모든 상관관계를 측정하는데, Style matrix는 위와 같이 계산된다. G_{k{k}'}^{[l]} k {k}'의 상관관계 정도를 의미하며 k는 1 ~ 의 값이다. Gram matrix라고도 부른다. 이렇게 Style matrix를 정의하고, 이 행렬들을 사용해서 Style Cost function을 정의하면 다음과 같다.

여기서 \lambda(정규화 상수)는 어짜피 Cost Function에서 \beta를 곱하기 때문에 중요하지 않다.

 

1D and 3D Generalizations

1D

  • 1D로의 변환은 단지 너비와 높이가 없이 일렬로 값들이 나열된다는 차이점 뿐이다.
  • (14x14x3)의 2D 이미지가 (5x5x3)의 필터를 거쳐 (10x10x16)의 output으로 나오는 연산은 (14x1)의 1D 정보가 (5x1)의 필터를 거쳐 (10x16)의 output으로 나오는 연산과 동일하다.

3D

  • 3D의 예시로 CT 촬영을 들 수 있다.
  • CT는 몸의 각 단면을 스캔하는 것으로 너비, 높이 외에 깊이에 대한 정보가 추가된다.
  • 따라서, 필터도 3차원으로 구성되며 (14x14x14x1)의 이미지가 (5x5x5x1)의 필터를 거쳐 (10x10x10x16)의 output을 출력하는 예를 들 수 있다.

 

 

배경

  • 모바일 기기 및 엣지 디바이스를 위한 딥 러닝 모델 배포 및 활용 필요성의 급속한 증가
  • 최근의 드론, 로봇을 포함하여, 스마트폰 및 다양한 IoT 기기들은 그 컴퓨팅 환경의 특성으로 인해 제한된 연산 능력, 메모리, 전력을 가지고 효율적으로 컴퓨터 비전, 음성 및 자연어 처리 등과 관련한 딥 러닝 모델 탑재 및 추론이 지속적으로 요구되고 있음
  • 이를 위해 딥 러닝 알고리즘을 경량화 하여 적은 저장 공간, 연산량을 요구하면서 고속으로 추론할 수 있는 기술을 필요로 함
  • 이에 따라 딥 러닝 모델의 경량화 및 추론에서의 효율성에 관한 관심이 점차 증가하고 있음

 

딥러닝 모델 경량화란?

딥뉴럴 네트워크에서 방대한 연산량을 줄이기 위한 연구.

경량화를 하는 이유는 real-time에서 작동하지 않기 때문에 latency를 빠르게 하기 위해서, 메모리를 많이 차지 하기 때문에 memory를 줄여서 특정 환경에서 실행하기 위해, 하드웨어 디바이스 중에는 8비트만 지원하기 때문에 평소에 사용하던 32비트를 8비트로 변환하기 위해서 등이 있습니다.

GPU 뿐만 아니라 모바일, 엣지 디바이스, 클라우드 등에 딥러닝 모델이 쓰이기 위해서 연구되고있다.

 

딥러닝 경량화 방향

딥러닝 경량화에 대한 연구는 알고리즘 자체를 적은 연산과 효율적인 구조로 설계해서 기존 모델 대비 효율을 극대화하는 ‘경랑 딥러닝 알고리즘 연구’와, 이미 만들어진 모델의 파라미터를 줄이는 ‘모델 압축’ 기법으로 나눌 수 있다.

  • 경랑 딥러닝 알고리즘 => 새로운 알고리즘을 만듦
  • 모델 압축(알고리즘 경량화) => 기존의 알고리즘을 경량화 시킴

 

<ETRI 경량 딥러닝 기술 동향>

 

https://lv99.tistory.com/35

'딥러닝 이론' 카테고리의 다른 글

AutoEncoder  (0) 2022.08.24
Meta Learning  (0) 2022.08.22
*Transformer  (0) 2022.07.06
RNN & LSTM  (0) 2022.07.06
CNN  (0) 2022.06.30

Object Localization

Object Detection(객체 탐지)를 위해서는 먼저 Object Localization에 대해서 학습하는 것이 필요하다.

Classification with localization은 단순히 이 object가 자동차라는 것뿐만 아니라, 이 알고리즘이 object를 대상으로 bounding box를 표시하는 것을 의미한다.(자동차 위치 주변을 따라서 빨간 박스를 그리는 것)

 

강의 후반부에서 Detection Problem에 대해서 알아볼텐데, 사진 속에 object가 여러개인 경우가 발생한다. 이때, 모든 object를 탐지해야될뿐만 아니라 위치 또한 알아내야한다. 특히 자율주행에서 이 작업을 수행할 때, 다른 자동차들 뿐만 아니라 보행자, 오토바이, 다른 주변 물건들까지도 탐지해야할 수 있다. 지금은 하나의 object만 다루도록 한다.

 

우선 Classification with localization에 대해서 자세히 알아보도록 하자.

우리는 이미 이미지를 분류하는 것에 대해서는 익숙할텐데, 여러 layer로 이루어진 ConvNet에 이미지를 입력해서 softmax unit이라는 output vector로 class를 예측할 수 있다.

여기서 예시로 총 4개의 class가 있고, softmax unit은 총 4개가 될 것이다.

여기서 만약 이미지에서 자동차의 위치를 알아내고 싶다면 어떻게 해야될까?

위치를 탐지하기 위해서는 Bounding Box의 위치를 나타내는 output을 갖도록 Neural Network를 변경하면 된다. 즉, output으로 b_x, b_y, b_h, b_w가 추가될 수 있다. 이 output은 탐지된 object의 bounding box를 파라미터로 나타낸 것이다. bounding box의 중앙 좌표(b_x, b_y)와 폭(b_w) 그리고 높이(b_h)에 의해서 위치를 탐지하게 된다.

(강의에서는 왼쪽 위 모서리를 (0, 0), 오른쪽 아래 모서리를 (1, 1)로 표시한다.)

 

이제 신경망이 예측하려고자 하는 training set는 object의 label뿐만 아니라 4개의 정보(bounding box)가 추가된다. 

위 이미지에서는 b_x = 0.5, b_y = 0.7, b_h = 0.3, b_w = 0.4로 나타낼 수 있을 것이다.

 

따라서 target의 label y는 아래와 같이 정의될 수 있다.

여기서 p_c는 이미지에 object가 존재하는지에 대한 확률이고, b_x, b_y, b_h, b_w는 bounding box의 위치정보, 나머지 c_1, c_2, c_3는 각 class일 확률이다. 

그래서 아까전 예시인 이미지는 왼쪽과 같이 y를 나타낼 수 있고, 만약 이미지에 object가 없다면 p_c = 0이고 나머지 정보는 'don't care'로 표시된다.

 

다음으로는 신경망을 학습시키기 위한 Loss Function(손실 함수)에 대해서 알아보도록 하자.

기본 true label은 y 그리고 신경망을 통해 나온 pred label은 이다. 

그리고 MSE(mean squared error)를 사용한다면, Loss function은 다음과 같다.(y는 8개의 unit을 가지고 있다)

(p_c = 0이라면 나머지 값은 모두 don't care이기 때문에 두번째줄처럼 계산된다)

 

설명을 단순하게 하기 위해서 MSE를 예시로 설명했지만, c_1, c_2, c_3에는 log-likelihood loss와 softmax를 사용하고, bounding box 정보에는 MSE를, 그리고 p_c에는 Logistic Regression Loss를 사용할 수도 있다.

 

Landmark Detection

우리는 신경망이 탐지할 object의 bounding box를 위치시키기 위해서 b_x, b_y, b_h, b_w 정보를 신경망의 output으로 내보내는 방법을 살펴보았다. 더 일반적인 경우에서는 신경망에서 이미지의 주요 포인트(landmark)를 X와 Y의 좌표로 나타낼 수 있다.

얼굴 인식에서 우리가 사람 눈의 코너부분이 어디에 있는지 인식하기 위해서 눈의 코너 부분의 X, Y 좌표를 가질 수 있을 것이다. 따라서 신경망의 output이 눈의 코너 부분의 좌표가 되도록 할 수 있다. 

만약 두 눈의 네 개의 코너를 전부 알고 싶다면, l로 output을 출력하도록 수정할 수 있다. 물론 4개 지점 이상의 output도 가능하다.

만약 입을 따라서 주요 landmark를 표시하면, 우리는 입 모양을 찾아내서 이 사람이 웃고 있는지 인상을 쓰고 있는지 말할 수 있을 것이다. 

 

얼굴에 64개의 랜드마크가 있다고 가정해보자. 우리는 이 모든 랜드마크를 포함하는 training set의 label을 생성해서 신경망이 얼굴의 주요 랜드마크가 어디에 있는지 학습시킬 수 있다.

따라서 output으로는 이 이미지가 얼굴인지 아닌지에 대한 정보 1개와 각 랜드마크의 위치 정보 128개, 총 129개의 output을 가질 수 있다. 이것은 얼굴의 감정을 인식하기 위한 기본 구성이 된다. (스냅챗, AR 필터 등에 사용)

 

만약 포즈를 감지하는 알고리즘을 학습한다면, 위와 같이 어깨, 팔꿈치, 팔목 등의 몇 가지 랜드마크의 위치들을 정의할 수 있다.

 

주의해야 할 점은 각 랜드마크가 일관성이 있어야 한다는 것이다. 만약 landmark 1은 언제나 왼쪽 눈의 코너부분이고, landmark 4는 항상 오른쪽 눈의 코너부분을 가리켜야한다는 것이다.

 

 

Object detection

앞서 object localization과 landmark detection에 대해서 알아봤고, 이번에는 다른 object detection 알고리즘을 구성해보도록 하자. 바로, Sliding Windows Detection 알고리즘을 사용해서 Object Detection을 위해 ConvNet을 사용하는 방법이다.

 

만약 자동차를 감지하는 알고리즘을 만든다고 가정해보자. 우선 우리는 input x와 output y로 label된 training set를 만들 수 있다. 

그래서 이 ConvNet은 ouput y를 출력한다.(input image가 자동차인지 아닌지)

 

그리고 다음으로는 특정 사이즈의 window를 하나 골라서, 탐색을 시작한다. 

그리고 직사각형 영역에 포함되는 이미지를 ConvNet의 입력으로 사용해서 직사각형 영역에 자동차가 있는지 없는지 확인하는 것이다. 위 이미지 위치에서는 자동차가 없다고 output을 나타낼 것이다. 그런 다음에 직사각형 box를 약간 옆쪽으로 옮기고 다시 ConvNet의 입력으로 사용해서 자동차가 있는지 확인한다. 

이런 방법으로 Sliding Window 알고리즘은 빨간 사각형이 포함하는 이미지 영역을 가져와서 ConvNet으로 수행하는 작업을 반복한다. window가 위치할 수 있는 모든 위치에서 확인할 수 있도록 계속 반복한다. 만약 조금 더 빠르게 진행하고 싶다면 strides를 더 크게 지정해서 sliding window 알고리즘을 수행할 수도 있다.(정확도는 떨어지겠지만)

그리고 더 큰 box를 사용해서 위 작업을 반복한다.

 

sliding window 알고리즘에 큰 단점은 바로 Computaion Cost이다. 이미지에서 많은 box 영역들을 추출해서 Convnet으로 각각 독립적으로 확인하기 때문이다. 만약 아주 큰 stride를 사용한다면, 확인할 box 영역들은 줄어들어서 더 빨라지겠지만, 성능에 안좋은 영향을 끼칠 수 있다. 그리 나쁜 방법은 아니지만, sliding window는 매우 느리고, 또한 매우 작은 stride를 사용하지 않는 한, object의 정확한 위치를 감지하는 것도 불가능하다.

 

다행히 Computation Cost에 대한 좋은 방법이 있다.

 

Convolutional Implementation of Sliding Windows 

위에서 보았듯이 ConvNet을 사용한 Sliding Window 알고리즘을 알아봤는데, 이 방법이 매우 느리다는 것을 보았다.

이번에는 이 알고리즘을 어떻게 Convolutional하고 실행할 수 있도록 FC(Full connected) layer를 Convolutional Layer로 튜닝하는 것을 알아볼 것이다.

 

Object Detection 알고리즘이 14x14x3의 input을 가진다고 가정하고, 5x5 filter 16개를 사용한다고 하자.

위 구조는 기본적으로 object를 분류하기 위한 모델이다. 

 

object detection을 위해서 우리는 위 모델에서 FC를 400개의 5x5 filter로 튜닝해서 아래와 같이 convolve 시킬 것이다.

이렇게 튜닝한 모델이 어떻게 object detection(sliding window)에 사용이 될까? (OverFeat 논문에 근거)

우리는 14x14x3의 input image를 ConvNet에 통과시켜서 1x1x4의 결과를 얻었다.

만약 16x16x3의 input을 입력으로 사용한다면 어떻게 되는지 살펴보자.

기존 sliding window 알고리즘이라면, 14x14 box를 사용해서 한 칸씩 이동하면서 각각의 14x14x3 이미지가 ConvNet에 독립적으로 수행하게 된다.(stride가 2라면 16x16x3의 이미지에서 총 4번의 ConvNet 연산이 수행된다)

즉, 16x16x3 이미지를 입력으로 사용하면, 총 4개의 14x14x3의 입력을 각각 ConvNet을 수행하게 되고 겹치는 부분은 연산이 중복된다. 

하지만, 위에서 튜닝한 방법을 사용하면 4개의 이미지에서 중복되는 연산이 공유가 가능하게 된다.

16x16x3을 튜닝한 ConvNet에 통과시키면 2x2x4의 output이 나오게 되고, 1x1x4의 output이 총 4개가 나오게 되는 것이다. 따라서, 튜닝을 통해서 독립적인 input으로 계산하는 것이 아닌, 4개의 input을 하나의 계산으로 결합해서 공통되는 부분을 공유하게 되는 것이다.

 

28x28x3의 이미지로 다시 한번 어떻게 결과가 나오는지 살펴보자.

기준이 되는 box의 크기가 14x14이기 때문에, 28x28x3의 이미지에서 sliding window를 적용하면 총 8x8개의 독립적인 input이 생기게 된다. 하지만 튜닝한 ConvNet을 사용하면 공통되는 연산 부분을 공유하게 되고, output으로 8x8x4의 결과를 얻을 수 있다. 이렇게 Sliding Window의 연산 비용 문제가 해결이 된다.

(여기서 이미지가 8x8개의 구역으로 나뉘어지는 것은 MaxPool의 stride의 영향이다)

 

하지만, 여기에는 bounding box의 위치가 그리 정확하지 않다는 단점이 있는데, 이 문제는 어떻게 해결할 수 있는지 살펴보도록 하자.

 

Bounding Box Predictions

Slinding Window 알고리즘에 Convolutional 구현을 적용해서 계산 비용 문제를 해결했지만, 정확한 bounding box를 찾을 수가 없다는 문제가 발생했다. 즉, Slinding Window의 box를 사용해서 탐색하다보면, object가 정확하게 그 box에 위치하지 않고 object의 일부만 걸치는 문제가 발생할 수 있다는 것이다.

또한, object가 정사각형의 bounding box를 가지지 않을 수도 있다.

 

결론을 먼저 이야기하면, 정확한 bounding box를 가져오는 방법은 YOLO(You Only Look Once) 알고리즘을 사용하는 것이다.

 

input 이미지가 100x100인 경우를 예시로 살펴보자. 

우선 이미지의 3x3 grid를 설정한다. (설명을 위해서 3x3으로 설정했지만, 보통 19x19 grid를 사용)

YOLO 알고리즘의 기본 아이디어는 위에서 학습했던 Image Classification과 Image Localization을 9개의 grid에 각각 적용하는 것이다. 

그리고 training set에서 사용하는 label을 정의해주어야 하는데, 9개의 grid셀에 대해서 label y를 설정한다. 여기서 y는 위에서 본 것처럼 8차원 vector이다.(p_c, b_x, b_y, b_h, b_w, c_1, c_2, c_3)

YOLO 알고리즘은 Object의 중간점(Mid Point)를 취해서, 이 중간점을 포함하는 grid 셀에 object를 할당한다.

그래서, 왼쪽 위 보라색 셀은 object가 존재하지 않기 때문에 p_c = 0이 되고 나머지 요소들은 'don't care'가 된다. 초록색으로 표시된 셀은 차량이 존재하고, 그 차량의 중간점이 포함되기 때문에 [1, b_x, b_y, b_h, b_w, 0, 1, 0] 으로 labeling되고, 노란색으로 표시된 셀도 마찬가지이다.

 

3x3 grid로 구역이 나누었고, 각 grid 셀에서 8차원 vector y를 가지고 있기 때문에, 목표로하는 output의 3x3x8의 형태를 가지게 되며, output은 각각의 구역과 매칭이 된다.

즉, input 100x100x3을 Conv와 MaxPool을 거쳐서 3x3x8의 output이 나오게 된다. 여기서는 3x3 grid를 사용했지만, 보통 19x19 grid를 사용하고, 19x19 grid를 사용한다면 output은 19x19x8의 형태를 띄게 된다.

(19x19 grid를 사용한다면, 더욱 세밀하게 구역을 나누는 것이고, 하나의 셀에 여러개의 object가 할당될 가능성을 감소시켜준다. -> 하나의 셀에 object의 Mid Point가 두 개가 될 확률을 줄여준다.)

 

결국 YOLO 알고리즘은 Object Classification/Localization과 Sliding Window Convoluional Implementation을 합친 것이라고 볼 수 있다.

 

추가로 bounding box의 b_x, b_y, b_h, b_w는 어떻게 인코딩을 해야할까 ?

YOLO 알고리즘에서 각 cell에서 왼쪽 위의 점은 (0, 0)이고, 오른쪽 아래의 점은 (1, 1)이다. 그리고 너비와 높이는 cell의 전체 너비와 높이의 비율로 지정된다. 따라서 노란색 셀에 있는 차량의 bounding box 정보는 b_x = 0.4, b_y = 0.3, b_h = 0.9, b_w = 0.5로 나타낼 수 있다. 

그리고 bounding box의 mid point는 (0, 0)과 (1, 1) 사이의 좌표값을 가지기 때문에 항상 0에서 1사이의 값을 가지게 되지만, bounding box의 너비와 높이는 각 cell의 크기를 벗어날 수 있기 때문에 1보다 커질 수 있음에 유의한다.

 

Bounding box를 설정하는 방법은 여러가지가 있지만, 위 방법도 합리적인 방법 중의 하나이며, YOLO 논문을 살펴보면 훨씬 더 잘 동작할 수 있도록 파라미터화된 것들이 있다.

 

Intersection Over Union (IOU)

Intersection over union(IoU)은 Object Detection이 잘 동작하는지 판단하기 위한 함수이다. 이 함수는 Object Detection 알고리즘을 평가할 때나 더 잘 동작되도록 하기 위해서 사용된다.

만약 Object Detection 알고리즘을 통해서 보라색의 bounding box를 얻었다면, 이것은 좋은 결과일까?

좋은 결과인지 판단하기 위해서 IoU 함수를 사용하고, 이 함수는 두 개의 bounding box의 Intersection over Union을 계산한다.(여기서는 보라색 박스와 빨간색 박스의 IoU 계산)

즉, 두 개의 bounding box의 전체 넓이와 겹치는 부분의 넓이의 비율을 계산하는데, 보통 IoU 값이 0.5보다 크다면 예측한 bounding box의 결과가 옳다고 판단한다. 

예측된 bounding box가 실제 측정한 bounding box와 완벽하게 일치하면 IoU는 1이 되며, 일반적으로 0.5보다 크거나 같다면 그 bounding box는 합리적이라고 판단한다. 보다 엄격하게 체크하고 싶다면, 기준을 0.6 등으로 높이면 된다.

 

IoU는 Object Localization Detection의 정확성 여부를 평가하는 방법이고, 일반적으로는 두 bounding box 사이의 겹치는 정도의 척도라고 할 수 있다. 또한, 두 bounding box가 얼마나 비슷한지 측정하는 방법이 될 수도 있다.

 

IoU는 non-max suppression에서 사용된다.

 

Non-max Suppression

지금까지 알아보았던 Object Detection의 문제점 중 하나는 알고리즘이 동일한 object를 여러번 탐지할 수 있다는 것이다.

즉, 위와 같이 19x19 grid를 사용했을 때, object의 Mid Point가 다양한 cell에서 포함된다고 판단될 수 있다는 것이다. 

이 경우에 Non-max suppression을 사용하면 알고리즘이 하나의 object를 하나의 cell에서 한번만 탐지할 수 있도록 한다.

 

19x19 grid, 361개의 grid cell에서 image classification/localization을 수행하고 있기 때문에, 위와 같이 각 cell에서 object가 여기에 있다고 판단할 수 있다. (박스 옆에 숫자는 p_c를 의미한다.) 따라서, 알고리즘을 실행할 때, 각 object에 대해서 여러 번의 탐지가 이루어 질 수 있다. 

 

여기서 non-max suppress가 하는 일은 하나의 object에 대한 여러 탐지를 정리하는 것이다. 

우선 각각의 detection과 관련된 확률을 조사한다. 즉, p_c를 체크하는 것인데, 실제 알고리즘에서는 c_1, c_2, c_3와 곱한 확률을 의미하지만, 여기서는 자동차 class만 판단한다고 가정하고(class가 하나만 존재) 단순히 p_c만을 가지고 설명하도록 하겠다.

p_c를 조사하고 가장 큰 것만 취한다. 위 이미지의 오른쪽 차량의 경우에는 0.9의 p_c만을 취하는 것이다. 

 

그리고 나서, non-max suppress는 남은 box들을 가지고, 0.9의 box와의 IoU를 조사한다.

그리고, 계산된 IoU가 많이 겹쳐있어서 높다면, 그 box는 suppress(제거)한다. (class가 여러개인 경우) 만약 낮은 IoU라면, 다른 object를 탐지했을 가능성이 높고, 제거하지 않는다. 위 경우에서는 차량만 탐지하는 예시였고, IoU 또한 높은 값으로 겹쳐있으므로 나머지 0.6, 0.7의 box는 제거된다.

이미지 왼쪽의 차량도 마찬가지이다.

 

따라서, non-max suppress 과정을 거치면 다음과 같이 정리가 된다.

위 예시를 통해 non-max suppression 알고리즘을 정리하면 다음과 같다. (class는 차량판단만 한다고 가정)

1. 각 cell의 output에서 p_c를 조사해서 0.6 이하라면 제거

2. 남은 box 중에서 가장 높은 p_c를 갖는 박스를 예측된 bounding box로 선택

3. 남은 box들의 IoU(2에서 선택한 박스와의 IoU)를 계산해서 0.5보다 크다면, 같은 object일 확률이 높으므로 제거

 

여기서 class가 자동차 하나뿐이었지만, 만약 자동차/보행자/오토바이로 3개의 object를 탐지한다면, non-max suppress를 독립적으로 각각 3회 수행한다.(output class당 수행해야함)

 

Anchor Boxes

지금까지 보았듯이 Object Detection의 문제점 중의 하나는 각 grid cell이 오직 하나의 object만 감지할 수 있다는 것이다. 여기에서 우리는 anchor box라는 아이디어를 가지고 이 문제를 해결할 수 있다.

 

다음과 같은 예시를 살펴보자.

위 이미지에서 자동차와 사람은 거의 동일한 Mid Point를 가지고 있다. 즉, 이전의 알고리즘을 사용한다면, output y가 탐지할 object 중의 하나를 선택해야 한다.

 

하지만 anchor box를 사용하면 이 문제를 해결할 수 있는데, 우선 anchor box의 모양을 미리 정의한다.

그리고 두 개의 anchor box를 output과 연관시킨다. (일반적으로 5개 or 그 이상의 anchor box를 사용함)

따라서 두개의 anchor box로 인해서 output y는 각 anchor box에 대한 8차원의 unit을 가지게 된다.

위 이미지에서 보행자는 Anchor Box 1에 더 유사하고, 자동차는 Anchor Box 2에 더 유사하기 때문에, Anchor Box 1에 대한 output은 보행자 정보로, Anchor Box 2는 자동차 정보로 인코딩 할 수 있다.

 

Anchor Box 알고리즘을 정리하면 다음과 같다.

이전에는 학습 이미지에서 각 object는 object의 Midpoint를 포함하는 하나의 grid cell에 할당이 되었다면,

두 개의 Anchor Box를 사용함으로, 각 object는 object의 Midpoint를 포함하는 grid cell에 할당됨과 동시에 IoU가 가장 높은 Anchor Box에 할당된다.

즉, object는 (grid cell, anchor box)의 쌍으로 할당이 되는 것이다.

 

따라서, 위 이미지 예시에서 output y는 다음과 같다.

만약 이 이미지에서 사람이 없다면, Anchor Box 1에 대한 정보에서 p_c는 0이되고, 나머지는 'don't care'가 된다. 그리고 Anchor Box 2의 정보는 그대로 차량의 정보를 가지게 될 것이다.

 

여기서 2개의 Anchor Box를 사용했는데, 만약 3개의 object의 Midpoint가 같은 grid cell에 있다면 어떻게 될까?

이런 경우에는 알고리즘이 잘 처리하지 못하게 될 것이다. 이런 경우에 default tiebreaker(3개 이상의 object가 탐지될 경우의 예외)를 설정해두어야 한다. 실제 19x19 grid에서 두 object가 같은 midpoint를 가지는 확률이 그리 크지는 않다.

 

Anchor Box의 선택은 manual로 선택을 할 수도 있고, K-mean 알고리즘을 통해서 얻고자하는 유형의 object 모양끼리 그룹화할 수도 있다.

 

YOLO Algorithm

이번에는 위에서 알아봤던 내용들을 결합해서 YOLO Object Detection Algorithm을 정리해보자.

 

먼저 training set를 구성하는 방법이다.

여기서 anchor box를 두 개 사용할 것이고, class는 총 3개이기 때문에 output y의 shape는 3x3x2x8 or 3x3x16이다.(보통 anchor box별로 나누지 않고, vector 꼴로 나타내는 것으로 보임)

여기서 대부분의 grid cell은 object가 존재하지 않기 때문에, 각 anchor box의 p_c는 0이고, 초록색으로 표시된 cell에만 object가 존재한다. 또한, 차량의 bounding box가 anchor box 2의 모습과 유사하기 때문에(더 높은 IoU를 가지기 때문) anchor box 2에 해당하는 정보를 구체화한다. 

 

만약 19x19 grid cell을 사용하고, anchor box 또한 5개를 사용한다면, output y는 19x19x5x8 or 19x19x40의 shape를 갖게 된다.

 

그리고 예측을 하게 되면, 다음과 같다.

object가 없는 cell은 파란색과 같은 결과를 나타낼 것이고, 초록색 cell은 anchor box 2에 bounding box의 정보를 담아서 output으로 예측할 것이다.

 

마지막으로 non-max suppression을 수행하는데, 다른 이미지를 가지고 살펴보자.

anchor box가 두개이기 때문에, 각 grid cell은 최대 2개의 bounding box를 가질 수 있다. 여기서 낮은 확률을 가지는 예측 결과는 제거하고, 각 class에 non-max suppression을 적용해서 최종 예측결과를 얻는다.

YOLO 알고리즘은 실제로 가장 효과적인 Object Detection 알고리즘 중의 하나이다.

 

Region Proposals (R-CNN)

Sliding Window 알고리즘을 떠올려보면, window들을 슬라이딩하면서 object를 탐지하는 방법이지만, 많은 구역들을 살펴보는 단점이 있다.

R-CNN은 이렇게 탐지하는 것이 아닌, 이미지로부터 Region 후보군을 뽑아내서 object를 탐지하는 방법이다.

즉, 오른쪽 이미지처럼 segmentation algorithm을 통해서 여러개의 집합(?)으로 나누어서 유사한 픽셀들을 뽑아내서 object를 탐지한다.

물론 R-CNN 알고리즘은 느리지만, 이 알고리즘의 속도를 높이기 위한 연구들이 있었다.

(자세한 것은 더 알아봐야겠지만.. 결국에는 Segmentation 알고리즘에 Convolutional network를 적용해서 각각 독립적으로 수행하는 것이 아닌, 한 번의 연산으로 탐지를 하는 것으로 생각된다.)

 

Semantic Segmentation with U-Net

  • Semantic Segmentation 은 컴퓨터비젼 분야에서 가장 핵심적인 분야 중 하나이며,
  • 위 그림처럼, 이미지 내에 있는 물체들을 의미 있는 단위로 분할해내는 것입니다.
  • 더 구체적으로는 아래 그림처럼, 이미지의 각 픽셀이 어느 클래스에 속하는지 예측하는 것입니다.

  • Semantic Segmentation은 다른 컴퓨터비젼 문제들과 마찬가지로, Deep Convolution Neural Network (깊은 신경망)을 적용해서 많은 발전을 이루었습니다.
  • 이번 포스트에서는 Semantic Segmentation 에 대해서 자세히 설명하고, 자주 활용되는 몇가지 접근방법을 알아보겠습니다.

Semantic Segmentation의 의미와 목적

  • Semantic Segmentation 의 의미와 목적에 대해 알아보겠습니다.
  • 우선, 컴퓨터 비젼에서 가장 많이 다뤄지는 문제들은 아래와 같은 것들이 있습니다.
    • Classification (분류)
      • 인풋에 대해서 하나의 물체를 구분하는 작업
      • LeNet, AlexNet, VGG Nets, GooLeNet, ResNet, Xception 등의 모델
    • Object Detection (객체 탐지)
      • 물체를 구분함과 동시에, 그 물체가 어디에 있는지까지 Boxing하는 작업
      • RCNN, Fast RCNN, Faster RCNN, SPP Net, YOLO, SDD, Attention Net 등의 모델
    • Segmentation (분할)
      • 모든 픽셀에 대해, 각 픽셀이 어떤 물체의 class인지 구분하는 작업
      • FCN, DeepLab, U-Net, ReSeg 등의 모델
  • 따라서, Semantic Segmentation의 목적은 사진에 있는 모든 픽셀을, 해당하는 class로 분류하는 것입니다.
    • 이미지에 있는 모든 픽셀에 대한 예측을 하는 것이기 때문에, dense prediction 이라고도 불립니다.
  • 또한, Semantic Segmentation은 두 가지로 나뉩니다.
  • 바로, Semantic Segmentation과 Instance Segmentation입니다.
  • 예제를 통해 자세히 알아보겠습니다.
  • 만약, 위 예제처럼 가족사진이 주어졌을 때,
  • Semantic Segmentation은 오른쪽처럼, 픽셀 단위로 어떤 class인지만 구분하지만
  • Instance Segmentation은 왼쪽처럼, 픽셀 단위로 어떤 class인지 구분한 이후, 동일한 class 내에서도 다른 Instance를 구분합니다.

 

Transpose Convolutions

Convolution 계산을 하면 feature map이 작아진다. 반대로 feature map이 커지게 하려면 어떻게 해야할까? 단순하게 생각해보면 Convolution 계산과정을 역으로 하면 된다.
(조립은 분해의 역순…)

 

위 Convolution 그림에서 input의 빨간색 박스안에 있는 원소들이 kernel과 곱해져서 output의 빨간색 원소가 된다. input의 파란색 박스 안에 있는 원소들은 output의 파란색 원소와 대응한다. output의 나머지 원소에 대해서도 마찬가지로 대응하는 원소들을 찾을 수 있다. 그림에서는 나머지 원소에 대한 대응 원소 표시는 생략하였다.

 

input과 output의 위치를 바꿔서 생각해보자. 위 그림에서 input의 빨간색 원소는 output의 빨간 박스 안에 있는 원소들과 연관이 있다. 마찬가지로 input의 파란색 원소는 output의 파란색 박스 안에 있는 원소들과 대응한다.

Transposed Convolution을 계산하는 방법은 이렇다. input의 빨간색 원소를 3x3 kernel에 곱해서 output의 대응하는 자리에 집어넣는다. 같은 방법으로 input의 파란색 원소를 3x3 kernel에 곱해서 output의 대응하는 위치에 집어넣는다. 이 때 output에 겹치는 구간(빗금 표시)이 발생하는데, 겹치는 부분의 값은 모두 더해준다. input의 나머지 원소에 대해서도 동일한 방법으로 계산한다.

 

U-Net Architecture

U-Net은 Semantic Segmentation Task 수행에 널리 쓰이는 모델 중 하나입니다.

  • U-Net 구조
    • U-Net의 구조는 알파벳 U의 왼쪽 절반에 해당하는 Contracting Path와
    • 오른쪽 절반에 해당하는 Expanding Path의 2가지 Path로 분리할 수 있습니다. 
  • 1) Contracting Path
    • Contracting Path는 Encoder의 역할을 수행하는 부분으로 전형적인 Convolution Network로 구성됩니다.
    • Contracting Path는 입력을 Feature Map으로 변형해 이미지의 Context를 파악합니다.
    • 이 경우에 Contracting Path의 앞단에 이미 잘 학습된 모델을 Backbone으로 사용해 학습 효율과 성능을 높일 수 있습니다. 주로 ResNet 등의 모델을 사용합니다.
  • 2) Expanding Path
    • Expanding Path는 Decoder의 역할을 수행하는 부분으로, 전형적인 Upsampling + Convolution Network로 구성됩니다.
    • 즉, Convolution 연산을 거치기 전 Contracting Path에서 줄어든 사이즈를 다시 복원하는(Upsampling) 형태입니다.
    • Expanding Path에서는 Contracting을 통해 얻은 Feature Map을 Upsampling하고,
    • 각 Expanding 단계에 대응되는 Contracting 단계에서의 Feature Map과 결합해서(Skip-Connection Concatenate) 더 정확한 Localization을 수행합니다.
    • 즉, Multi-Scale Object Segmentation을 위하여 Downsampling과 Upsampling을 순서대로 반복하는 구조입니다.

Why look at case studies?

여러 연구/논문에서 CNN의 효과적인 Building Block 구성 방법이 연구되었으며, 이런 예시들을 참고하는 것이 CNN으로 학습할 때 유용하다. 

 

현대 Computer Vision의 토대가 되는 Classic Networks는 아래와 같은 것들이 있다.

  • LeNet-5
  • AlexNet
  • VGG

그리고, 다음 강의에서 CNN에서 유용하게 사용되는 ResNet or Conv Residual Network와 Inception Neural Network를 알아볼 것이다.

 

Classic Networks

[LeNet-5]

[Input -> Conv2D -> Avg Pool -> Conv2D -> Avg Pool -> FC -> FC -> output]

LeNet-5의 구조는 위와 같다. 

위 논문이 작성될 시기에는 Average Pooling이 많이 사용되었으며, padding이나 valid convolution을 사용하지 않았다. 그리고 논문에는 non-linearity(비선형) 활성화 함수로 ReLU가 아닌 sigmoid나 tanh 함수를 많이 사용했다.(당시에 비선형성을 사용하지 않았음)

 

LeNet의 구조는 신경망이 깊어질수록 높이와 폭(N_H, N_W)가 줄어드는 경향이 있고, 채널 수(N_C)는 증가하고 있다. output에는 최근에는 softmax를 많이 쓰지만, 당시에는 다른 분류기를 사용했고, 현재보다 작은 신경망으로 약 60,000개의 파라미터를 가지고 있다.

 

[AlexNet]

AlexNet의 구조는 위와 같고, LeNet과 유사한 구조를 가지고 있지만, 더 크다는게 차이점이다. 약 6천만개의 파라미터가 존재한다. 여기서는 비선형으로 ReLU를 사용하며, Multiple GPU도 사용한다. 그리고 Local Response Normalization(LRN)을 사용했는데, 연구를 통해서 성능에 크게 영향을 미치지 않는다고 밝혀졌고 최근에는 잘 사용하지 않는다.

 

[VGG-16]

VGG-16 Network에서 주목할 만한 점은 많은 하이퍼파라미터를 가지고 있지만, 네트워크를 더 단순하게 만들었다는 것이다. [ConV(3x3 filter, strides=1, same convolution) -> Max Pool(2x2 filter, strides=2)] 로 구성된 network를 반복해서 사용한다.

구성은 다음과 같다.

VGG-16 이름에서 유추할 수 있듯이 16개의 layer로 구성되어 있으며, 약 1억 3800만개의 파라미터가 있다. 이 수치는 오늘날에도 매우 큰 값이고, 학습시킬 파라미터가 매우 많은 큰 네트워크이다. 하지만, 네트워크가 매우 단순하고 균일한 구조를 가지고 있다는 점에서 매력적이다. VGG-19가 조금 더 큰 네트워크이지만, VGG-16과 거의 유사하다.

 

아주 Deep한 신경망은 Vanishing Gradient, Exploding Gradient와 같은 문제가 발생하기 때문에 학습시키기가 어렵다.

이 문제를 해결하기 위해서 하나의 layer에서 activation을 취해서 더 깊이 있는 layer에 제공하는 skip connection에 대해서 알아볼 것이다. 이 방법을 사용하면 아주 Deep한 네트워크를 학습시킬 수 있는 ResNet을 만들 수 있다. 심지어 100개가 넘는 layer로 구성된 네트워크도 학습이 가능하다. 

 

[ResNets]

Residual Block

ResNet은 Residual Block이라는 것으로 구성되어 있다. 

Residual Block은 다음과 같다.

 

위와 같이 a^{[l]}이 2개의 layer를 초록색의 main path로 지나게 되면 a^{[l+2]}를 얻을 수 있다. Residual Block에서는 입력인 a^{[l]}을 바로 다음 layer를 뛰어넘고, 그 다음 layer(ReLU를 적용하시키기 전)로 연결시켜준다. 이 path를 shortcut이라고 부르며, a^{[l]}의 정보가 shortcut을 따라 더 깊은 layer로 바로 전달된다. 

따라서 마지막 값은 a^{[l+2]} = g(z^{[l+2]} + a^{[l]})가 된다. 

정리하자면, a^{[l]}이 layer를 하나 혹은 두개씩 건너뛰는 것을 의미한다.

 

ResNet의 구성하는 방법은 이런 Residual Block들을 많이 사용해서 Deep NN을 구성한다. 

 

논문에 사용되는 용어로 shortcut이 없는 일반적인 NN을 Plain Network라고 한다.

Plain Network

 

ResNets은 위와 같이 Residual Block으로 이루어진 네트워크이며, 

만약 Residual Block, Shortcut없이 학습을 수행한다면, 아래 왼쪽 그래프처럼 네트워크가 더 깊어질수록 성능이 안 좋아지는 것을 볼 수 있다. 하지만, ResNet을 사용한다면 Deep Network를 학습하는데 효과적이다.

위 결과는 layer가 많아져도 train error를 저하시킬 수 있다는 것을 보여주고 있고, ResNet을 사용하면 중간에 있는 activation이 더 깊이 전달되어서 vanishing/exploding gradient 문제를 해결되는 것이다.

 

Why ResNets Work?

그렇다면 왜 ResNet이 Deep Network에서 잘 동작하는 것일까?

방금 우리는 더 깊은 네트워크를 만들면 학습 성능에 손상을 줄 수 있다고 했다. 하지만 ResNet을 사용한다면 효과적으로 학습을 시킬 수 있다.

위와 같은 구조가 있고, 네트워크 전체에 걸쳐서 activation function으로 ReLU를 사용한다고 가정한다면, 모든 activation은 0보다 크거나 같을 것이다.(Input은 예외가 있을 수 있음) 

그리고 skip connection의 shortcut에 의해서

a^{[l+2]} = g(z^{[l+2]} + a^{[l]}) = g(W^{[l+2]}a^{[l+1]} + b^{[l+2]} + a^{[l]})

이 된다. 

만약 L2 Regularization을 사용한다면 W^{[l+2]}가 줄어드는 경향이 있을 것이고, bias에도 적용하고 있다면, b^{[l+2]}도 줄어들 수도 있다.

 

극단적으로 W^{[l+2]} = 0, b^{[l+2]} = 0이라고 가정해보자. 

그렇다면 결국 a^{[l]}만 남게 된다. (ReLU이기 때문에) 따라서, a^{[l+2]} = a^{[l]}이라는 것을 보여주고 있고, 또한, Identity function을 학습하는 것은 쉽기 때문에 신경망의 성능을 저하시키지 않는다는 것을 보여준다. 만약, residual block이 없는 deep network에서는 Identity function을 위한 파라미터 선택(학습)이 어렵고, 성능이 떨어진다.

 

한 가지 주의해야하는 것은 z^{[l+2]} a^{[l]}이 같은 dimension을 가져야한다는 것이다. 그래야 shortcut을 적용할 수 있다. 만약 다른 dimension을 갖는다면, 추가 matrix를 사용해서 차원을 동일하게 만들어 줄 수도 있다.

a^{[l+2]} = g(z^{[l+2]} + W_sa^{[l]}

여기서 W_s는 파라미터일 수도 있고, 고정된 matrix일 수도 있다.

위 이미지는 논문에 있는 이미지이다. 그리고 'same convolution'을 사용하기 때문에 z^{[l+2]}, a^{[l]}의 dimension은 일치하게 된다. 만약 다른 Conv나 pooling이 추가되면 W_s와 같은 것으로 dimension을 조정해주어야 한다.

 

Networks in Networks and 1x1 Convolutions

https://hwiyong.tistory.com/45

CNN 설계에 있어서 1x1 convolution을 사용하는 것은 아래와 같은 장점을 가지고 있다.

  • Channel 수 조절
  • 연산량 감소(Efficient)
  • 비선형성(Non-linearity)

만약 28x28x192 volume이 있을 때, 높이와 넓이를 줄이고 싶다면 Pooling layer를 사용하면 된다. 

채널이 너무 많아서, 채널을 줄이고 싶다면(28x28x32로), 32개의 1x1 filter를 사용하면 된다. 각각의 filter는 1x1x192이다.

(어떻게 연산하는지와 어떻게 채널의 수를 줄이는 것이 가능한지는 밑에서 설명)

만약 채널의 수를 192로 유지하고자 한다면, 아래와 같이 filter수를 설정하면 된다.

 
 
 

Inception Network Motivation

아래는 Inception Module이며, feature들을 효과적으로 추출하기 위해서 Conv(1x1, 3x3, 5x5)와 Max-Pooling(3x3)을 각각 수행해서 output을 쌓아올린다. 아래에서는 28x28x192 volume은 Inception Modeul을 통해서 28x28x256 volume이 된다.

Szegedy el al. 2014. Going deeper with convolutions

기본 아이디어는 네트워크가 원하는 파라미터가 무엇이든, 원하는 filter 사이즈 조합이 무엇이든, 이것들을 모두 다 학습하게 하는 것이다. 

하지만, 한 가지 문제점이 존재하는데 연산량이 너무나 많다는 것이다.

5x5 Conv에 대해서 연산량이 얼마나 되는지 한 번 알아보자.

28x28x192 volume에 대해서 5x5 'same' conv 연산을 수행하면, 28x28x32x5x5x192로 1억2천만번의 연산이 수행된다.

 

여기서 방금 전에 언급했던 1x1 Convolution을 적용하면 어떻게 될까? 

결과는 연산량을 약 10배정도 감소시킬 수 있다.

방금 전의 5x5 Conv연산에서 중간에 1x1 Conv 연산을 추가했는데, bottleneck layer(병목층)이라고 부르기도 한다. 중간 과정을 통해서 16채널로 감소시키고, 5x5 Conv 연산을 진행하게 된다.

연산량은 28x28x16x1x1x192(1x1 conv 연산) + 28x28x32x5x5x16(5x5 conv 연산)으로 2.4M + 12.4M이며, 약 1240만으로 1억2천만에서 약 10배정도 감소되었다. 

 

요약하자면, 만약 신경망을 구성할 때, 어떤 layer를 사용할지 잘 모르겠다면 inception module을 사용하면 된다. 하지만 연산량 문제가 있기 때문에 1x1 Conv를 추가해서 연산량을 크게 줄일 수 있었다. 다만, 1x1 Conv를 추가하는 것이 신경망의 성능을 떨어지게 하는 것이 아닌지 의심할 수도 있다. 이 bottlenect layer를 구현함으로써 channel 수를 감소시키며, 성능을 떨어뜨리지는 않는 것처럼 보이고, 연산량을 줄일 수 있다.

이것이 inception module의 기본 아이디어이고, 계속해서 어떻게 full inception network를 구성할 수 있는지 알아보자.

 

Inception Network

방금까지 기본직인 Inception Building Block을 살펴보았고, 이 block을 결합해서 Inception Network를 구현해보도록 하자.

 

Inception Module은 다음과 같이 구성되며, input은 이전 layer에서 나온 activation을 사용한다. 우리는 방금 보았던 28x28x192를 input으로 사용하겠다.

위와 같이 input 28x28x192를 1x1 Conv / 1x1 Conv->3x3 Conv / 1x1 Conv->5x5 Conv / MAXPOOL->1x1 Conv 을 각각 거치도록해서 나온 결과를 합쳐서 28x28x256의 output을 얻는다. MAXPOOL layer 뒤에 1x1 Conv layer가 오는 것에 유의한다(MAXPOOL을 통해서는 channel 수를 감소시킬 수 없어서, 1x1 Conv를 사용해서 channel 수를 줄여준다).

 

이런 block들을 합쳐서 아래와 같은 모델을 구성할 수 있다.

Szegedy et al., 2014, Going Deeper with Convolutions

모델을 보면 알겠지만, 모델 초반에는 Inception Module이 들어가지 않는다.(Stem 영역이라고 하는데, 일반적인 Conv-Pool 스타일을 가지고 있고, 초반에는 Inceoption 효과가 크기 않다고 한다.)

 

그리고, 논문에는 초록색으로 표시된, 모델 output layer 말고, 보조로 사용되는 softmax layer가 존재한다. 이것은 파라미터가 잘 업데이트되도록 도와주며, output의 성능이 나쁘지 않게 도와준다. 또한, regularization 효과를 얻을 수 있고, overfitting 과적합을 방지한다.

 

위 모델은 Google의 개발자들에 의해서 만들어졌고, GoogLenet이라고 부른다.

이 모듈을 기반으로 다른 버전을 만든 것도 있으며, Inception v2, v3, v4와 residual block과 결합된 inception network도 있다. 

 

MobileNet

사물인터넷이나 5G같은 저전력 통신망, 딥러닝이 발달하면서 모든 곳에서 딥러닝을 활용하려고 많은 시도가 이루어지고 있습니다. 이러한 환경에 맞춰 MobileNet이 등장

https://melonicedlatte.com/machinelearning/2019/11/01/212800.html

배포시 cpu나 gpu가 덜 강력한 장치에서 신경망을 실행하기위해서 mobilenet 개발

mobilenet은 Depth-wise separable convolutions 라는 방식을 사용. 비교를 위해 normal한 computational cost를 구해보자.

input size가 6×6×3 이고 5개의 3×3×3 filter로 conv 연산을 했다고 하면, Computational cost는 filter의 파라미터 개수와 output의 파라미터 개수의 곱이므로 3×3×3 * 4×4×5 = 2160이다.   

이를 depthwise를 적용하면 Depthwise Convolution과 Pointwise Convolution 부분으로 나누어서 계산할 수 있다.

Depthwise convolution은 다음과 같이 총 filter의 개수는 생각하지 않고 filter의 채널과 input의 채널을 각자 계산을 하는 것이다. 그렇게 하면 Computational cost에서 filter와 output의 채널 수에 대한 곱이 빠지게 된다. 따라서 한 채널에 해당하는 filter의 파라미터에 output 파라미터를 곱하고 채널의 수를 곱해주면 된다. 3×3 * 4×4 * 3 = 432 개가 나온다.

이제 pointwise convolution을 통해 nomal 방식과 output의 shape을 맞춰준다. Computational cost를 계산해보면 filter의 파라미터 * output 파라미터이므로, 1×1×3 * 4×4×5 = 240 이다.

앞서 봤던 일반적인 계산 방식에서는 2160개의 연산이 필요했는데, depthwise separable 방식을 사용하면 432 + 240 = 672의 연산이 필요한 것을 알 수 있다. 이는 2160의 0.3에 해당하는 숫자이다.

일반적으로 그 수치는 1/(output 채널의 개수) + 1/(filter size의 제곱) 로 예상할 수 있다.

 

 

EfficientNet

네트워크에서 조절할 수 있는 요소로는 Resolution, Depth, Width 등이 있는데 어떤 크기로 어떻게 조합해야 좋은 선택일까?

EfficientNet을 통해 디바이스에 적합한 R, D, W의 조합을 찾을 수 있다.

 

* 파이썬은 대부분의 라이브러리가 이미 다른 사용자에 의해서 구현되어 있음 (파이썬의 장점)

 

* 남이 만든 프로그램 쓰는법 객체 < 모듈

 

* 모듈과 패키지

 

* 패키지 : 여러 모듈을 모아놓은 단위, 하나의 프로그램

새 창에서 열기

Computer Vision

- Image Classification

- Object detection

- Neural Style Transfer

컴퓨터 비전의 문제 중의 하나는 매우 큰 input을 가질 수 있다는 것인데, 만약 3채널(RGB)의 64 x 64 크기의 이미지로 작업을 한다고 했을 때에는 입력의 크기가 64 x 64 x 3 = 12288가 된다. 이정도는 그리 나쁜 것은 아니지만, 만약 1000 x 1000 크기의 매우 고화질의 이미지를 입력으로 사용한다면, 300만의 input size를 가지게 된다. 즉 입력은 300만 차원이 되는 것이고, 다음 hidden layer의 unit size가 1000이라면, (1000, 3m) 차원의 파라미터를 가지게 되는 것이다.

그렇다면 고화질 이미지에 대한 파라미터의 개수는 30억개가 되며, 이렇게 많은 파라미터를 가진 NN이 overfitting(과대적합)을 피할만큼 충분한 데이터를 얻는 것이 어렵고, 컴퓨터 사양이나 메모리 사용량을 고려한다면 실행이 불가능하다.

하지만, 컴퓨터 비전 app을 학습할 때, 작은 이미지에 한정되어서 사용하기는 원하지 않기 때문에, 이러한 문제점을 해결하기 위한 방법들을 배워보도록 할 것이다.

 

Edge detection Example

왼쪽 이미지가 있을 때, 오른쪽처럼 어떻게 수직 모서리나 수평 모서리를 감지할 수 있을까?

그렇다면, 위의 3x3 filter로 convolution 연산을 진행한 것이 어떻게 vertical edge detection을 수행하게 되는 것일까?

조금 더 단순한 이미지를 가지고 convolution 연산한 결과를 살펴보도록 하자.

이미지의 각 element의 숫자가 높을수록 밝고, 낮을수록 어둡다고 할 때, 각 이미지, filter, output은 위와 같이 연산된다.

input 이미지를 봤을 때, 중앙에 edge가 있으며 우리는 이것을 검출하면되는데, 3x3 vertical edge detection filter를 사용해서 연산을 하게 되면 오른쪽 4x4 output을 얻을 수 있다. 중앙에 아주 밟은 하얀색 부분이 존재하게 되는데, 이 부분에 의해서 vertical edge를 감지할 수 있다.

우리가 input 이미지를 꽤 작은 것으로 사용했기 때문에, 흰색 부분이 꽤 두꺼워 보일 수 있는데, 만약 1000x1000과 같은 고해상도의 이미지를 사용한다면, 이미지의 vertical edge가 더 잘 감지될 것이다.

 

More Edge Detection

이번에는 positive edgenegative edge의 차이점과 다른 유형의 edge detector를 살펴보도록 하자.

방금 전 위에서 봤던 예시인데, input 이미지가 왼쪽은 밝고 오른쪽은 어두운 이미지이다. 이러한 Edge를 positive edge라고 한다. 그리고 3x3 filter를 conv 연산을 통해서 이미지 가운데에 vertical edge를 감지하도록 했다.

만약 input 이미지의 색상이 뒤집어져서, 왼쪽이 어둡고 오른쪽이 밝게 된다면 어떻게 될까? 즉, negative edge인 이미지를 의미한다.

전환되는 명암이 반대가 되기 때문에, 위와 같이 conv 연산 결과값이 -30으로 나타나게 된다. 이것은 edge가 어두운 색에서 밝은 색으로 변환한 것을 감지했다는 의미이고, 만약 positive나 negative를 신경쓰지 않는다면, output matrix에 절대값을 얻어서 사용하면 된다.

지금까지 vertical edge detection을 살펴보았는데, horizontal edge detection은 아래의 filter를 사용해서 감지할 수 있다.

그래서 위와 같은 6x6 이미지가 조금 복잡한 예시이긴 하지만, 이 input 이미지를 horizontal edge filter와 conv연산을 하게 되면, 오른쪽 4x4 output matrix를 얻을 수 있다. 초록색 박스의 경우에는 10 -> 0으로 변화하는 positive edge의 결과이며, 보라색 박스의 경우는 0 -> 10으로 변화하는 negative edge의 결과이다. 여기서 노란색 박스의 10을 살펴보면, 왼쪽은 positive edge를 감지하고 있고, 오른쪽은 negative edge를 감지하고 있는 것을 볼 수 있다. 따라서 두 edge 감지가 섞여서 중간값을 나타내고 있는것이다. 6x6 이미지는 매우 작기 때문에 체감이 되지 않겠지만, 1000x1000 정도의 이미지라고 한다면, 10이나 -10과 같은 전환영역은 보이지 않게 된다.

지금까지 vertical, horizontal edge detection filter를 살펴봤는데, 이는 우리가 선택할 수 있는 filter들 중에 일부이다.

이렇게 우리가 9개의 숫자를 선택할 수 있는데, 딥러닝에서는 직접 선택할 필요가 없으며, 학습을 통해서 이 값들을 얻게 된다. 즉, 3x3 filter의 경우에는 9개의 학습할 parameter를 갖게 되는 것이다.

그렇기 때문에, 어느 방향의 edge detection이든지 데이터로부터 학습할 수 있다. (이것은 low-level의 feature가 된다)

따라서, CNN에서의 장점은 어떤 특정한 filter를 선택하는 것이 아니라, 학습을 통해서 최적의 filter(일종의 weight)를 얻게 되는 것이다.

 

Padding

6x6 이미지에 3x3 filter로 conv연산을 했을 때, output matrix가 4x4의 크기를 갖는 것을 보았다. 4x4 matrix가 되는 이유는 3x3 filter가 input 이미지에 놓일 수 있는 공간이 4x4이기 때문이다.

따라서, (n x n) image * (f x f) filter를 연산하면 (n - f + 1) x (n - f + 1)의 output을 얻을 수 있다.

이 부분에서 2가지 단점이 존재한다.

1. convolution 연산을 수행할 때마다 이미지가 작아진다. 계속해서 작아진다면, 몇 번의 conv연산 밖에 할 수 없게 된다.

2. 코너나 모서리에 존재하는 픽셀은 많이 사용되지 않는다. -> 코너나 모서리에 존재하는 픽셀의 정보를 버리는 것과 같다.

이렇게 이미지가 conv연산을 할 때마다 줄어든다면, 만약 100개의 deep layer를 가진 network가 있을 때 100 layer 이후에는 너무나 작은 이미지만 남게 되고, 또한 가장자리의 정보들을 버리게 된다.

이 문제점을 해결하기 위해서 우리는 경계에 이미지를 채워서(padding을 추가해서), conv연산을 이미지 전체에 적용하면 된다.

위와 같이, 원래 6x6 이미지에 padding을 추가해서 8x8이미지로 만들고 3x3 filter를 통해서 conv연산을 수행하면, output matrix는 입력 이미지와 동일한 6x6 크기의 matrix를 얻을 수 있게 되며, 원본 이미지의 크기를 보존하게 된다.

padding의 정도를 p라고 한다면, (기본 p = 0; no padding) 아래와 같은 공식으로 크기가 결정된다.

(n + 2p, n + 2p) image * (f, f) filter = (n + 2p - f + 1, n + 2p - f + 1) output

물론 p=2, 2개의 pixel을 추가해도 된다.

padding의 존재에 따라서 두 가지 옵션의 convolution이 있는데, 각각 Valid Convolution, Same Convolution이라고 부른다.

Valid Convolution은 기본적으로 padding없이 conv연산하는 것을 의미한다.

Same Convolution은 padding을 추가해서 input size가 output size와 동일하도록 conv연산하는 것을 의미한다.

Same Convolution에 대해서 조금 더 살펴보면, input image가 (n, n), filter가 (f, f), 그리고 padding을 p만큼 적용한다면, output matrix는 (n+2p-f+1, n+2p-f+1)이 된다. 우리는 이 size가 input과 동일하도록 만들기 위해서 방정식으로 정리하면, 결국 p = \frac{f - 1}{2}p=2f−1​로 나타낼 수 있다.

전형적으로 f는 거의 홀수이며, 만약 짝수라면, 비대칭 padding을 해야한다.(f를 홀수로 지정해서 중앙 포지션을 갖도록 하는 것이 computer vision에서 좋은 편이다) f가 홀수인 것이 항상 좋다는 이유는 될 수 없지만, 많은 논문에서 3x3 filter가 흔하며, 5x5, 7x7, 1x1의 filter도 존재하며, 만약 f가 짝수더라도 좋은 성능을 낼 수도 있다.

 

Strided Convolutions

Strided Convolution은 CNN에서 사용되는 기본적인 building block 중의 하나이다. 7x7 이미지를 3x3 filter와 conv연산을 수행하는데, stride = 2로 설정한다고 하면 다음과 같은 연산된다.

첫 번째 element는 이전과 동일하게 진행하지만, 2번째 element는 원본 이미지에서 2칸 이동해서 element-wise 곱을 수행하게 된다.

그 결과, 우리는 7x7 image와 3x3 filter를 conv연산을 통해서 3x3 output matrix를 얻게 된다. input과 output 크기는 다음 공식에 따라서 결정된다. (padding p, stride s가 있을 때)

⌊z⌋=floor(z)를 의미하며, 만약 정수가 아니라면 소수점은 버리게 된다. 즉, 위에서 파란색 박스가 이미지 내에 완전히 포함될 경우에만 유효하다는 것을 의미한다.

여기서는 p = 0이고, s = 2 이기 때문에, 공식을 적용하면 다음과 같이 된다.

Convolutions Over Volumne

지금까지 2-dim에서의 convolution 연산을 살펴보았고, 이제는 3-dim 이상의 volume에서 어떻게 conv연산을 수행하는지 살펴보자.

우선 RGB channel을 가지고 있는 이미지를 convolution 연산을 수행한다면, 연산에 사용되는 filter의 channel은 input 이미지의 channel과 동일해야 한다. 이렇게 연산을 하게 되면, ouput은 4x4가 되는데, 이것은 4x4x1이라는 것을 명심해야한다. 어떻게 연산되는지 자세하게 살펴보자.

일반적인 conv연산과 거의 동일하며, 차이점은 input과 filter를 각각의 채널에서 요소간의 곱을 수행한다. 그러면 각 채널마다 9개의 결과값이 나오고, 총 27개의 결과값이 나오게 된다. 그리고 이 결과값들을 모두 더해주면, 최종 output이 되는 것이다. 나머지 element들도 기존과 동일한 방법으로 구하고, 채널끼리 conv 연산을 수행해서 모두 더해주면 된다.

그리고, 만약 R Channel에서만 Edge를 감지하고 싶다면, R channel만 채워고, 나머지 channel은 전부 0으로 채우면 된다.

이렇게 하면, R Channel에서만 Vertical Edge 감지하는 filter가 된다.

또는, vertical edge의 색상을 신경쓰지 않는다면, 3가지 channel에 모두 동일하게 vertical edge detector로 만들 수 있으며, 이렇게 만든다면 어느 색상의 모서리도 감지할 수 있는 filter가 된다.

이렇게 파라미터를 다르게 선택함으로써, 3x3x3 filter로부터 다른 feature detector를 얻을 수 있다.

위 예시는 6x6x3 input image를 3x3x3 filter로 conv연산을 수행하면 4x4, 즉, 하나의 필터를 사용해서 결과는 2-dim으로 나타나는 것을 보여주고 있다. 만약 우리가 동시에 여러 filter를 사용하고 싶다면 어떻게 해야 할까?

만약 동시에 2가지 filter를 사용하기 원한다면, 위와 같이 각각의 filter(여기서는 vertical edge와 horizontal edge detector)에 대해서 conv연산을 수행하고, 결과 matrix를 쌓으면 된다. 따라서, 결과는 4x4x2의 matrix가 된다.

요약하자면, 다음과 같이 나타낼 수 있다.

여기서 nc는 input 이미지의 channel을 의미하고, nc′​는 filter의 수를 의미한다.

이렇게 filter의 수를 추가함으로써 다른 feature들을 동시에 감지할 수 있도록 해준다.

여기서 input의 마지막 dimension을 channel의 수라고 언급했는데, 종종 다른 문헌에서는 volume의 'depth'라고 부르기도 한다. channel과 depth, 모두 문헌들에서 흔하게 사용되는 표현이지만, Neural network의 depth를 말할 때도 동일하게 depth를 사용하므로 혼동이 될 수도 있어서, 강의에서는 세 번째 dimension을 channel이라는 용어로 지칭한다.

 

One Layer of a Convolutional Network

이제 CNN에서 하나의 layer를 어떻게 구성하는지 살펴보도록 하자.

이전 강의까지 우리는 input 이미지를 filter를 통해 conv연산을 수행했는데, 연산을 수행하고 bias를 추가한 후에 non-linear(ReLU)를 적용한다. 이 과정이 하나의 CNN layer가 된다.

우리가 잘 아는 공식으로 나타낸다면, 다음과 같이 나타낼 수 있을 것이다.

a[0]은 input x이고, filter들이 w[1]와 같은 역할을 하게 된다.

이 예제에서는 2개의 filter를 사용했기 때문에, output이 4x4x2로 나타나고, 만약 10개의 filter를 사용했다면, 4x4x10의 결과를 얻을 수 있다.

예제를 같이 풀어보면서 한 layer에서 파라미터의 개수가 어떻게 되는지 한번 살펴보도록 하자.

만약 CNN Layer에서 3x3x3의 filter 10개를 사용한다면, 이 layer에서 파라미터의 개수는 어떻게 될까?

하나의 filter를 먼저 살펴보면, 각 filter는 3x3x3=27 parameters와 1개의 bias가 존재하며, 따라서 하나의 filter에는 28개의 parameter가 존재한다.

따라서, 총 280개의 파라미터가 존재하게 된다.

여기서 CNN의 장점이 나타나는데, input 이미지의 크기가 아무리 크다고 하더라도 파라미터의 수는 280개로 항상 고정되어 있다. 따라서, 매우 큰 이미지가 있더라도 overfitting하지 않도록 할 수 있게 된다.

Notation 정리

- if layer l is a convolution layer

기본적인 notation은 위와 같고, 이제 input/output, filter의 크기가 어떻게 표시되는지 살펴보자.

m개의 example이 있다면, activation, weight, bias는 다음과 같이 나타낼 수 있다.

 

Simple Convolutional Network Example

 

Pooling layer 

일반적으로 합성곱 층(합성곱 연산 + 활성화 함수) 다음에는 풀링 층을 추가하는 것이 일반적입니다. 풀링 층에서는 특성 맵을 다운샘플링하여 특성 맵의 크기를 줄이는 풀링 연산이 이루어집니다. 풀링 연산에는 일반적으로 최대 풀링(max pooling)과 평균 풀링(average pooling)이 사용됩니다. 우선 최대 풀링을 통해서 풀링 연산을 이해해봅시다.

풀링 연산에서도 합성곱 연산과 마찬가지로 커널(=필터)과 스트라이드의 개념을 가집니다. 위의 그림은 스트라이드가 2일 때, 2 x 2 크기 커널로 맥스 풀링 연산을 했을 때 특성맵이 절반의 크기로 다운샘플링되는 것을 보여줍니다. 맥스 풀링은 커널과 겹치는 영역 안에서 최대값을 추출하는 방식으로 다운샘플링합니다.

다른 풀링 기법인 평균 풀링은 최대값을 추출하는 것이 아니라 평균값을 추출하는 연산이 됩니다. 풀링 연산은 커널과 스트라이드 개념이 존재한다는 점에서 합성곱 연산과 유사하지만, 합성곱 연산과의 차이점은 학습해야 할 가중치가 없으며 연산 후에 채널 수가 변하지 않는다는 점입니다.

pooling의 목적

 

1. input size를 줄임(Down Sampling).
: 텐서의 크기를 줄이는 역할을 한다.

2. overfitting을 조절
: input size가 줄어드는 것은 그만큼 쓸데없는 parameter의 수가 줄어드는 것이라고 생각할 수 있다. 훈련데이터에만 높은 성능을 보이는 과적합(overfitting)을 줄일 수 있다.

3. 특징을 잘 뽑아냄.
: pooling을 했을 때, 특정한 모양을 더 잘 인식할 수 있음.

4. 지역적 이동에 노이즈를 줌으로써 일반화 성능을 올려준다. maxpooling의 경우 주어진 픽셀중 큰것만 뽑기때문에 모양이 조금 달라지는 특성을 가지고 있다.

 

CNN example

Fully Connected Layer

CNN에서는 필터를 이용한 Convolution연산을 반복적으로 진행하면서 이미지의 특징을 검출하기 때문에 생각보다 구조가 간단합니다. 다음의 세 가지 layer를 기억하시면 됩니다.

1. Convolution layer : 특징 추출(feature extraction)

2. Pooling layer : 특징 추출(feature extraction)

3. Fully-connected layer : 분류(classificaiton)

Fully-Connected layer는 CNN 마지막에서 분류(Classification)를 결정하는 단계입니다.

1. flatten : 각 레이어를 1차원 벡터로 변환

2. fully-conneced layer : 1차원 벡터로 변환된 레이어를 하나의 벡터로 연결 (각 층의 노드들은 하나로 연결)

마지막으로 Softmax 함수를 이용해 가장 확률이 높은 class를 output으로 분류합니다.

+ Recent posts