반응형

이글은 www.analyticsvidhya.com의 내용임. (링크)

A Comprehensive Guide to Attention Mechanism in Deep Learning for Everyone

Overview

  • 어텐션 메커니즘은 딥러닝 알고리즘을 사용하는 방법을 바꾸었다.
  • NLP(Natural Language Processing)과 심지어 컴퓨터 비젼 같은 분야도 어텐션 메커니즘에 의해 혁신되었다.
  • 이 글에서는 딥러닝에서 어텐션 알고리즘이 어떻게 동작하는지와 파이썬으로 구현하는 방법을 알아본다.

Introduction

“Every once in a while, a revolutionary product comes along that changes everything.(가끔씩, 모든것을 바꾸는 혁신적인 제품이 생긴다.)” – Steve Jobs

    어텐션 메커니즘은 지난 10년간 딥러닝 연구분야에서 가치있는 혁신중 하나이다. 이는 Transformer architecturedhk Google’s BERT를 포함하여 NLP 분야에서 최근 많은 혁신을 낳았다.

    이 글에서는 몇가지 어텐션 메커니즘에 대한 기초와 동작 방법 그리고 기본 가정과 직관에 대해 알아본다.


Table of Contents

  1. What is Attention?
    1. How Attention Mechanism was Introduced in Deep Learning
    2. Understanding the Attention Mechanism
  2. Implementing a Simple Attention Model in Python using Keras
  3. Global vs. Local Attention
  4. Transformers – Attention is all you Need
  5. Attention in Computer Vision

What is Attention

    심리학에서 어텐션은 선택적으로 하나 또는 몇가지에 집중하지만 나머지는 무시하는 인지 과정이다.

신경망은 단순화된 방법으로 인간의 뇌를 모방하기 위한 노력으로 간주된다. 어텐션 메커니즘 또한 심층신경망에서 다른 것은 무시하면서 관련있는 것을 선택적으로 집중하는 동일한 행동을 구현하기 위한 시도이다.

    이 의미가 무엇인지 알아보자. 초등학교때의 사진 묶음을 보고 있다고 가정하면, 보통 몇줄에 걸쳐 앉아있는 아이들의 그룹이 있고 선생님은 그 사이 어디엔가 앉아 있을 것이다. 이제 누군가가 "몇명이나 있을까?"라고 묻는다면, 어떻게 대답할까?

    단순하게 머릿수를 센다. 사진에 다른 어떤 것도 고려할 필요가 없다. 이제 누군가가 "사진에서 선생님은 누구야?"라는 다른 질문을 한다면, 뇌는 정확하게 무엇을 할지 알고 간단하게 사진에서 어른의 특징을 찾는다. 다른 남은 특징은 무시된다. 이것이 우리의 뇌가 구현에서 매우 능숙한 '어텐션(attention)'이다.

