반응형

Python으로 딥러닝하기|자연어 처리 1. 토크나이징

Python으로 딥러닝하기|자연어 2. 단어 임베딩, Word2Vec

Python으로 딥러닝하기|RNN(Recurrent Neural Networks) Part1. 이론

Python으로 딥러닝하기|LSTM(RNN) Part1&2. 이론 및 실습

 

잠시 미뤄왔던 자연어처리 시리즈를 다시 작성해보고자 합니다... 화이팅!

 


seq2seq paper: Sequence to Sequence Learning with Neural Networks

 

우선 Sequence to Sequence(Seq2Seq) 모델은 RNN의 many-to-many 와 유사한 구조로 시퀀스 형태의 입력값을 넣으면 시퀀스 형태의 출력값을 내놓는 구조입니다. 따라서 번역, 요약, 챗봇 등 다양한 분야에서 활용될 수 있습니다.

 

RNN(LSTM) 모델을 기반으로 Encoder와 Decoder 부분이 나눠져 있습니다. Encoder에서는 입력값의 context vector(=hidden status)를 생성하고 Decoder에서는 해당 vector를 활용해 재귀적으로 출력값을 만들어내는 구조입니다.

그리고 Encoder와 Decoder는 길이가 고정되어있지만, 각각 다른 최대 길이를 가질 수 있고, 데이터의 길이가 적으면 Padding으로 채웁니다.

Seq2Seq: Encoder-Decoder

 

 

RNN의 many-to-many 와 유사한 구조라고 이야기했는데, Decoder에서 다른 부분이 존재합니다.

 

우선 Seq2Seq 구조의 경우 <EOS> 혹은 <START>, <END> 라는 토큰을 활용하여 시작과 끝맺음을 할 수 있도록 데이터를 구성하여 훈련할 수 있습니다. (참고: 최대 길이보다 길이가 짧은 경우 <END> 토큰 이후에 Padding으로 채우는 방식)

 

또한 "재귀적"으로 훈련된다는 점도 다릅니다. Decoder의 현재 cell(층)의 input은 이전 cell의 output을 활용하는 것으로 구성되어 있습니다. (RNN은 context vector 하나만 사용)

여기서 만약 Decoder가 시작부터 틀린다면 학습이 잘 되지 않을 수 있습니다. 따라서 Decoder의 현재 cell의 input 값을 실제(정답) 데이터로 사용하는 Teacher Forcing이라는 새로운 학습 방법이 제안됩니다.

 


Transformer paper: Attention Is All You Need

 

이후에 Transformer를 설명할 것인데, 이를 이해하기 위해서는 논문의 제목에서도 알 수 있듯, Attention이라는 개념을 먼저 알아야합니다.

 

Attention 매커니즘은 고정된 크기의 context vector를 사용하는 Seq2Seq를 개선하는 방법으로 아래의 그림을 참고해서 보면 Attention의 뜻을 짐작해 볼 수 있습니다.

1. Encoder에서 모든 cell(층)의 hidden status와 Decoder의 현재 cell의 hidden satus와 dot product를 하여 attention scores를 생성

2. softmax에 통과시켜 가중합을 한 attention value를 구하고 Decoder에서 현재 cell의 output 값과 concatenate하여 다음 값을 예측

이러한 과정을 통해 Encoder 부분의 어떤 hidden status에 더 "집중"하면 좋은지를 학습할 수 있습니다.

출처: https://wikidocs.net/22893

 

Attention 식은 매우 간단합니다. 아래의 식은 Scaled Dot-Product Attention Score입니다.

$\text{attention score}(s_t, h_i) = \frac{s_t^Th_i}{\sqrt{n}}$

$s_t$: Decoder의 현재 hidden status

$h_i$: Encoder의 i번째 hidden status

 


Transformer도 할 내용이 많아서.. 다시 돌아오겠습니다.

 

반응형
반응형

안녕하세요.

 

오늘은 이전 포스팅 RNN 이론에 이어 LSTM 이론 및 실습을 하도록 하겠습니다.

 

실습은 "Tensorflow 2.0 beta" 버전으로 RNN을 구축하겠습니다!

 


 

먼저,

 

LSTM(Long Short-term Memory)에 대해 알아보겠습니다.

 

 

Part 1. 이론

 

LSTM은 RNN의 Gradient Vanishing 문제를 해결하기 위해 도입되었습니다.

 

LSTM 구조의 기본 원리는

신경망이 장기적인 관계를 학습을 위하여

중요한 정보를 확실하게 전송할 목적으로 설계되었다는 것입니다.

 

[RNN 과 LSTM 비교]

그림 출처: https://ratsgo.github.io

 

 

1. 유지 게이트(keep/forget gate): 얼마나 많은 양의 이전 메모리를 유지할지 결정

 

이전 시간 단계에서 메모리 상태 텐서는 정보가 풍부하지만,

 

일부 정보는 오래된 것일 수 있다.

 

 

2. 쓰기 게이트(write/input gate): 어떤 정보를 메모리 상태에 기록해야 할 것인지 결정

 

1) 어떤 정보를 쓰려는지 알아 낸다.

 

2) 계산된 텐서가 새로운 상태를 포함하길 원하는지, 이전의 값을 전달하길 원하는지 파악한다.

 

 

3. 출력 게이트(output gate): 시간 단계마다 LSTM 유닛 출력

 

1) tahnh 층은 중간 텐서를 생성한다.

 

2) 시그모이드 층은 현재 입력과 이전 출력을 사용해 비트 텐서 마스크를 생성한다.

 

