Data/자연어처리

자연어 처리를 위한 피드 포워드 신경망(1)/ 다층 퍼셉트론, 파이토치 구현

빛날희- 2021. 7. 22. 14:40

50

델립라오, 브라이언 맥머핸의 파이토치로 배우는 자연어처리 책을 참고하여 작성하였습니다.

참고 강의1, 참고 강의2


▶ 다층 퍼셉트론이란?

이전 포스팅에 올렸던 퍼셉트론을 여러 층으로 쌓아올린 구조를 말한다. XOR 논리게이트와 같이 하나의 직선으로 데이터 포인트를 나눌 수 없는 경우 여러 개의 퍼셉트론을 사용해 논리게이트를 구현할 수 있었듯이 복잡한 패턴의 데이터를 학습하기 위해선 여러 개의 퍼셉트론을 쌓아 학습하는 과정이 필요하다. 

 

 

 

▶ 다층 퍼셉트론의 구조

파이토치로 배우는 자연어 처리 p111

단층 퍼셉트론이 입력층 하나와 출력층 하나로 구성됐다면 다층퍼셉트론은 입력층과 출력층 사이에 은닉층이 추가된다. 은닉층은 경우에 따라 여러 개의 은닉층이 쌓일 수 도 있다.

 

MLP의 학습과정은 다음과 같다.

 

1) 입력벡터가 들어오면 첫번째 Linear 층에서 활성화 함수를 적용하여 은닉벡터를 출력한다. 

2) 은닉벡터가 두번째 Linear 층의 입력으로 들어간다. 

3) 두번째 Linear층에서 출력벡터를 계산하여 task에 맞는 크기의 벡터를 출력한다. XOR gate를 예시로 들면 출력벡터의 크기는 0 또는 1에 해당할 확률을 하나의 수치로 나타내기 때문에 출력벡터의 크기는 1이다. 다중 분류에서는 출력벡터의 크기가 클래스 개수와 같을 것이다. 

 

MLP의 강점은 이렇게 은닉층을 통해 중간 표현을 학습할 수 있다는 데에서 비롯된다. 

 

 

 

▶ 다층 퍼셉트론 예시- XOR gate

XOR gate를 보며 다층퍼셉트론에 대해 이해해보자. 

지난 포스팅에서 보았듯이 우리는 NAND게이트와 OR게이트를 통해 나온 벡터들을 다시 AND게이트의 입력값으로 넣어 XOR게이트의 출력벡터를 만들 수 있었다. 그리고 각각의 게이트에 적합한 가중치와 편향은 back propagation을 통해 찾을 수 있었다. 

 

XOR게이트는 다층퍼셉트론으로 NAND, OR 게이트는 은닉층이며 해당 게이트에서 나온 핑크 색의 벡터부분이 은닉벡터라고 볼 수 있다. 이 은닉벡터를 출력층인 AND게이트를 거치면 XOR게이트의 출력벡터를 얻을 수 있다. 

 

그런데 NAND gate와 OR gate는 다음과 같이 하나의 게이트로 나타낼 수 있다. 

 

 

즉 첫번째 은닉 게이트에선 나온 K 은닉벡터를 출력 층의 입력으로 넣어 출력벡터를 생성할 수 있다. 

다음 그림은 XOR에 입력으로 들어간 벡터들의 표현을 그림으로 나타낸 것이다. 

파이토치로 배우는 자연어 처리 p 113

1) XOR gate에 들어가는 입력 벡터 표현이다. 

2) 첫번째 은닉 층의 선형 출력이다. 단일 퍼셉트론이라면 이 단계에서 학습이 끝난다.

3) 선형출력에 활성화함수를 적용한 표현이다. 

4) 3번 벡터들을 입력으로 넣어 두번째 층에서 선형출력한 벡터이다. 중간표현의 공간변형을 통해 별과 동그라미를 선형적으로 구분할 수 있도록 포인트를 재조직할 수 있었다. 

 

XOR gate의 벡터들을 분리하기 위해 두개의 직선이 필요하기 때문에 두개의 결정경계를 통해 포인트들이 나눠진다고 생각할 수 있지만, 이는 사실 위와 같이 중간학습을 통해 선형벡터들의 공간을 비틀었기 때문에 하나의 결정 경계가 두개의 결정경계처럼 보이는 것이라고 이해할 수 있다. 

 

 

 

▶ 파이토치 구현

▷ 정방향 계산까지 구현- 코드 출처

파이토치는 모델 정의와 정방향 계산에 맞춰 자동으로 역방향 계산과 그레디언트 업데이트를 수행할 수 있기 때문에 정방향 계산만 구현한다.

 

해당 코드에선 손실함수를 계산하고 역방향계산을 수행하는 코드는 없지만 크로스 엔트로피 손실함수를 사용하기 위해선 softmax활성화 함수는 False로 지정해줘야한다. 

 

만일 선형 층만 쌓게 되면 결국 모든 층이 수학적으로 같아지기 때문에 이 선형관계를 깨기 위해 중간 중간 비선형 함수를 쌓아 모델이 벡터 공간을 비틀 수 있게 해야한다. 해당 코드에선 relu 활성화 함수를 비선형 함수로 사용하였다. 

첫번째 입력벡터의 크기는 3, 은닉벡터의 크기는 100, 출력벡터의 크기는 4로 설정한 모델을 생성한다. 

 

모델을 훈련하지 않았으므로 출력벡터는 랜덤으로 출력되었다. 

 

해당 코드를 통해 형태만 알아보고 가자. 

우선 입력벡터로 2행 3열의 벡터가 첫번째 층에 들어가고 100크기의 은닉층을 통과한 후 출력벡터로 2행 4열의 벡터가 출력된다. 즉 은닉 벡터는 3행 100열의 벡터였을 것이다. 

 

첫번째 y_output은 relu활성화 함수를 적용하기 전인 예측 벡터가 나왔다. 훈련할 때에는 해당 예측벡터에 손실함수를 적용해 학습을 진행하기도 한다.

두번째 y_output이 예측벡터에 softmax 활성화 함수를 적용한 벡터이다. 0에서 1사이의 확률값이 벡터로 출력되었음을 알 수 있다. 

 

 

 

▶ XOR gate구현- 코드 출처

(역방향 계산을 매뉴얼하게 코드로 구현해보고 싶다면 역방향 계산 코드까지 구현한 해당 유튜브 강의를 참고하자. )

이번에는 XOR gate를 파이토치로 구현해보았다. 구조는 위 코드와 동일하지만 이번에는 binary cross entropy손실함수와 옵티마이저까지 구현하여 최종 확률값을 예측해보았다. 

마찬가지로 선형층과 비선형 층을 차례대로 쌓았다. 손실함수와 옵티마이저까지 설정해준다. 

옵티마이저를 0으로 초기화 한후 역방향 계산을 수행한다. 손실함수의 값이 학습을 진행할수록 줄어든다. 

X를 input으로 모델에 넣어 예측된 확률값을 hypothesis에 넣고 이를 라벨값으로 바꾼다. 

모두 정확하게 예측되었음을 알 수 있다.