How Attention Mechanism was Introduced in Deep Learning

    NLP(Natural Language Processing)분야에서 인코더-엔코더 기반 neural machine translation system 전반에 대한 개선으로 어텐션 메커니즘이 나타났다. 이후 이 메커니즘 또는 이것의 변형은 컴퓨터 비젼, speeching processing등을 포함한 다른 응용프로그램 분야에서 사용된다.

     Bahdanau et al proposed the first Attention model in 2015이전에는 neural machine 번역은 인코더-디코더 RNNs/LSTMs기반이었다. 인코더와 디코더 모두 LSTM/RNN 유닛의 스택(stack)이고 이는 다음 두단계로 동작한다.

  1. 인코더 LSTM은 전체 입력 문장을 처리하고 이를 컨텍스트 벡터(context vector)로 인코딩하기 위해 사용된다. 이는 LSTM/RNN의 최종 숨은 상태(hidden state)이다. 이는 입력 문장에 대한 좋은 요약이 될 것으로 예상된다. 인코더의 모든 중간 상태는 무시되고 최종 상태는 디코더의 초기 숨은 상태가 되어야 한다.
  2. LSTM 또는 RNN 디코더는 차례로 문장에서 단어를 만든다.

    간단하게 RNNs/LSTMs 두개가 있다. 인코더로 부르는 하나는 입력 문장을 읽고 이를 요약하기 전에 이해하려고 노력한다. 인코더는 이 요약(컨텍스트 벡터)를 입력 문장을 번역하는 디코더에 전달한다.

    이 방법의 주요 문제점은 분명하다. 만약 인코더가 나쁜 요약을 만들면, 번역 또한 나쁠것이다. 그리고 정말로 인코더가 더 긴 문장을 이해하려고 할때 나쁜 요약을 생성하는 것이 관찰되었다. 이를 long-range dependency problem of RNN/LSTMs라고 한다.

    RNNs은 기울기 vanishing/exploding 문제로 더 긴 문장과 시퀀스를 기억할 수 없고 방근 본 부분만을 기억할 수 있다. 인코더-디코더 네트워크를 제시한 Cho et al (2014)조차도 인코더-디코더 네트워크의 성능은 입력 문장의 길이가 증가하는 만큼 빠르게 저하된다는 것을 보였다.

    비록 LSTM이 RNN보다 긴 범위 의존(long-range dependency)을 갭쳐한다할지라도 특정 경우에서 잊어버리는(forget) 경향이 있다. 다른 문제는 문장을 번역하는 동안 다른 단어와 비교해 몇몇 입력 단어에 좀 더 중요성을 줄 방법이 없다는 것이다.

    이제 문장에서 다음 단어를 예측하고 그것의 문맥(context)는 몇단어 뒤에 있다고 해보자. 여기서 예제는 “Despite originally being from Uttar Pradesh, as he was brought up in Bengal, he is more comfortable in Bengali”를 사용한다. 문장의 그룹에서 만약 "Bangali"단어를 예측해야 한다면, "brought up""Bengal" 이 두 단어는 예측하는 동안 좀 더 가중치가 주어져야 한다. 그리고 비록 Uttar Pardesh"가 다른 상태(state)의 이름일지라도 무시되어야 한다.

    그러면, context vector를 생성하는 동안 온전한 입력 문장에서 관련된 정보를 모두 유지할 수 있는 방법은 없을까?

Bahdanau 등(2015)은 단지 context vector에서 모든 입력 단어가 고려되어지는 것 뿐만 아니라 관련된 중요도 또한 각각에 주어지는 것을 제안하는 간단하면서도 세련된 아이디어를 제안한다.

    따라서 제안된 모델이 문장을 생성하는 언제든지 사용가능한 가장 관련있는 정보가 있는 인코더 hidden state에서 위치 셋(set of position)을 검색한다. 이 아이디어를 'Attention'이라고 부른다.

Understanding the Attention Mechanism


    위 그림은 Bahdanau’s paper에서의 Attention model이다. 여기서 사용된 양방향(bidirectional) LSTM은 각 입력 문장에 대한 시퀀스 어노테이션($h_1, h_2, ..., h_Tx$)를 생성한다. 작업에서 사용된 모든 벡터 $h_1, h_2, ..., etc, ...$는 기본적으로 인코더에서 정방향과 역방향에 대한 hidden state의 결합이다.


    간단하게 하면, 모든 벡터 $h_1, h_2, ..., h_Tx$는 입력 문장에서 단어의 수 Tx를 나타낸다. 간단한 인코더와 디코더 모델에서, 단지 인코더 LSTM의 마지만 상태가 context vector로 사용되었다.(이 경우, $h_Tx$)

하지만 Bahdanau 등은 context vector를 생성하는 동안 (hidden state로 나타나게 되는) 입력에서 모든 단어에 대해 임베딩에 강조(emphasis)하였다. 그들은 간단하게 hidden state의 가중치합을 갖는 것으로 이를 수행했다.

    이제, 질문은 어떻게 가중치가 계산되었는가이다. 가중치는 또한 전방향 신경망에 의해 학습되어지고 관련 수식은 다음과 같다.

    출력 단어 $y_i$에 대한 context vector $c_i$는 어노테이션의 가중치가 적용된 합을 사용하여 생성된다.


    가중치 $a_ij$는 아래 수식과 같이 softmax 함수로 계산된다.



    $e_ij$는 입력 j와 출력 i간 정렬을 캡쳐하는 함수 a로 셜명되는 전방향 신경망의 출력점수이다.

    기본적으로 만약 인코더가 각각 d차원을 갖는 어노테이션의 Tx 수(hidden state vectors)를 생성한다면, 전방향 네트워크의 입력 차원은 (Tx, 2d)이다.(디코더의 이전 상태 또한 d차원이고 이들 두 벡터는 연결된다고 가정한다.) 이러한 입렵은 (2d, 1)의 매트릭스(물론 편향이 더해진다.) Wa와 (Tx, 1) 차원을 갖는 $e_ij$ 점수를 얻기위해 곱한다.

    이 $e_ij$ 점수의 맨위에서 tan hyperbolic 함수가 적용되고 출력 j에 대한 정규화된 정렬 점수(normalized alignment score)를 얻기 위해 softmax를 적용한다.

