NLP
Transformer
- CNN, RNN 대신 Self-Attention을 사용하는 모델
Transformer는 RNN, LSTM없이 time 시퀀스 역할을 하는 모델입니다. RNN, LSTM 셀을 일체 사용하지 않았으나, 자체만으로 time 시퀀스 역할을 해줄 수 있는 굉장히 novel한 논문입니다.
일반적인 Seq2Seq-Attention 모델에서의 번역 태스크의 문제는 원본 언어(Source Language), 번역된 언어(Target Language)간의 어느정도 대응 여부는 어텐션을 통해 찾을 수 있었으나, 각 자신의 언어만에 대해서는 관계를 나타낼수 없었습니다. 예를 들면
I love tiger but it is scare
와나는 호랑이를 좋아하지만 그것(호랑이)는 무섭다
사이의 관계는 어텐션을 통해 매칭이 가능했지만it
이 무엇을 나타내는지?와 같은 문제는 기존 Encoder-Decoder 기반의 어텐션 메커니즘에서는 찾을 수 없었습니다.
-
순서:
- Seq 처리: '
positional encoding
' (순서정보를 입력하면 저장되고 공식에 맞춰 벡터를 수치화 시키는 곳)
상대적/절대적인 정보를 넣어야 함
- 그걸 (input) encoder의 attention으로 전달
- 2의 결과를 FNN을 전달(단순 linear prejection(차원축소) 위함)
- 3의 결과를 Decoder의 attention으로 전달
- (
fine Tuning
) input Decoder에서 입력한 순서 정보(positional encoding) 출력 - 5의 결과를 attention으로 전달
- 4의 결과와 합침
- FNN으로 전달(linear, softmax 거침)
- 그 결과물을 일부(?) 다시 1로 전달
- Seq 처리: '
attention
: 입력된 값을 가중치로 조정하여 목적에 맞게 바꿔줌self attention
: 입력값인 Q와 transposed K를 내적한 후, Scaled with Softmax 한다. 이는 곧 Self-Attention 시키는 것이고, 이를 통해 attention score 얻을 수 있다.-
Masked
: Self-Attention시 자신의 time step 이후 word는 가려 Self-Attention 되는 것을 막는 역할.''' # make mask like this. 0 1 1 0 0 1 0 0 0 '''
d_model
: 임베딩을 하기 위한 차원으로 보통 512를 사용. embedding vector table.attention value
: 수치화된 table에서 중요한 정보를 골라 가중치를 줄 수 있음
Encoder
-
Encoder
기능 설명
-
추가 설명
positional encoding
:
PE = positional_encoding(50,5) # emb_size = dmodel = 2차원으로 표현
Decoder
설명 | ||
---|---|---|
인코더와 동일하지만, Self-Attention 시, 'Masked'-Multi-Head Attention 을 쓴다는 점이 다르다.* Masked를 쓰는 이유: Self-Attention시 자신의 time step 이후의 word는 가려서 Self-Attention 되는 것을 막는 역할. |
||
노란색 Box에서 왼쪽 2개 화살표가 Encoder의 K,V 오른쪽 화살표가 Self-Attention을 거친 Decoder의 Q |
이렇게 나온 값을 일반적인Teacher Forcing을 통해 학습 |
- 출처 및 참고: platfarm tech team
Inference(추론)
전체 Inference | Encoder Inference |
---|---|
Inference시 Encoder의 들어오는 문장(번역할 문장)은 정확히 알지만, Decoder에 들어오는 문장(번역되어지는 문장)은 알지 못한다. 시작 표시를 나타내는 <S>를 사용해서 Seq2Seq와 동일하게 Inference 한다. |
inference word가 <E> (end point)이면 inference를 멈춘다. |
Chatbot Code
-
(2020-08-14) (data set)를 transformer 모델에 학습한 챗봇 만들기 미니 프로젝트
Created by jynee & molo6379 & hh & Dabi
Zhao HG keras transformer 코드 응용
- 데이터 입력
from keras_transformer import get_model, decode
import pickle
import warnings
warnings.filterwarnings('ignore', 'tensorflow')
# 단어 목록 dict를 읽어온다.
with open('./dataset/6-1.vocabulary.pickle', 'rb') as f:
word2idx, idx2word = pickle.load(f)
# 학습 데이터 : 인코딩, 디코딩 입력, 디코딩 출력을 읽어온다.
with open('./dataset/6-1.train_data.pickle', 'rb') as f:
trainXE, trainXD, trainYD = pickle.load(f)
# 평가 데이터 : 인코딩, 디코딩 입력, 디코딩 출력을 만든다.
with open('./dataset/6-1.eval_data.pickle', 'rb') as f:
testXE, testXD, testYD = pickle.load(f)
- model 빌드
model = get_model(
token_num=max(len(word2idx), len(word2idx)),
embed_dim=32,
encoder_num=2,
decoder_num=2,
head_num=4,
hidden_dim=128,
dropout_rate=0.05,
use_same_embed=False, # Use different embeddings for different languages
)
model.compile('adam', 'sparse_categorical_crossentropy')
- model load or fit(학습)
LOAD_MODEL = True
if LOAD_MODEL:
MODEL_PATH = './dataset/transformer.h5'
model.load_weights(MODEL_PATH)
else:
model.fit(
x=[trainXE, trainXD],
y=trainYD,
epochs=1,
batch_size=32)
model.save_weights(MODEL_PATH)
- predict 함수 정의
def ivec_to_word(q_idx):
decoded = decode(
model,
q_idx,
start_token=word2idx['<START>'],
end_token=word2idx['<END>'],
pad_token=word2idx['<PADDING>'],
)
decoded = ' '.join(map(lambda x: idx2word[x], decoded[1:-1]))
return decoded
- chatbot
MAX_SEQUENCE_LEN = 10
def chatting(n=100):
for i in range(n):
question = input('Q: ')
if question == 'quit':
break
q_idx = []
for x in question.split(' '):
if x in word2idx:
q_idx.append(word2idx[x])
else:
q_idx.append(word2idx['<UNKNOWN>']) # out-of-vocabulary (OOV)
# <PADDING>을 삽입한다.
if len(q_idx) < MAX_SEQUENCE_LEN:
q_idx.extend([word2idx['<PADDING>']] * (MAX_SEQUENCE_LEN - len(q_idx)))
else:
q_idx = q_idx[0:MAX_SEQUENCE_LEN]
answer = ivec_to_word(q_idx)
print('A: ', answer)
chatting(100)
units of words
-
등장 배경:
- FastText를 사용한다면, n-gram character 방식
단점 >
- word2vec의 oov 문제를 해결하지만, collision 문제 발생
- hash 사용한다면, hash-table 크기를 작게 잡으면 collision 발생
참고: DB에서는,
- Collision 문제를 해결하기 위해서 별도의 overflow page를 사용한다
- overflow page가 늘어나면 검색 속도가 떨어진다
-
overflow page가 임계치를 초과하면 hash-table을 늘려서 DB를 재구성
=> "Reorganization" 따라서 기존의 단어들의 위치가 변경된다.
- NLP 분석 시엔 Reorganization하면 단어들의 위치가 변경되므로 다시 학습시켜야 한다. 따라서 근본적인 해결책이 되진 못한다.
- NLP 분석 시엔 Reorganization하면 단어들의 위치가 변경되므로 다시 학습시켜야 한다. 따라서 근본적인 해결책이 되진 못한다.
- FastText를 사용한다면, n-gram character 방식
-
Word Piece(WPM)
,Sentence Piece(SPM)
- NLP에서 Sub-word 구축할 때 사용
- 형태소 분석과 달리 언어의 특성에 구애 받지 않아 아무 언어나(한글/영어 등) 사용이 가능하다.
- 빈도가 높은 문자열들은 하나의
unit
으로 취급하여 사전에 등록해 사용한다. - 'unit': 의미를 가진 문자는 아니고 음절이라기엔 두 음절을 하나로 보니 unit이란 이름을 사용한다.
-
구글은 자신들의 구글 번역기에서 WPM이 어떻게 수행되는지에 대해서 기술했다.
WPM을 수행하기 이전의 문장: Jet makers feud over seat width with big orders at stake WPM을 수행한 결과(wordpieces) : _J et _makers _fe ud _over _seat _width _with _big _orders _at _stake
Jet는 J와 et로 나누어졌으며, feud는 fe와 ud로 나누어진 것을 볼 수 있다. WPM은 입력 문장에서 기존에 존재하던 띄어쓰기는 언더바로 치환하고, 단어는 내부단어(subword)로 통계에 기반하여 띄어쓰기로 분리한다.
기존의 띄어쓰기를 언더바로 치환하는 이유는 차후 다시 문장 복원을 위한 장치이다. WPM의 결과로 나온 문장을 보면, 기존에 없던 띄어쓰기가 추가되어 내부 단어(subwords)들을 구분하는 구분자 역할을 하고 있으므로 본래의 띄어쓰기를 언더바로 치환해놓지 않으면, 기존 문장으로 복원할 수가 없다.
WPM이 수행된 결과로부터 다시 수행 전의 결과로 돌리는 방법은 현재 있는 띄어쓰기를 전부 삭제하여 내부 단어들을 다시 하나의 단어로 연결시키고, 언더바를 다시 띄어쓰기로 바꾸면 된다.
- 출처: 정민수
- pre-trained 된 SKTBrain의 KoBert를 fine tuning으로 사용하면 쉽게 SentencePiece를 만들 수 있다.
- WPM, SPM
- SPM은 GOOGLE이 C++로 만들어서 속도가 빠르다.
-
(단점) 조사도 쪼개서 보기 때문에 챗봇 만들 때 답변으로 잘못된 조사가 붙여 나올 수 있다.
- ex: 번역 api 사용 시 부자연스러운 조사
- 개선 방법: (1) 데이터 양을 늘린다. (2) BERT를 사용한다.
[나는 학교에 간다]
- 단어와 단어를 구분하는 단어의 띄어쓰기에만 언더바 붙이기 "나는_학교에_간다"
- '_학교' → 사전에 등록
- '_나' → 사전에 등록
- '는' → 사전에 등록
- '간다' → 사전에 등록
- ['_학교', '_나', '는', '간다']
- [5, 4, 61,12]
-
BPE
- 데이터 압축기술.
구글의 WPM에는 BPE(Byte Pair Encoding) 알고리즘이 사용되었다.
BPE 알고리즘의 기본 원리는 가장 많이 등장한 문자열에 대하여 병합하는 작업을 반복하는 데, 원하는 단어 집합의 크기. 즉, 단어의 갯수가 될 때까지 이 작업을 반복한다.
- 출처: 정민수
예>
[abcabtabsta]
- 'ab' → 사전에 등록
- 'abc' → 사전에 등록
- 'r' → 사전에 등록
- 't' → 사전에 등록
- 'u' → 사전에 등록
-
참고:
- 아마추어 퀀트, blog.naver.com/chunjein
- platfarm tech team. 2019.05.11. "어텐션 메커니즘과 transfomer(self-attention)". https://medium.com/platfarm/어텐션-메커니즘과-transfomer-self-attention-842498fd3225
- Zhao HG. "keras-bert". https://github.com/CyberZHG/keras-bert
- 정민수. 2019.06.07. "자연어처리(NLP) 5일차 (단어 분리)". https://medium.com/@omicro03/%EC%9E%90%EC%97%B0%EC%96%B4%EC%B2%98%EB%A6%AC-nlp-5%EC%9D%BC%EC%B0%A8-%EB%8B%A8%EC%96%B4-%EB%B6%84%EB%A6%AC-60b59f681eb7. @omicro03