슬기로운 연구생활

Classification - [14] Model 본문

슬기로운 NLP 생활

Classification - [14] Model

vhrehfdl 2020. 12. 9. 19:04

이전 글

[1] 자연어처리란?

[2] Classification Task

[3] POS Tagging

[4] Stemming, Lemmatizing

[5] 형태소 분석기

[6] One-Hot Encoding, Bag Of Word

[7] TF-IDF

[8] Word2vec

[9] Fasttext

[10] Glove

[11] ELMo

[12] GPT

[13] BERT

 

들어가며

이전에는 BoW부터 BERT까지 자연어처리의 핵심인 Word Representation에 대해서 알아보았습니다.

자연어 처리 흐름은 데이터 불러오기 > 데이터 전처리 > 문장 벡터 변환 > 모델 생성 > 평가 순으로 진행됩니다.

이번 글에서는 Word Representation된 벡터를 활용해 모델에 입력한 후 학습하는 모델 생성 부분에 대해 살펴보겠습니다.

 

Word Representation

문장을 벡터로 변환하면 1차원 혹은 2차원의 행렬로 변경 됩니다.

 

  • BoW와 TF-IDF는 1차원
  • Word2vec, Fasttext, Glove는 2차원
  • ELMo, GPT, BERT는 1차원
    (BERT 같은 경우에는 2차원이지만 여러 토큰 중 [CLS] 토큰 값만 가져오기 때문에 1차원이라고 표현했습니다.)

단어 벡터가 생성되면 해당 벡터가 어떤 속성인지 아는 것이 필요합니다.

예를들면, Word2vec, Fasttext, Glove와 같은 2차원 행렬은 각 행이 단어의 속성을 나타내는 벡터 입니다.

 

모델은 통계기반 머신러닝 부터 딥러닝까지 다양한 방법을 사용할 수 있습니다.

통계기반 방법에는 Naive Bayes, SVM, XGBoost 등 방법이 있습니다.

딥러닝 방법에는 FCNN, CNN, LSTM, GRU등 알고리즘을 적용할 수 있습니다.

오늘은 자연어처리에 대표적으로 사용되는 TextCNN에 대해서 알아보겠습니다.

 

TextCNN

TextCNN은 Yoon Kim 박사가 “Convolutional Neural Networks for Sentence Classification” 논문에서 제안한 구조입니다.

CNN을 이해하고 있다는 것을 가정하고 그림과 함께 TextCNN을 살펴보겠습니다.

가장 좌측의 2차원 행렬은 (7x5) 형태이며 문장을 행렬로 변환한 것입니다. 

2차원 행렬에 2,3,4 사이즈인 convolution mask를 각각 2개씩 적용합니다. 

위의 하이퍼 파라미터는 사용자가 원하는대로 변경할 수 있습니다.

 

다만, convolution mask의 열 개수는 2차원 행렬의 열 개수만큼 되야됩니다.

한 단어가 1차원 벡터로 표현되어 있기 때문에 해당 벡터를 전부 포함해 연산 될 수 있는 convolution mask의 형태가 되야합니다.

이러한 형태를 1D CNN이라 합니다.

위에서 convolution mask가 (4x5), (3,5), (2x5)로 되어 있는 것은 2차원 행렬이 5이기 때문입니다.

 

2차원 벡터에 convolution mask를 적용하면 문장의 핵심정보가 담긴 (1x4), (1x5), (1x6) 형태가 됩니다.

그 후, Max pooling을 적용해 해당 벡터에서 최대값을 추출한 후 concatenate 합니다.

마지막으로 (1x6) 형태를 만들어 FCNN을 적용해 이진 분류를 합니다.

여기까지가 위 그림의 해석입니다.

 

TextCNN은 1D CNN을 사용한다는 것이 특징입니다.

 

코드

def TextCNN(sequence_len, embedding_matrix, embedding_dim, filter_sizes, flag, data_type, category_num=None):
    # Input Layer
    input_layer = Input(shape=(sequence_len,))

    # Embedding Layer
    if flag == "self_training":
        embedding_layer = Embedding(embedding_matrix, embedding_dim)(input_layer)
    elif flag == "pre_training":
        embedding_layer = Embedding(*embedding_matrix.shape, weights=[embedding_matrix], trainable=False)(input_layer)

    # Hideen Layer
    pooled_outputs = []
    for filter_size in filter_sizes:
        x = Conv1D(embedding_dim, filter_size, activation='relu')(embedding_layer)
        x = MaxPool1D(pool_size=2)(x)
        pooled_outputs.append(x)

    merged = concatenate(pooled_outputs, axis=1)
    dense_layer = Flatten()(merged)

    # Output Layer
    if data_type == "binary":
        output_layer = Dense(1, activation='sigmoid')(dense_layer)
    elif data_type == "multi":
        output_layer = Dense(category_num, activation='softmax')(dense_layer)

    model = Model(inputs=input_layer, outputs=output_layer)

    return model

input layer는 값을 입력받는 부분이고 바로 embedding layer로 연결됩니다.

embedding layer를 거치면 (토큰의 개수 x 차원의 수)로 문장이 변환됩니다.

for문 부분이 convolution filter 부분이고 max pooling을 거쳐 pooled output에 저장됩니다.

그리고 concatenate되어 flatten으로 1차원 형태로 변형시킵니다.

마지막으로 output layer를 거쳐 결과가 나옵니다.

 

관련 코드는 아래 github에 있습니다.

https://github.com/vhrehfdl/cookbook-keras/blob/master/models/text_cnn.py

 

GitHub - vhrehfdl/cookbook-keras

Contribute to vhrehfdl/cookbook-keras development by creating an account on GitHub.

github.com

 

마무리

이번 글에서는 문장 벡터에 적용하는 모델에 대해 살펴보았습니다.

다음 글에서는 마지막 단계인 평가 부분에 대해 살펴보겠습니다.

'슬기로운 NLP 생활' 카테고리의 다른 글

Classification - [8.1] Word2vec Negative Sampling  (0) 2021.10.21
Classification - [15] Evaluation  (0) 2020.12.09
Classification - [13] BERT  (0) 2020.10.07
Classification - [12] GPT  (0) 2020.10.07
Classification - [11] ELMo  (0) 2020.09.24
Comments