$E = I[Tx \times 2d] \times Wa[2d \times 1] + B[Tx \times 1]$

$\alpha = softmax(tanh(E))$

$C = IT \times \alpha$

    $\alpha$는 (Tx, 1)차원 벡터이고 이것의 요소(elements)는 입력 문장에서 각각 단어에 일치하는 가중치이다.

    $\alpha$[0.2, 0.3, 0.3, 0.2]이고 입력 문장이 "I am doing it"라고 해보자. 여기서 이것에 일치하는 컨텍스트 벡터는 아래와 같다.

$C = 0.2 \times I"I" + 0.3 \times I"am" + 0.3 \times I"doing" + 0.2 \times I"it"$ [$I_x$는 단어 X에 일치하는 hidden state이다.]


Implementing a Simple Attention Model in Python using Keras

    이제 자주 인용되는 어텐션 매커니즘이 무엇인지에 대해 알았다. 무엇을 배우고 실제 설정에서 이를 적용해보자.

    여기서는 어떻게 간단한 어텐션 모델이 케라스로 구현될 수 있는지 알아본다. 이 데모의 목적은 어떻게 간단한 어텐션 레이어가 파이썬으로 구현되어질 수 있는지 보이는 것이다.

    아래 그림과 같이 이 데모는 the University of California Irvine Machine Learning Repository에서 수집한 간단한 sentence-level sentiment analysis dataset에서 실행한다.

    여기서는 단 2개의 감정 범주만 존재한다. - '0'은 부정적 감정, '1'은 긍정적 감정을 나타낸다. 데이터셋은 3개의 파일로 구성된다. 2개 파일은 문장수준의 감정이고 나머지 하나는 단락수준의 감정이다.

    여기서는 문장레벨 데이터 파일(amazon_cells_labelled.txt, yelp_labelled_txt)을 아래와 같이 합쳐서 사용한다.


    케라스의 Tokenizer() 클래스를 사용하여 모델에 맞추는 사전작업을 수행한다.


t=Tokenizer()
t.fit_on_texts(corpus)
text_matrix=t.texts_to_sequences(corpus)

    text_to_sequence() 메서드는 corpus를 시퀀스로 변환한다. 즉, 각 문장은 하나의 벡터가 된다. 벡터의 요소(element)는 어휘목록(vocabulary)에서 유일한 각 단어에 일치하는 유일한 정수이다.


len_mat=[]
for i in range(len(text_matrix)):
    len_mat.append(len(text_matrix[i]))

    문장이 다른 길이를 갖기 때문에 문장에 일치하는 벡터의 최대길이를 알아야 한다. 0을 채움으로써(zero padding) 최대 길이를 맞출 수 있다. 여기서는 'post padding' 기술을 사용했다. 즉, 벡터의 끝에 0이 채워진다.


from keras.preprocessing.sequence import pad_sequences
text_pad = pad_sequences(text_matrix, maxlen=32, padding='post')

    다음으로 기본적인 LSTM 모델을 정의한다.


inputs1=Input(shape=(features,))
x1=Embedding(input_dim=vocab_length+1,output_dim=32,\
             input_length=features,embeddings_regularizer=keras.regularizers.l2(.001))(inputs1)
x1=LSTM(100,dropout=0.3,recurrent_dropout=0.2)(x1)
outputs1=Dense(1,activation='sigmoid')(x1)
model1=Model(inputs1,outputs1)

    여기서는 Embedding layer 다음에 LSTM을 사용한다. 임베딩 레이어는 32차원 벡터를 가지고 (32, 32)차원 행렬(matrix)를 출력한다. 즉, 임베딩 레이어는 각 단어와 일치하는 32차원 벡터를 생성하며 모델 훈련동안 훈련된다.

    그리고 100개의 뉴런을 가진 LSTM레이어를 추가한다. 여기서는 간단한 인코더-디코더 모델이기 때문에, 인코더 LSTM의 각 hidden state를 사용하지 않고 단지 인코더 LSTM의 최종 hidden state만을 사용한다. 이는 케라스 LSTM 함수에서 'return_sequence'=False를 설정하는 것으로 할 수 있다.

    하지만, 케라시으에서 이것의 기본값은 False이므로 필요한 추가 작업은 없다.

    출력은 이제 100차원 벡터가 된다. 즉, LSTM의 hidden state가 100차원이고 이것이 전방향 또는 'sigmoid' 활성화를 가진 Dense layer로 전달된다. 모델은 binary cross-entroy를 사용하는 Adam 옵티마이저로 훈련된다. 아래와 같은 구조의 모델로 10 epoch동안 훈련한다.


