티스토리 뷰

이번 수업 시간에는 CNN에 대한 수업이었는데, 기존에 이미지 인식에서 자주 쓰이던 CNN을 자연어 처리에 쓰게 된 배경과, CNN이 자연어 처리에서 쓰일 때는 어떤 차이가 있는지에 대한 내용이다. 출바알-! 

1. CNN을 쓰는 이유는? 

CNN을 쓰는 이유는 RNN이 가진 한계에서 온다. 우선 RNN 은 어떤 구문에 대해서 구문 별개로 인식을 할 수가 없다. 무슨 말이냐면, RNN 의 hidden state를 보면, 항상 왼쪽에서 오른쪽으로 문맥이 포함되는 구조임을 알 수 있다. 즉, 중간이나 마지막에 오는 단어의 vectcor에는 원하든 원하지 않든, 이전에 나온 단어의 문맥이 포함될 수 밖에 없다 (bi-directional도 마찬가지임). 결국 어떤 단어, 혹은 구문 (phrase) 의 의미가 문장의 앞에 나온 다른 단어 혹은 구문을 배제하고 표현되기가 어렵다는 얘기다. 왜 이것이 문제가 되냐면, 가끔 sentence classification이나 sentiment analysis 같은 경우네는 키가 되는 단어 몇 개로 classification을 하는데, 문장의 끝에 오는 단어는 이미 앞에 나온 너무 많은 단어들에 대한 문맥을 포함하고 있기 때문이다.

 

결론적으로 CNN 을 사용해서 모든 n-gram에 대해서 독립적으로 vector를 만들고자 하는 것이 메인 아이디어다. 

2. CNN 레이어 하나씩 살펴보기! 

그럼 컨볼루션이 뭔지에 대해서 자세히 살펴보자. 우선 컨볼루션은 앞서 말했듯이 이미지 인식에서 자주 사용되는 기법이다. 컨볼루션의 키는 필터에 있다. 원래 이미지에서 사용할 때는, 이 필터로 전체 이미지를 훑어가면서 피쳐맵을 만드는데 목적이 있다.

 

이미지 인식에서는 당연히 input이 픽셀값으로 표현된 이미지 전체이겠지만, NLP에서는 문장 안의 모든 word vector 의 concatenation 이다. 중요한 점은, 열 하나당 한 단어를 표현한다는 점! 즉, 어떤 문장 안에 단어가 7개가 들어있고, 그 word vector 의 차원이 6차원이라면, 해당 문장의 vector 는 7 x 6 이 되겠지 (하지만 실제로 word vector 를 쓸 때는, 그 차원이 이것보다 훨씬 크다). 

 

이미지 인식에서는 n x n 모양의 필터가 이미지 전체를 왼쪽에서 오른쪽으로, 위에서 아래로  훑는다면, 자연어 처리에서 쓰이는 필터는 그냥 아래로만 훑는다 (단어 단위로 훑어야 하고, 각 열이 하나의 단어를 나타내는 벡터이기 때문에 열 단위로 훑어야 한다). CNN 의 마지막에는  softmax 가 있기 때문에 고정된 fixed input dimension이 필요한데, zero pad 를 이용해서 처리한다. 그리고 자연어 처리 CNN 필터의 사이즈는 결국 원하는 n-gram 사이즈에 따라 달려있다. Bi-gram 이라면, 필터의 사이즈는 2 x D (여기서 D는 워드 벡터의 차원 수), tri-gram이면 3 x D ... 가 된다. 서로 다른 사이즈의 필터를 사용해서 모든 문장에서 피쳐를 뽑아낸다. 

 

이렇게 필터를 거치고 나면 1차 피쳐맵이 나올 텐데, 여기서 pooling layer를 사용해서 가장 두드러지는 특징을 지닌 것만을 뽑아낸다. Pooling layer 에서 가장 흔하게 쓰는게 max pooling 인데, 쉽게 말해 가장 큰 값만을 취하는 방식이다. 각 문장은 단어 수 x 워드 벡터 크기의 벡터로 표현된다. 필터를 지나고 나면, 문장 내 모든 n-gram이 하나의 값으로 벡터로 표현이 될 거고, 풀링 레이어를 거쳐서, 이 중 가장 큰 값을 지닌 것만을 뽑아낸다. 결국 하나의 문장마다 단 하나의 n-gram vector 만 최종적응로 뽑히는 거고, 만약 5개의 서로 다른 필터가 이 문장을 훑었다면 최종적으로는 5개의 n-gram features 만 남게 되는거다. 그리고 이 피쳐들을 모두 합쳐서 fully connected layer 를 통과시켜 원하는 label값을 얻는다.

 

