let us not love with words or tongue but actions and truth.

IT/자연어분석

LSTM and Sequential Labeling

sarah0518 2022. 5. 25. 12:13

General Problems Solved with LSTM

- Sequence labeling

  POS tagging, NER

- Language modeling

  : 다음에 들어올 단어 예측

- Sequence classification

  : text가 들어왔을 때, spam메일인지 아닌지 분류하는 것

 

** NER은 조화평균으로 성능을 평가함

 

 

Sequence to Sequence transduction

encoder / decoder framework - 기계번역등에 활용

BERT는 encoder로, GPT3와 같은것은 decoder로 만든 것임 

 

 

LSTM의 활용 사례

 

RNN의 단점: vanishing gradient problem 

LSTM의 단점: 계산량이 많음

→ GRU(Gated Recurren Unit)로 계산을 간소화함

 

 

Bi-LSTM을 활용한 NER실습에서 참고할 내용들 정리

[preprocess]

 def get_train_iterator(self, train_data):
        train_iterator = torchtext.legacy.data.BucketIterator(
            train_data,
            device=self.device,
            batch_size=self.args.train_batch_size,
            sort_key=lambda x: len(x.text),
            repeat=False,
            train=True,
            sort=True)
        return list(train_iterator)

위의 코드에서는 각각 비슷한 길이의 데이터 example을 묶어주는 iterator를 정의한 것임

 

 

아래는 pretrained 된 word embedding(Glove)를 가져와서 embedding vector를 초기화 하는 것임

def load_pretrained_word_embed(self, data):
        print('We are using pre-trained word embeddings.')
        self.LABEL.build_vocab(data)
        vectors = torchtext.vocab.Vectors(name='/content/data/glove.6B.50d.txt')
        
        return self.TEXT.build_vocab(data, vectors = vectors)

>> 나중에 모델에서는 nn.Embedding.from_pretrained(embeddings=text_filed.vocab.vectors)로 불러오면 됨

 

 

[model]

class LSTMCRFNER(torch.nn.Module):
    def __init__(self, text_field, label_field, emb_dim, hidden_size, emb_tuning=False):
        super(LSTMCRFNER, self).__init__()
        voc_size = len(text_field.vocab)
        self.n_labels = len(label_field.vocab)

        # Input(Embedding) layer initialized from Glove embedding
        #    - Defined embedding matrix
        #    - Initialized weight from processed vocab vectors
        #    <variable_name:self.word_embedding , dim: (vocab_size, embedding_dim)>
        self.word_embedding = nn.Embedding.from_pretrained(embeddings=text_field.vocab.vectors)
        # LSTM layer
        # <variable_name:self.lstm>
        self.lstm = nn.LSTM(input_size=emb_dim, hidden_size = hidden_size, bidirectional=True)
        # Output(Fully connected) layer
        self.linear = nn.Linear(2*hidden_size, self.n_labels)

        #CRF layer
        self.crf = CRF(self.n_labels)

        # pad information
        self.pad_word_id = text_field.vocab.stoi[text_field.pad_token]
        self.pad_label_id = label_field.vocab.stoi[label_field.pad_token]

# output layer단에서 보면

마지막에 foward된 LSTM과 backward된 LSTM을 concat해서 사용하므로

nn.Linear의 hidden_size를 2배해준 것임

 

# CRF layer에서는 

torch crf를 사용하는데, 거기서는 label의 개수만 넣어주면 됨

 

 

CRF 사용이유:

LSTM 역할: 입력 단어 사이의 관계 및 정보를 반영

CRF 역할: 예측 되는 label 사이의 관계 및 정보를 반영

위 그림에서 '레알', '마드리드', 'FC'라는 단어가 들어왔을 때 

이 레이블간의 관계(빨강색 선)를 잘 나타내기 위한것이 CRF임

(TAG의 순차적 정보를 잘 나타낼 수 있음)

→ LSTM에 CRF를 추가하는 것이 더 성능이 좋음

 

 

'IT > 자연어분석' 카테고리의 다른 글

BERT2  (0) 2022.05.26
BERT1  (0) 2022.05.26
Word Vector and Word embedding  (0) 2022.05.06
[자연어]Statistical Parsing  (0) 2022.04.20
[자연어]Part of Speech Tagging, Sequence Labeling, HMM  (0) 2022.04.08