model1.summary()


model1.fit(x=train_x,y=train_y,batch_size=100,epochs=10,verbose=1,shuffle=True,validation_split=0.2)

    기본 LSTM기반 모델을 사용하여 검증 정확도가 77%까지 달성했다.

    케라스로 Bahdanau Attention layer를 구현하여 LSTM 레이어에 추가하지 않는다. 여기서는 케라스의 기본 Layer 클래스를 사용하고 Layer클레스를 상속받아 Attention이라고 이름 붙힌 클래스를 정의한다. 케라스 custom layer 생성(generation) 규칙에 따라 build(), call(), compute_output_shape(), get_config()인 4개의 함수를 정의해야 한다.

    build()내부에서 가중치과 편차를 정의한다. 즉, WaB를 정의한다. 만약 이전 LSTM 레이어의 출력 모양이 (None, 32, 100)이면 출력 가중치는 (100,1)이고 편차는 (100,1)차원이 되어야 한다.


ef build(self,input_shape):
        self.W=self.add_weight(name="att_weight",shape=(input_shape[-1],1),initializer="normal")
        self.b=self.add_weight(name="att_bias",shape=(input_shape[1],1),initializer="zeros")        
        super(attention, self).build(input_shape)

    call()내부에서 어텐션의 주요 로직을 작성한다. 여기서는 간단하게 MLP(Multi-Layer Perceptron)을 생성한다. 따라서 가중치(weight)와 입력(input)의 점곱(내적, dot product)를 취하고 편향(bias)을 더한다. 그리고 'tanh'을 적용하고 softmax 레이어를 적용한다. Softmax는 정렬 점수(alignment score)를 제공한다. 이것의 차원은 LSTM의 숨겨진 상태의 수(number of hidden states)이다. 즉, 이번 경우에는 32이다. 숨겨진 상태와 함께 취하는 것은 컨텍스트 벡터를 구하게 된다.


def call(self,x):
        et=K.squeeze(K.tanh(K.dot(x,self.W)+self.b),axis=-1)
        at=K.softmax(et)
        at=K.expand_dims(at,axis=-1)
        output=x*at
        return K.sum(output,axis=1)

    위의 함수는 컨텍스트 벡터를 반환한다. 다음 코드는 완전한 custom Attention 코드이다.


from keras.layers import Layer
import keras.backend as K

class attention(Layer):
    def __init__(self,**kwargs):
        super(attention,self).__init__(**kwargs)

    def build(self,input_shape):
        self.W=self.add_weight(name="att_weight",shape=(input_shape[-1],1),initializer="normal")
        self.b=self.add_weight(name="att_bias",shape=(input_shape[1],1),initializer="zeros")        
        super(attention, self).build(input_shape)

    def call(self,x):
        et=K.squeeze(K.tanh(K.dot(x,self.W)+self.b),axis=-1)
        at=K.softmax(et)
        at=K.expand_dims(at,axis=-1)
        output=x*at
        return K.sum(output,axis=1)

    def compute_output_shape(self,input_shape):
        return (input_shape[0],input_shape[-1])

    def get_config(self):
        return super(attention,self).get_config()

    get_config() 메서드는 입력 모양과 모델에 대한 다른 정보를 수집한다.

    이제 custom Attention layer에 이전에 정의한 모델을 추가해 보자. Custom Attention layer를 제외하고 모든 다른 레이어와 레이어의 파라미터는 동일하게 유지된다. 여기서 LSTM이 모든 숨겨진 상태를 출력하도록 LSTM 레이어에서 return_sequence=True로 설정해야 한다.


inputs=Input((features,))
x=Embedding(input_dim=vocab_length+1,output_dim=32,input_length=features,\
            embeddings_regularizer=keras.regularizers.l2(.001))(inputs)
att_in=LSTM(no_of_neurons,return_sequences=True,dropout=0.3,recurrent_dropout=0.2)(x)
att_out=attention()(att_in)
outputs=Dense(1,activation='sigmoid',trainable=True)(att_out)
model=Model(inputs,outputs)
model.summary()