여기서 가장 중요한 것은 CNN 와 자연어 처리에 대한 intuition에 있다. 이미 자연어 처리 task를 위해서 CNN을 써봤지만 몰랐던 내용이라 나한테는 충격이었다..! 우선 CNN의 하나의 필터는 하나의 pattern 만을 잡아낸다. 예를 들어서 어떤 필터는 단어의 긍정성에 대해서 잡아낸다고 하면, 그 필터는 그 패턴만을 잡아내는 것이다. 이게 어떤 방식이냐면, 필터가 어떤 n-gram 벡터를 지나갔을 때 큰값이 반환된다는 것은 그 인풋 n-gram이 그 필터를 fire / activate 한다는 뜻이다. 큰 값이 반환 된다는 것 = 두 벡터의 inner product (근데, 필터와 인풋은 inner product가 아니지 않나? -> 확인해볼 것) 의 값이 크다는 뜻이고, 그 의미는 바로 두 벡터의 cosine similarity가 크다는 것을 의미한다. 그리고 풀링 레이어에서는 이 중 최대값 만을 반환함으로써 “이 부분이 중요해” 라고 higher layer에 signal을 보내는 것이다. 최대값이 아닌 나머지 값은 버려지므로 gradient 도 0이 된다. 

 

또 중요한 것은, 하나의 필터는 하나의 패턴만을 잡아낸다고 했고, 우리는 더 많은 패턴, 즉 피쳐를 잡아내고 싶기 때문에 필터를 여러 개를 사용한다. 예를 들어, bi-gram 용 20개, tri-gram용 20개... 이런 식으로 (결국 각 문장마다 최종적으로 40개의 벡터값이 반환되는 거임). 이 때, 어떻게 크기가 같은 필터가 각기 다른 패턴을 잡아내는지가 의문일 수 있는데, 우선 각 필터는 서로 다른 값으로 Initialize 되고, 서로 다른 방향으로 움직이며 learning 하기 때문에 자연스럽게 different values 배운다고 한다. 러닝을 하는 실행하는 사람이 따로 뭘 할필요도 없다고 했음. 

 

3. CNN 성능을 향상시키는 다양한 팁! 

3.1 Multi channel idea 

우선, multi channel idea 는 2개의 word vector를 concatenate 한 것을 인풋으로 사용하되, 하나는 트레이닝 과정에서 gradient 를 통해서 값을 업데이트 하고, 하나는 고정값으로 사요하는 것이다. 왜 그렇게 하냐고? 보통은 이미 방대한 양의 코퍼스로 학습된 word vector 를 초깃값으로 쓴다. 그리고 트레이닝이 지나감에 따라 단어들의 벡터 값이 업데이트 될 텐데, 문제는 업데이트 되는 값이 오직 트레이닝 set에 등장하는 단어뿐이라는 것이다. 결국 트레이닝 set 에 나오지 않은 단어의 벡터 값은 업데이트 되지 않기 때문에 방대한 코퍼스를 통해 학습한 워드 벡터가 가지는 generality 가 없어지는 것이고, 이 말은 즉 트레이닝 set 에서 보지 못한 단어가 test set 에 등장하면 정확도가 굉장히 떨어질 것이라는 것을 의미한다. 그래서 하나는 업데이트 하고, 다른 하나는 고정된 값을 사용하는 것이다. 이 2개의 채널은 맥스 풀링 레이어 전에 하나로 합쳐진다 (정확히 어떻게 합쳐지는지는 모르겠다).

 

3.2 Drop out 

 드랍 아웃은 쉽게 말해서 학습된 weight 의 일부만 계산에 쓰는 것이다. 드랍아웃 비율이 만약에 50% 라고 한다면, 학습된 weight 의 절반만 놔두고, 나머지는 0으로 처리해 계산에 포함되지 않도록 하는 것 (실제로는 1혹은 0 으로 이루어진 벡터를 weight vector 에 곱해서 처리한다. 그러면 이 벡터도 트레이닝으로 배우는 건가..? 아니면 랜덤으로 하는 건가..?) 어쨌든, 트레이닝 중에는 이렇게 계산했지만, 테스트에서는 드랍 아웃을 쓰지 않기 때문에, 결과 값이 더 큰값이 나와 버리기 때문에 (총 합이), 리스케일을 통해서 값을 조절한다. 

 

