2019.06.30
출처 : https://wikidocs.net/book/2155
핵심키워드
- Tagging Task
- Bidirectional RNN
태깅 작업(Tagging Task)
여기서는 자연어 처리 분야에서 각 단어가 어떤 유형에 속해있는지를 알아내는 태깅 작업에 대해서 배운다. 이러한 단어 태깅 작업은 대표적으로 크게 두 가지가 있는데 각 단어의 유형이 사람, 장소, 단체 등 어떤 유형인지를 알아내는 개체명 인식(Named Entity Recognition)과 각 단어의 품사가 명사, 동사, 형용사인지를 알아내는 품사 태깅(Part-of_Speech Tagging)이 있다.
이러한 작업은 챗봇, 기계 번역 등과 같은 자연어 처리분야에서 메인 작업에 앞서 전처리 작업으로서 필요한 경우가 많지만, 전처리 작업이라고 쉬운 작업이 아니라 그 자체로도 까다로운 작업이 되어 많은 시간을 필요로 하는 작업이 되기도 한다.
여기서는 케라스(Keras)를 이용해서 인공 신경망을 이용한 개체명 인식기와 품사 태거를 만드는 간단한 미니 프로젝트를 수행해보도록 한다.
케라스를 이용한 태깅 작업 개요(Tagging Task using Keras)
이번 챕터에서는 케라스(Keras)로 인공 신경망을 이용하여 태깅 작업을 하는 모델을 만든다. 개체명 인식기와 품사 태거를 만드는데, 이러한 두 작업의 공통점은 RNN의 다-대-다(Many-to-Many) 작업이면서 또한 앞, 뒤 시점의 입력을 모두 참고하는 양방향 RNN(Bidirectional RNN)을 사용한다는 점이다.
두 개의 실습 챕터를 진행하기 전에 전체적으로 실습이 어떻게 진행되는지 정리해보도록 한다. 텍스트 분류 개요 챕터와 겹치는 부분에 대해서는 요약하여 설명하므로, 이해가 되지 않는 부분이 있다면 해당 챕터를 참고바란다.
1. 훈련 데이터에 대한 이해
태깅 작업은 앞서 배운 텍스트 분류 작업과 동일하게 지도 학습(Supervised Learning)에 속한다. 이 챕터에서는 태깅을 해야하는 단어 데이터를 X, 레이블에 해당되는 태깅 정보 데이터는 y라고 이름을 붙였다. X에 대한 훈련 데이터는 X_train, 테스트 데이터는 X_test라고 명명하고 y에 대한 훈련 데이터는 y_train, 테스트 데이터는 y_test라고 명명한다.
이번 챕터에서 X와 y데이터의 쌍(pair)은 병렬 구조를 가진다는 특징이 있다. X와 y의 각 데이터의 길이는 같다. 예를 들어 품사 태깅 작업을 한다고 가정해본다. 그리고 X_train와 y_train의 데이터 중 4개의 데이터만 확인해본다고 가정한다. 이 때 데이터는 다음과 같은 구조를 가진다.
가령, X_train[3]의 ‘The’와 y_train[3]의 ‘O’는 하나의 쌍(pair)이다. 또한, X-train[3]의 ‘European’과 y_train[3]의 ‘B-ORG’는 쌍의 관계를 가지며, X_train[3]의 ‘Commision’과 y_train[3]의 ‘I-ORG’는 쌍의 관계를 가진다.
이렇게 병렬 관계를 가지는 각 데이터는 정수 인코딩 과정을 거친 후, 모든 데이터의 길이를 동일하게 맞춰주기위한 패딩(Padding) 작업을 거친다.
2. 시퀀스 레이블링(Sequence Labeling)
위와 같이 입력 시퀀스 X = [x1, x2, x3, …, xn]에 대하여 레이블 시퀀스 Y=[y1, y2, y3, …, yn]를 각각 부여하는 작업을 시퀀스 레이블링 작업(Sequence Labeling Task)라고 한다. 태깅 작업은 대표적인 시퀀스 레이블링 작업이다.
3. 양방향 RNN(Bidirectional RNN)
model.add(Bidirectional(LSTM(hidden_size, return_sequences=True)))
이번 챕터에서도 바닐라 RNN이 아니라 성능이 개선된 RNN인 LSTM을 사용한다. 텍스트 분류 챕터에서는 단방향 LSTM을 사용하였지만, 이번 챕터에서는 양방향 LSTM을 사용한다. 이전 시점의 단어 정보 뿐만 아니라, 다음 시점의 단어 정보도 참고하기 위함이다. 양방향은 기존의 단방향 LSTM()을 Bidirectional() 안에 넣으면 된다.
인자 정보는 단방향 LSTM을 사용할 때와 동일하다. 즉, 인자값을 하나 줄 경우에는 이는 hidden_size를 의미하며, 결과적으로 output_dim이 된다.
4. RNN의 다-대-다(Many-to-Many) 문제
RNN의 은닉층은 모든 시점에 대해서 은닉 상태값을 출력할 수 있고, 마지막 시점에 대해서만 은닉 상태값을 출력할 수 있다. 이는 인자로 return_sequence=True를 넣을 것인지, 넣지 않을 것인지로 설정할 수 있는데 태깅 작업의 경우에는 다-대-다(Many-to-Many) 문제로 return_sequence=True를 설정하여 출력층에 모든 은닉 상태값을 보낸다.
이제 RNN이 어떻게 설계되는지 확인해보자. 예를 들어 위에서 설명한 데이터 중 첫번째 데이터에 해당되는 X_train[0]를 가지고 4번의 시점(timesteps)까지 RNN을 진행하였을 때의 그림은 다음과 같다.
하지만 이번 실습에서는 양방향 RNN을 사용할 것이므로 아래의 그림과 같다.