model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['acc'])
model.fit(x=train_x,y=train_y,batch_size=100,epochs=10,verbose=1,shuffle=True,validation_split=0.2)

    이전 모델과 비교해 실제 개선이 있다. 검증 정확도가 custom Attention layer 추가 후, 81.25%까지 올랐다. 추가적인 사전처리와 파라미터 그리드 서치(grid search)로 좀 더 개선할 수 있다.

    다른 연구자들은 점수 계산에 다른 기술을 시도해 보았다. 어떻게 점수 그리고 컨텍스트 벡ㅌ터가 계산되어지는가에 따른 어텐션 모델의 변종이 있다. 물론 다른 변종도 존재한다.


Global vs. Local Attention

    지금까지, 모든 입력이 약간 중요성을 갖게되는 가장 기본적인 어텐션 매커니즘을 알아보았다. 이제 좀더 깊이 알아보자

    "global" Attention 용어는 모든 입력에 중요성이 주어지기 때문에 적절하다. 원래 Global Attention은 앞에서 살펴본 어텐션의 개념과 약간 미묘한 차이가 있다.

    그 차이는 글로벌 어텐션이 "가변 길이"(variable-length) 컨텍스트 벡터를 계산하기 위해 인코더와 디코더 LSTM 모두의 숨겨진 상태를 고려하는 반면, Bahdanau 등은 컨텍스트 벡터를 계산하기 위해 단방향(unidirectional) 디코더 LSTM의 이전 숨겨진 상태와 인코더 LSTM의 모든 숨겨진 상태를 사용한다.

인코더-디코더 구조에서 점수(score)는 보통 인코더와 디코더의 숨겨진 상태의 함수이다. 어떠한 함수라도 출력 단어에 관한 입력 단어의 관련된중요성을 캡쳐하는한 유효하다.

    "Global" Attention 레이어가 적용되었을 때 너무 많은 계산이 초래된다. 이는 모든 숨겨진 상태가 계산, 행렬(matrix)로 연결 그리고 전방향 연결의 최종 레이어를 얻기 위해 올바른 가중치 행렬과 곱해져야만하기 때문이다.

    따라서 입력 크기가 증가하면 행렬크기 또한 증가한다. 간단하게 전방향 연결에서 노드의 수가 증가하면 사실상 계산이 증가한다.

    어떤 방법으로 이를 줄일 수 있을까? 그 답은 Local Attention이다.

    직관적으로 어떤 주어진 정보로부터 무엇인가 추정하려고 할 때, 단지 가장 관련있는 입력을 취하는 것으로 더욱 더 탐색 영역을 지능적으로 줄이려는 경향을 보인다.

    전역(Global)과 지역(Local) 어텐션의 아이디어는 컴퓨터 비전 작업 분야에서 주로 사용되는 Soft and Hard Attention의 개념에서 영감을 받았다.

Soft Attention은 모든 이미지 패치(patch)에 약간의 가중치가 주어지는 전역 어텐션이다. 하지만, Hard Attention은 한번에 단지 하나의 이미지 patch만 고려된다.

    하지만 지역 어텐션은 이미지 캡션 작업(image captioning task)에서 사용되는 hard attention작업과 동일하지 않다. 반대로, 두가지 개념을 섞었다. 여기서 모든 인코딩된 입력을 고려하는 대신 단지 부분이 컨텍스트 벡터 생성을 위해 고려된다. 이는 단지 soft Attention에서 초래되는 비싼 계산을 피할 뿐아니라 hard Attention보다 훈련하기도 쉬워진다.

    애초에 어떻게 이것을 달성할 수 있을까? 여기서 모델은 입력 단어의 임베딩의 시퀀스에서 위치 pt를 예측하려고 한다. 위치 pt 주변에서 모델은 크기의 윈도우(window of size) 말하자면 2D를 고려한다. 그러므로 컨텍스트 벡터는 위치 [pt - D, pt + D]에서 가중치가 적용된 입력의 평균으로써 생성된다. 여기서 D는 경험적으로 선택된다.

    게다가, 두가지 형태의 정렬(type of alignment)가 있을 수 있다.

  1. 단조로운 정렬(monotonic alignment), 여기서 pt는 시간 t에서 오로지 t의 주변(neighborhood)에서의 정보만이 중요하다고 가정하면서 t로 설정된다.
  2. 예측적인 정렬(predictive alignment), 여기서 모델 자신은 아래와 같이 정렬 위치를 예측한다.
     
     
    여기서 '$V_p$'와 '$W_p$'는 훈련동안 학습되는 모델 파라미터이고 '$S$'는 소스 문장 길이이다. 명확하게 pt ε [0,S]이다.

    아래 그림은 전역과 지역 어텐션 매커니즘간 차이를 보여준다. 전역 어탠션은 모든 숨은 상태(파랑)을 고려하는 반면, 지역 어텐션은 단지 하위 집합만을 고려한다.