3) 중간텐서는 최종 출력을 생성하기 위해 비트 텐서와 곱해진다.

 


 

Part2. 실습

 

우선 Tensorflow 2.0 버전을 설치하겠습니다.

 

!pip install -q tensorflow==2.0.0-beta1

!pip install -q tensorflow-gpu==2.0.0-beta1  # gpu 버전

 

 

두 문장이 유산한지(NLP) 예측하는 LSTM 모델을 구현하였습니다.

 

data: 캐글 대회 중 하나인 "Quora Question Pairs"

(단, 데이터 전처리는 다루지 않습니다.)

 

import tensorflow as tf
from sklearn.model_selection import train_test_split # 데이터 셋 분할
import numpy as np
import pandas as pd
import json

train_input, test_input, train_label, test_label = train_test_split(input_data, label_data, test_size=0.2, random_state=2019)

VOCAB_SIZE = input_data.max()+1
WORD_EMBEDDING_DIM = 64
BUFFER_SIZE = 10000
BATCH_SIZE = 16

train_dataset = tf.data.Dataset.from_tensor_slices((train_input, train_label))
test_dataset = tf.data.Dataset.from_tensor_slices((test_input, test_label))

train_dataset = train_dataset.shuffle(BUFFER_SIZE)
train_dataset = train_dataset.batch(BATCH_SIZE)

test_dataset = test_dataset.batch(BATCH_SIZE)

model = tf.keras.Sequential([
    tf.keras.layers.Embedding(VOCAB_SIZE, WORD_EMBEDDING_DIM),    # 자연어 처리 핵심 함수
    tf.keras.layers.Bidirectional(tf.keras.layers.LSTM(64, return_sequences=True)),
    tf.keras.layers.Bidirectional(tf.keras.layers.LSTM(32)),
    tf.keras.layers.Dense(64, activation='relu'),
    tf.keras.layers.Dropout(rate=0.2),
    tf.keras.layers.Dense(1, activation='sigmoid')
])

model.compile(loss='binary_crossentropy',
              optimizer='adam',
              metrics=['accuracy'])
              
# 모델 훈련
history = model.fit(train_dataset,
                    epochs=10,
#                     validation_data=test_dataset
                   )

 

[결과]

(케글에서 제공하는 test 데이터에 대한 결과는 케글에 제출하면 확인 가능합니다.)

 

[train_accuracy]
[train loss]

 

여기에서는 단층의 얕은 모델을 만들어서 유사도를 측정하였습니다.

 

추가로 더 깊은 모델을 만들어서 성능을 높여 보세요~


LSTM 이론 출처: 딥러닝의 정석

반응형
반응형

 

 

 

 

안녕하세요!

 

오늘은 "파이썬으로 딥러닝 하기!" 중 RNN에 대해 알아보도록 하겠습니다~

 

딥러닝 알고리즘 중 CNN은 전 포스팅에서 다뤘습니다.

 

 

먼저,

 

RNN이란 Recurrent Neural Networks로 순환 신경망이라고 합니다.

 

RNN은 시퀀스 데이터, 예를 들어 음성, NLP, 동영상 등의 데이터에서 사용됩니다.

 


 

[기존 DNN과 RNN 비교]

 

 

RNN이 기존 딥러닝 알고리즘과 가장 다른 점은

 

뉴런의 상태를 저장하고 다음 스텝에서 입력으로 사용함으로

 

긴 시퀀스에 대해서도 예측할 수 있다는 것입니다.

 

 

 

<RNN, 순환 신경망 구조>

 

 

 

이미지 출처: 성킴_RNN_YouTube강의

 

 

모든 뉴런은 이전 층의 모든 뉴런에서 나오는 입력 연결과 이어지는 층으로

 

 모든 뉴런을 유도하는 출력 연결 둘 다를 가지고 있습니다.

 

 

하지만 전방향층과 달리 순환층은 순환 연결이 있으며 동일한 층의 뉴런 간에 정보를 전파합니다.

 

 

따라서 순환 신경망에서 뉴런 활성도는 신경망 인스턴스의 누적 상태를 나타냅니다.

 

 

 

 

<RNN 종류>

 

 

이미지 출처: 성킴_RNN_YouTube강의

 

 

RNN은 위와 같이 입력과 출력의 개수에 따라 다양하게 구성할 수 있습니다.

 

 

many-to-one: 마지막 출력 값이 label 값과 같아지는 것이 목표

 

many-to-many: 입력 데이터를 차례대로 입력하면 차례로 출력 데이터 출력

 

 

 

[RNN의 한계]

 

 

RNN의 Gradient Vanishing(기울기 소실) 문제

 

 

과거 여러 단계 입력들에 대해 계산할 때,

 

경사(Gradient)가 빠르게 줄어들어 (즉, 오차가 더 줄어들지 못하고 수렴하는 문제 발생)

 

장기 의존성을 학습하는 모델의 능력이 심각하게 제한됩니다.

 

 

이 문제를 해결하기 위해 LSTM 구조를 도입했습니다.

 

LSTM은 다음 포스팅에서 다루도록 하겠습니다.

 

 

※ 참고: Back-Propagation Through Time (BPTT)

 

 

RNN은 시간에 따라 펼쳐 놓으면 MLP(Multi-Layer Propagation)와 유사하기 때문에

 

Back-Propagation방법으로 Gradient를 계산할 수 있습니다.

 

 


 

오늘은 여기까지!

 

다음 포스팅으로 돌아오겠습니다~

반응형

+ Recent posts