드랍 아웃을 쓰는 것은 결국 노이즈를 더하는 것과 마찬 가지다. 딥러닝을 노이즈가 있을 대, 과적화 되지 않고 더 잘 배운다고 알려져 있다. 예를 들어 learning 과정에서 특정 tri-gram이 나왔을 때 해당 문장이 positive하다는 것을 배웠다고 할 때, 해당 tri-gram이 꼭 정확하게 나와야지만 그 문장을 positive하다고 배우는 것이 아니라 하나 혹은 2개만 나와도 positive하다는 것을 배우는 것이다.

 

3.3 Hyper parameters 선택하기

보통 하이퍼 파라미터를 선택할 때 (예 - CNN 필터 크기, 각 크기 당 필터 갯수, 드랍 아웃 비율, 활성함수 종류 등), 각 하이퍼 파라미터마다 가능한 옵션들을 모두 조합해서 트레이닝한다 (이상적). 하지만, 필터 갯수만해도 20 개도 될 수 있고, 21 개도 될 수 있고, .. 200 개도 될 수 있는데, 그렇다면 180 개의 옵션을 각 하이퍼 파라미터마다 다 테스트 해야 된다는 건가? 어느 세월에..? 그렇기 때문에, 실제로는 샘플링을 통해서 하이퍼 파라미터 set 를 구한다고 한다, 즉, 필터 갯수를 20, 21, 22, 23.... 199, 200 다 테스트 하는 것이 아니라 25, 50, 75 .. 200 이런 식으로 20~ 200 사이라는 바운더리만 정하고 그 안의 몇 개만 뽑아서 테스트를 한다는 것이다. 

 

여기서 또 한번 내가 그동안 헷갈련던 개념을 집고 넘어가는데 바로 ‌Dev set에 대한 것이다. 보통 하이퍼 파라미터를 선택하기 위해서 Dev set 을 사용한다고 하는데 정확히 보자면 이렇다. 샘플링을 통해서 뽑은 하이퍼 파라미터 중, 하이퍼 파라미터 세트 1을 가지고 모델을 트레이닝 한다고 하자. 이 때, 여러 번의 iteration을 통해서 모델을 트레이닝 하게 될 거다. 트레이닝 중에는 cost 를 통해서 학습이 얼마나 잘 되는지를 평가한다. 그럼 이 파라미터 셋을 가지고 트레이닝한 이 모델의 최종 accuracy는 어떻게 알지? 테스트 할 때 까지 기다려야 됨?? 그게 아니라, Dev set을 이용해서 이 파라미터 셋을 통해 트레이닝한 모델의 성능을 테스트 해보는 것임. 그리고 이 과정을 통해서 training set에서 점수가 차이가 많이 난다면 과적화 된 것이기 때문에 모델 튜닝도 가능하다.

+ 교수님 말로는, 같은 하이퍼 파리미터 셋도 다르게 트레이닝 될수 있기 때문에 같은 하이퍼 마라미터 셋에서 여러 개의 모델을 트레이닝하고, 최종적으로 각 모델마다 테스트 셋으로 평가를 한 다음, 이 점수를 평균 내서 구하기도 한다고 했음 - ensembling - (륙이 했던 방법. 즉, 이미 트레이닝된 모델을 여러 번 테스트 하는 게 아니라, 여러 개의 모델을 트레이닝 하고, 각각 트레이닝 된 모델의 정확도를 평균내서 정하는 거임). 

 

데브 셋으로 평가를 할 때도, 타임 스텝이 지나감에 따라 점수가 다르게 나올 텐데, 보통 최고 높은 점수를 선택해서 dev set 에 대한 점수로 인정하다 (데브 셋도 여러 가지 배치로 해서 그러는 건가? 설마 데브셋도 epoch 여러 번 하는건가?) 

 

그리고 트레이닝 미니배치 수가 클 수록 노이즈가 적을테니 미니 배치수를 늘리면 된다고 생각할 수 있겠지만, 노이즈는 딥러닝에서 오히려 필요한 부분이기 때문에 미니배치수가 너무 크면 안 좋다고 한다. 

 

CNN 의 장점은 일단 빠르다는 것이고, parallel trainig 이 가능하다는 것이다. 300 개의 필터를 300개의 GPU 에 각각 넣어서 계산할 수 기 때문에 빠르고 병렬적인 트레이닝이 가능하다. 

 

 

 

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함