Transformers - Attention is All You Need

    Vaswani et al“Attention is All You Need” 논문은 지금까지 어텐션에 가장 중요한 기여를 한 논문중 하나이다. 그들은 key, query, values를 기반으로 어텐션의 매우 일반적이고 넓은 정의를 함으로써 어텐션을 재정의하였다. 그들은 multi-headed Attention이라 불리는 다른 개념을 참조했다. 이를 개략적으로 살펴보자.

    우선 "self-Attention"이 무엇인지 정의해 보자. Cheng 등은 “Long Short-Term Memory-Networks for Machine Reading” 논문에서 self-Attention을 단일 시퀀스 또는 좀 더 생생한 표현(representation)을 얻기 위한 문장의 다른 위치를 관련시키는 것에 대한 매커니즘으로써 정의했다.

    머신 리더(machine reader)는 자동적으로 주어진 텍스트를 이해할 수 있는 알고리즘이다. 아래 그림은 논문에서 인용한 것이다. 붉은 단어는 현재 인스턴스에서 읽히거나 처리되어지고 파란 단어는 기억된다. 다른 음영은 메모리 활성화 정도를 나타낸다.

    단어별로 문장을 읽거나 처리할 때, 이전에 본 단어 또한 강조되는 부분은 음영으로부터 추론된다. 그리고 이것이 정확히 머신 리더에서 self-Attention이 하는 일이다.


    앞에서 문장내 단어의 어텐션을 계산하기 위해 스코어 계산 메커니즘은 이전에 본 단어의 숨겨진 상태 표현으로 내적(dot product) 또는 단어의 다른 기능을 사용한다. 이 논문에서는 기본적으로 동일하지만 좀더 일반적인 개념이 제안되었다.

    "chasing" 단어에 대한 어텐션을 계산한다고 해보자. 메커니즘은 "The", "FBI", "is" 같은 이전에 본 각 단어의 임베딩으로 "chasing"의 임베딩의 내적을 구한다.

    이제 일반화된 정의에 따라, 단어의 각 임베딩은 일치하는 Key, Query, Value 3개의 다른 벡터를 가져야 한다. 행렬곱을 사용하여 이들 벡터를 쉽게 얻을 수 있다.

    입력 임베딩에 관한 목표(target) 단어의 어텐션을 계산하는 것이 필요한 언제라도 목표 단어의 Query와 일치하는 점수를 계산하기 위한 입력의 Key를 사용해야 한다. 그러면 이러한 일치하는 점수는 요약동안 Value 벡터의 가중치로써 동작한다.

    그러면 key, Query, Value 벡터가 무엇일까? 기본적으로 다른 하위공간(subspace)에서 임베팅 벡터의 추상개념(abstraction)이다. 다르게 말해보면, 쿼리가 발생하면 쿼리는 입력벡터의 키에 도달하고 키는 읽혀진 메모리 위치와 비교될 수 있게 된다. 그리고 값은 메모리 위치로부터 읽허진 값이다.

    만약 임베딩의 차원이 (D, 1)이고 (D/3, 1) 차원의 Key 벡터를 원한다면, (D/3, D) 차원의 행렬 Wk로 임베딩을 곱해야 한다. 그러면 키 벡터는 $K = Wk \times E$가 된다. 간단하게, QueryValue 벡터에 대한 식은 $Q = Wq \times E$, $V = Wv \times E$가 될 것이다. (E는 단어의 임베팅 벡터이다.)

    "chasing" 단어에 대한 어덴션을 계산하기 위해 "chasing"의 임베딩의 query벡터 내적을 이전 단어 즉, "The", "FBI", "is" 단어와 일치하는 키 벡터 각각의 key 벡터로 가지고와야 한다. 그러면 이들 값은 D (임베딩 차원)로 나누어지고 softmax 연산을 한다. 각각 연산은 아래와 같다.

  • softmax(Q"chasing", K"The" / D)
  • softmax(Q"chasing", K"FBI" / D)
  • softmax(Q"chasing", K"is" / D)

    기본적으로 이것은 목표 단어의 query 벡터와 입력 입베딩의 key 벡터의 함수 f(Qtarget, Kinput)이다. 반드시 QK의 내적일 필요는 없다. 누구나 자신이 선택한 함수를 선택할 수 있다.

    다음으로 얻어진 벡터가 [0.2, 0.5, 0.3]이라고 해보자. 이 값들은 어텐션의 계산에 대해 정렬 점수(alignment score)이다. 이 정렬 점수는 입력 임베딩 각각의 value 벡터와 곱해지고 이 가중치가 적용된 value 벡터는 context 벡터를 얻기위해 더해진다.

$C"chasing" = 0.2 \times V"the" + 0.5 \times V"FBI" + 0.3 \times V"is"$

    실제로 모든 임베딩 입력 베터는 단일 행렬 X로 결합된다. 이 행렬은 각각 K, Q, V 행렬을 얻기 위해 보통 가중치 행렬 Wk, Wq, Wv와 곱해진다. 이제 함축된 수식은 다음과 같아진다.

$Z = Softmax(Q \times \frac{KT}{D})V$

    그러므로, 컨텍스트 벡터는 Key, Query 그리고 Value의 함수이다. F(K, Q, v)

    Bahdanau 어텐션 또는 어텐션에 관련된 모든 이전 작업은 여기서 설명된 어텐션 메터니즘의 특별한 경우이다. 핵심적인 특성/키 강조는 단일 임베딩 벡타가 동시에 Key, Query, Value 벡터로써 작업에 사용되는 것이다.

    Multi-headed Attention에서 행렬 X는 각각 다른 K, Q, V 행렬을 얻기 위해 다른 Wk, Wq, Wv 행렬로 곱해지고 결구 다른 Z 행렬로 끝난다. 즉, 각각의 입력 단어의 임베딩은 다른 "표현 하위공간(representation subspace)"으로 투영된다.

    "chasing"과 일치하는 3-headed self Attention에서 "Attention Heads"로 불리우는 3개의 다른 Z 행렬이 있을 것이다. 이들 어텐션 헤드는 연결되고 모든 어텐션 헤드로부터 정보를 캡쳐할 하나의 어텐션 헤드를 얻기위해 하나의 가중치 행렬과 곱해진다.

    아래 그림은 multi-head Attention을 나타낸다. 여러개의 어텐션 헤드가 다른 V, K, Q 벡터로부터 생기고 이어지는 것을 볼 수 있다.


    실제 트랜스포머 구조는 좀 더 복잡해진다. 참고


    위 이미지가 트랜스포머 구조이다. 'positional encoding'이라 불리는 무엇인가가 사용되고 인코더와 디코더 모두에 입력의 임베딩이 더해진것을 볼 수 있다.

    지금까지 설명한 모델은 입력 단어의 순서를 설명할 방법이 없고 위치 인코딩을 통해 이를 캡쳐하려고 한다. 이 메커니즘은 각 입력 임베딩에 벡터를 더한다 그리고 모든 벡터는 각 단어의 위치 또는 입력에서 다른 단어간 거리를 알아낸는데 도움이 되는 패턴을 따른다.

    그림에서 본 것과 같이 positional encoding + input embedding 레이어 위에 2개의 하위레이어가 있다.

  1. 첫번째 하위레이어에는 multi-head self-attention 레이어가 있다. 위치 인코딩의 출력으로부터 multi-head self-attention의 출력으로 추가적인 잔차 연결(residual connection)이 존재한다. 그것들 위 정규화 레이어가 적용되었다. 레이어 정규화(layer normalization, Hinton, 2016)는 정규화 통계를 계산하기 위해 데이터의 미니배치 전체를 고려하는 대신 네트워크의 동일한 레이어에서 모든 숨은 유닛이 계산에 고려되는 배치 정규화와 유사하다. 이는 훈련 샘플의 미니배치 전반에 걸친 어떤 뉴런으로 합산된 입력에 대한 통계를 추정하는 문제점을 극복한다. 따라서 RNN/LSTM에서 사용하기 편리하다.
  2. 두번째 하위레이어에서는 multi-head attention 대신 (보이는 것과 같이) feedforward layer가 있고 모든 다른 연결은 동일하다.

    디코더 측면에서, 위에서 설명된 2개의 레이어외에 인코더 스택의 위에서 multi-head attention을 적용한 다른 레이어가 있다. 그러면, 하위 레이어 다음에 하나의 선형과 하나의 softmax레이어로 디코더로부터 출력확률을 얻을 수 있다.


Attention Mechanism in Computer Vision

    어텐션 메커니즘이 NLP에서 어디에 적용될 수 있는지 직관적으로 이해할 수 있다. 이를 넘어 Computer Vision의 맥락에서 이야기해보자. 여기서 몇가지 중요 아이디어를 참고하면 논문을 통해 더 깊이 알 수 있을 것이다.

Image Captioning-Show, [Attend and Tell (Xu et al, 2015):]https://arxiv.org/abs/1502.03044)

    이미지 캡셔닝에서 합성곱 신경망은 이미지로부터 어노테이션 벡터로 알려진 특성 벡터를 추출하기 위해 사용되었다. 이는 D차원 특성 벡터 L개를 생성한다. 이들 각각은 이미지의 부분에 일치하는 표현이다.

    이 작업에서 특성은 추출된 특성 벡터와 이미지의 위치간 관련성이 측정되어질 수 있도록 CNN 모델의 하위(lower) 합성곱 레이어로부터 추출되어진다. 이것의 위에서 어테션 메커니즘은 이미지에 일치하는 캡션을 생성하기 위해 다른 것과 비교해 이미지의 일부 위치에 선택적으로 좀더 중요성을 주기위해 적용된다.

    Bahdanau 어텐션의 약간 수정된 버전이 여기서 사용된다. 어노테이션 벡터(더 쉽게 설명된 숨겨진 상태와 유사한)의 가중치가 적용된 합 대신 함수는 어노테이션 벡터와 정렬 벡터 셋 모두를 가져와 간단하게 내적을 생성하는 대신 컨텍스트 백터를 출력도록 설계되었다.


Image Generation - DRAW – Deep Recurrent Attentive Writer

    구글 딥마인드에 의한 이 작업이 비록 직접적으로 어텐션과 연관되지 않더라도 이 메커니즘은 기발하게 예술가가 그림을 그리는 방법을 묘사하기 위해 사용되었다. 이는 이미지의 부분을 순차적으로 그려 완성한다.

    많은 흥미로운 작업에 이 메커니즘이 홀로 또는 다른 알고리즘과 조합되어 사용되었는지에 대한 아이디어를 얻기 위해 개략적으로 논문을 살펴보자

    이 작업의 주요 아이디어는 이미지 생성을 위해 변형 자동인코더를 사용하는 것이다. 간단한 오토인코더와는 다르게 변형 오토인코더는 직접적으로 데이터의 잠재 표현을 생성하지 않는다. 대신, 다른 편균과 표준편차를 가진 다수의 가우시안 분포(N개의 가우시안 분포라 하자)를 생성한다.

    N개의 가우시안 분포로부터 N개의 요소 잠재 벡터(element latent vector)가 샘플링된다. 그리고 이 샘플은 이미지를 출력하기 위해 디코더로 전달된다. 어덴션 기반 LSTM이 변형 오토인코더 프레임워크의 인코더와 디코더 모두에 대해 사용되었다는 것에 주목하자.

    이것의 주요 직관은 반복적으로 이미지를 생성하는 것이다. 매 단계에서 인코더는 하나의 새로운 잠재 벡터를 디코더에 전달하고 디코더는 누적 방식으로 생성된 이미지를 개선한다. 즉, 어떤 단계에서 생성된 이미지는 다음 단계에서 포함된다. 이는 단계별로 이미지를 그리는 작가의 행동을 묘사한는 것과 같다.

    하지만, 작가는 한번에 전체 그림을 작업하지 않는다. 부분으로 작업한다. 만약 작가가 초상화를 그린다면 순식간에 귀, 눈 또는 얼굴의 다른 부분을 함께 그리지 않는다. 작가는 눈을 그리는 것을 마치고 다른 곳을 그린다.

만약 간단한 LSTM을 사용한다면, 특정 단계에서 이미지의 특정 부분에 집중할 수 없을 것이다. 여기가 어텐션이 관련된 방법이다.

    LSTM의 인코더와 디코더 모두에서 어텐션 레이어("Attention gate"로 이름붙여진)가 사용된다. 이미지를 인코딩 또는 "읽는"동안 이미지의 단지 한 부분이 각 단계에서 집중된다. 유사하게 "쓰는" 동안 단지 이미지의 특정 부분이 그 단계에서 생성된다.

    아래 이미지는 참조한 논문으로부터 가져온 것으로 어떻게 DRAW가 단계별 처리로 MNIST 이미지를 생성하는지를 보여준다.




좀 더 관련 자료를 찾아 공부해 봐야 겠다. 아직은 잘 모르겠다.

반응형

+ Recent posts