오늘은 img2img 모델인 pix2pix gan 모델 논문에 대해 리뷰해보겠습니다.

 

https://arxiv.org/abs/1611.07004

 

Image-to-Image Translation with Conditional Adversarial Networks

We investigate conditional adversarial networks as a general-purpose solution to image-to-image translation problems. These networks not only learn the mapping from input image to output image, but also learn a loss function to train this mapping. This mak

arxiv.org

 

귀여워


 

1. introduction

- 해당 논문은 외국어를 translating ( 번역 ) 하는 것처럼 RGB 이미지를 image-to-image translation하는 task를 범용적으로 다룰 수 있는 framework를 제안한다.

- CNN과 같은 모델은 이미지 prediction에서 높은 성능을 보이지만, 이를 위해서 학습의 objective 즉 loss를 일일이 task에 맞춰 디자인하는 노력이 필요하다.

- 따라서 GANs을 사용하여, data에 adaptive한 gan loss로,  원래라면 여러 다른 종류의 loss가 필요했을 task들을 loss 디자인의 노력 필요없이 GAN하나로 가능하게 하면서,

이미지가 fake 처럼 보이지 않도록 함(D)과 동시에 loss를 최소화하는 방향(G)으로 이미지를 생성해낸다.

 

--

 

이미지를 내가 원하는 형태의 또 다른 이미지로 변환하는 img2img translation task를 범용적으로 다룰 수 있는 모델이 필요한데, 

 

CNN과 같은 모델은 loss를 최소화하며 학습하는 과정은 자동이지만, 이 목적성인 loss를 디자인하는 것 자체가 어렵다는 문제가 있다.

 

특정 스타일이나 , 원하는 결과물에 맞추어 특수한 loss를 만들어 줘야 하고,

모델의 성능을 좋게 하기 위해 이러한 loss를 하나하나 디자인한다는 것은

결국 img2img translation이라는 task를 범용적으로 CNN이 할 수 없다는 말이다.

 

만약 단순하게 Euclidean distance로 loss를 설계하면, 이미지의 생성 결과가 모델이 그럴듯한 출력의 모든 것을 평균화하여 loss를 최소화해버리는 선택을 해버려 흐려 보이는 이미지가 결론적으로 나타난다는 점에서 저자는 각각 task에 맞춘 loss 디자인이 필요성을 말한다.

 

이를 해결하기 위해 저자는 GAN을 사용해 img2img를 하면

GAN은 loss가 data에 맞게 변화하는 특징을 가지고 있어 task에 loss가 맞춰서 학습을 진행하여

 img2img라는 task를 범용적이게 할 수 있다고 하는 것이다.

 

 

2. Related works

 

1 . Structured losses

img2img 문제는 픽셀 단위의 회귀로 생각할 수 있지만, 픽셀 단위로만 생각하면 전체 구조적인 특성을 읽어버려 실제로는 이상하게 보이는 이미지를 생성해낼 수 있다.

 

2. Conditional GANs

해당 논문에서는 condition 즉 , input img x이 들어가는 gan을 사용한다. 

이게 무슨 말이냐 하면, 원래 본디 GAN의 초기 개념은 G 가 랜덤한 노이즈 z로 부터 점차 진짜같은 이미지를 생성해나가고, D가

이의 진위 판별을 하므로써 점차 두 모델의 성능이 좋아지는 것인데,

우리가 하고자 하는 img2img를 하기 위해서는 input x를 무언가로 변형해 output을 만들어내야 하기에 

 

conditional Gan 즉 input ( condition )이 있는 gan을 쓴다. 아래의 그림을 보면 손쉽게 이해가 가능하다.

 

cGAN

 

3. Method

method는 크게 1. loss 2. U-net generator 3. Patch GAN discriminator로 나눌 수 있다.

 

1. loss 

 

첫번째로 loss를 이해하기 위해 G와 D의 input output을 정확히 이해해야한다.

 

먼저 D는 discriminator로써, 두 개의 input (입력 이미지 x, 추론이미지) 가 들어왓을 때

추론해야하는 이미지가 실제 이미지(B)인지, G가 생성해낸 fake인지 구분해야 한다. (fake B)

 

이에 대한 추론 결과가 0~1 사이의 확률로 나오며, 추론이미지가 진짜라고 판단하면 1에 가까운 확률을 return한다.

 

두번째로, G는 입력 x(condition)과 ramdom한 noise z를 바탕으로 가짜 이미지를 생성해낸다. (fake B) 이게 return값 그 자체다.

 

이를 바탕으로 위의 (1)식을 봐보자.  

D를 우선적으로 보면 앞의 항은 진짜를 D가 판별하는 상황이므로 더 커져야 D의 성능에 좋다, 뒤의 항은 가짜를 D가 판별하는 상황이라서 D의 return값이 작이지면 좋은데 1- []이므로 뒤 항도 커져야 D 성능이 좋은 것이다. 

즉 , D입장에서는 전체 식이 커져야 성능에 좋은 것이고,

 

반대로 G입장에서는 D를 속여야 즉 뒤의 항의 값이 작아져야 G가 잘 하는 것이기에 전체 항이 작아져야 한다.

이러한 내용이 아래 (4)식에 minmax로 나와있다.

 

눈치챘을 수 있지만, 해당 loss는 G , D에 대해 동시에 계산, 업데이트가 쉽지 않다. 어느 한쪽은 고정되어 있어야 계산이 편리하기에 실제 학습에서도 순차적으로 backward를 진행한다.

 

여기서 기댓값으로 감싸져 있는 것은 실제로는 mini-batch의 평균으로 구현한다.

 


 

(4) 뒤 식을 보면 L1 loss가 G에 대해서 추가적으로 달려있는 것을 볼 수 잇다.

해당 항은 G가 실제 gt값에 가까운 이미지를 형성하는데 도움을 주기 위해서 필요한 항이다.

 


recall

 

논문에서는 random한 noise z에 대해서 언급하는데 

z가 없다면 gan이 결정론적인 동일한 output만을 계속하여 만들어서 모델의 품질이 떨어지기에 필요하지만, 

학습 과정에서 저절로 gan이 z를 무시하는 현상이 벌어져,

dropout을 통해 생성하는 결과물이 highly stochastic output을 낼 수 있도록 하려고 하였지만

그마저도 부족하여, 이에 대한 부분은 완전히 해결하지 못하였다고 한다.

 

추론 과정에서도 dropout을 사용하여, img2img 특성에 걸맞게 할 때마다 조금씩 다른 output이 생길 수 있음을 말한다.

 

 

2. u-net (G)

 

 

 

generator의 구조로써 U-net을 사용하였다고 한다.

일반 Encoder - decoder와 달리 U-net은 각 스케일마다 skip-connection을 사용하여 해상도별 정보를 보존한다.

(기존 encoder-decoder는 한번 bottleneck으로 압축되어 복원되기에 정보가 많이 손실된다. U-net은 skip connection으로 이러한 정보를 보내주는 것이다)

 

논문에서는 이를 bottleneck이 same underlying structure를 보존하고, skip connection이 surface appearance를 보존한다고 말한다.

 

3. PatchGAN (D)

기존의 L1/L2 Loss함수가 흐린 이미지를 생성해낸다는 것을 앞서 언급한바 있다.

이러한 L1/L2 Loss 를 통한 이미지 생성은 흐린 이미지를 생성해내지만, low frequency 를 충분히 잘 복원해낸다고 한다.

따라서 low frequency 영역은 L1/L2 loss로 충분하고 문제는 high frequency (선명함)을 보존하는 것인데, 

 

이게 대해서 D가 high-frequency structure만 모델이 만들도록 제한하고, low frequency는 L1/L2가 보장하는 방식으로 선명함을 만들어낸다. 

 

이때, 판별기는 N*N patch에 대해서 각 패치가 진짜인지 확인하는 방식으로 작동해 이를 PatchGan이라고 한다.

 

4.  Optimization and inference

 

- 모델의 backward는 D에 대해서 한번 수행한뒤 , G에 대해서 수행하는 방식을 사용한다.

 

- G loss는 앞서 나온 loss의 뒤 항을 쓰는 게 아니라

를 사용한다. * fake를 진짜라고 믿게 만들어라

( 로그함수는 0에 가까우면 , -oo, 커지면 완만한 커브

초기 G가 생성해내는 값은 누가 봐도 가짜기에 log(1-D(fake))이면 D가 낮은 값을 밷어 log함수의 완만한 배에 올라타 gradient를 얻기 쉽지 않다.

반대로 log(D(fake)) 이면 초기에 비교적 완만하지 않아 gradient로 학습이 되는 것이다.  )

 

- D의 objective를 1/2로 나누어서 G의 속도에 비해 D의 속도를 조절한다. 

* 우리가 학습하는건 결국 G가 잘 만들도록 하는 것이고, 처음부터 가짜를 G는 만들어야 하기에 D를 느리게 하여 페이스를 조절한다! 

 

4. Experiment 

앞서 언급한 loss의 이유를 직관적으로 확인할 수 있다 + D의 high freq 보존

 

추가적으로 아래 fig를 보면 PatchGAN의 Patch size별 양상을 비교하는 것을 볼 수 있는데 너무 작으면 blur하너나 artifact가 생기고 너무 크면 부분적으로 이상한 것들을 생성해내는것을 확인할 수 있다.

 

 

 

마무리

이렇게 gan은 범용적인 img2img를 낮은 리소스로 수행할 수 있다.

입력 - gt 간의 관계를 학습하여 새로운 이미지에 대해서도 해당 관계를 가지는 이미지를 형성해 낼 수 있는 것이다.

최근에는 diffusion 계열이 이러한 img2img를 잘 하는 것으로  알고 있는데 후에 diffusion에 대한 review도 해보려고 합니다.

찾으며 diffusion poilcy라는 방법이 robotics에서도 핫하다는데 해당 방향성으로 공부를 조금 해 보려고 합니다.

 

직접 gan을 써보고 모델도 pix2pix는 아니지만 조금 더 복잡한걸로 구현해서 사용까지 해 봤는데 이러한 논문 정독 후 코드리뷰가 큰 도움이 됨을 느겼습니다.

그림 20000

 

행복하세요

 

 

지난번 Attention is all you need 를 리뷰한 것에 이어 , vision에서 transformer가 성공적으로 적용된 모델인

ViT 논문에 대해서 리뷰해보겠습니다.

 

논문 arxiv link

https://arxiv.org/abs/2010.11929


ABSTRACT

- Transformer가 자연어 처리 분야에서 성공을 겪은 것과 달리 computer vision 분야에서 이의 활용은 제한되어 왔다.

- 기존 vision 연구에서 attention은 CNN과 결합되어 사용되거나, CNN 전체 구조는 유지한체로 특정 요소를 대체하는 방식으로 활용되어 왔다.

- 위 논문에서는 CNN의 전체 구조 유지가 필요 없이, 이미지 patches들의 sequence에 대해 순수 transformer를 적용한 것이 이미지 분류에 있어서 잘 작동함을 보여주려 한다.

- 큰 사이즈의 dataset에 대해 pretrain하고, 기존 recognition benchmark들에 적용했을 때 이는 기존 CNN의 SOTA 성능에 맞먹는 성능을 보이면서, 학습에 있어서 더 적은 컴퓨팅 리소스를 필요로 했다.

 

INTRODUCTION

- Transforemer(Self-attention based architecture)는 NLP분야에서 거대 데이터에 대해 pre-train되고 , 작은 데이터셋에 대해 fine-tune하여 사용하는 방식으로 사용된다.

- Transforemer의 계산 효율성은 모델의 사이즈와 데이터셋이 커져도, 성능을 지속적으로 향상시키는데 도움을 준다.

- 이러한 자연어 분야에서 성공을 거둔 Transformer를 최대한 작은 수정을 통해 vision에 적용시키고자 한다.

 

이미지를 patch들로 쪼게고 해당 patch들의 선형 임베딩 seq이 transformer의 input으로 들어간다.

이미지 패치들은 NLP에서의 token(word)와 같이 다루어진다.

 

해당 방법을 ImageNet같은 midsize 데이터셋으로 학습시키면 , 모델의 성능은 Resnet에 못미치는 정도이다..

: Transformer가 CNN에 내제된 inductive bias ( translation equivariance , locality ) 를 가지지 못한다 

-> 불충분한 데이터에서 Transformer는 잘 작동하지 않는다.

 

그러나, 충분히 큰 데이터셋으로 학습키면 학습이 inductive bias를 능가한다.

우리의 모델 Vit는 충분히 큰 데이터로 pre-train시키고 fewer datapoint 의 task로 transferred (fine-tune)했을 때 이전 SOTA 모델들의 벤치마크 성능을 압도했다.

 

* CNN의 inductive bias

 

locality : output이 input의 국소적 이웃에 의존 - ( kernel로 인한 convolution 연산 의존 )

픽셀 간의 거리가 멀면 서로의 연관성이 낫다고 가정

 

Translation Invariace :

CNN은 동일한 kernel이 이미지 전체를 이동하며 계산

> 입력의 위치가 변하여도 불력 feature map의 활성화도 동일하게 변한다

입력의 위치가 변하여도, 출력 결과 (class)는 변하지 않음 

 

METHOD

Fig1

 

- patch embedding

1. H * W * C 차원의 입력을 가로세로 P인 패치 N개로 자른다 ... H*W*C > N*(P^2 * C)

2. transformer는 d사이즈의 벡터를 입력으로 사용 , D dimension로 trainable한 Linear projection E를 진행 (equ 1)

이러한 patch를 Linear projection 한 것을 patch embeddings 라고 한다.

 

- position embedding

patch의 position 정보를 넣기 위해 position embedding 을 추가함 (equ 1)

해당 논문에서는 2D position embedding에서 유의미산 성능 이점을 찾지 못했기에

최종적으로 stradard learnable 1D position embedding를 사용 , 이러한 position embedding은 encoder의 input으로 들어감

 

- CLS token

* BERT의 [class] token과 같은 맥락으로 학습 가능한 embedding 한개를 임베딩 시퀀스 앞에 추가 Xclass = z0

Transformer encoder를 통과한 뒤, 해당 토큰에 해당하는 z를 이미지 representation y로 사용한다.

 

pre-train과 fine-tunning에서 각각 classification head가 해당 토큰의 encoder 결과에 붙는다 (MLP가 붙는다는 말)

논문에서는 pre-train에서 1개의 hidden layer MLP를 , fine-tuning 에서는 1개의 linear layer를 사용한다.

 

 

- layer nomalization

transformer encoder는 MSA(multi head attention)과 MLP 블록으로 이루어져있다. 

layer nomalization과 residual connection이 매 블록 후에 적용이 된다.

또한, MLP는 GELU로 비선형성을 가지며 2개의 layer를 가진다..

 


 

method - inductive bias

CNN에서는 locality - two dimensional neighborhood structure와 translation equivariance라는 구조적 가정이 들어가 있으며, 이러한 inductive bias가 전체 모델의 layer에 걸쳐 반영되어 있다.

 

그러나 Vit는 오직 MLP layer만이 이러한 inductive bias를 가지며 (self-attention은 global하게 적용됨)

 

two dimensional neighborhood structure는 모델의 시작 단계에서 이미지를 patch로 분할할떄와 ,

fine-tune할때 서로 다른 이미지의 해상도에 맞춰 position embedding을 조정할 떄에만 제한적으로 사용된다.

 

그러나 초기 시점의 position embedding은 2차원 정보를 아예 담고 있지 않으며 모든 공간적 관계는 처음부터 학습되어야 한다.

 

method - Hybrid Architecture

raw한 image를 patch의 input으로 넣는 것이 아닌 입력 seq를 CNN의 feature map을 input으로 구성하기도 한다. 

CNN으로부터 얻어진 feature map에서 추출된 patch들을 대상으로 patch embedding projection을 진행한다 - 

 

또한, 특별한 case로 patch의 spatial size를 1x1로 설정하여 가지게 시작하는 경우도 있다. 

이 경우 입력 seq는 feature map의 단순히 펼친 뒤, 이를 Transforemr 차원으로 투영하는 방법으로 얻어진다.

 

method - FineTunning and higher resolution

보통 Vit는 큰 데이터셋에서 pre-train하고, 작은 데이터셋에서 fine-tunning하는 방법을 사용한다.

해당 과정에서 기존 prediction head는 제거하고 , 새로운 fine-tunning class 수에 맞는 초기화된 feedforward layer를 달아준다.

 

보통 fine - tunning에서는 pre-train보다 높은 해상도의 이미지를 쓰는 것이 좋은데, 

이미지의 해상도가 높아지고 기존의 patch size는 같게 쓰는 것은 결과적으로 patch의 갯수가 많아짐 즉, seq의 길이가 길어짐을 의미한다.

 

이렇게 되면 기존의 pre-train 된 position vector가 무의미해지는 결과가 나오기에 , 사전학습된 position embedding을 2D 보간하는 방식으로 이전 pre-train에서의 position embedding의 효과를 다시 적용시킨다.

 

* 해당 해상도 조절과 patch extraction (2d 보간)이 vit에 inductive bias를 임의로 주입한 얼마 안되는 부분임을 주목 !

 

EXPERFIMENT

 

 

 


Vit 논문을 읽고 리뷰해보았습니다.

논문에서 언급된 CNN의 inductive bias와 관련하여 , vit가 large dataset에서 충분히 학습되어야 하는 이유를 인상깊게 읽었습니다.

추가로 모델 구조에서 사용된 , LN GELU에 대한 이해를 추가로 하고 모델코드를 분석하는 시간을 가지려고 합니다. 

Scaled Dot-Product Attention

Self - Attention

Multi-Head Attention

Position-wise Feed-Forward Networks

Positional Encoding

 


 

3. Model Architecture

 

트렌스포머는 seq2seq 구조와 유사하게 , encoder / decoder 구조로 구성되어있다.

encoder와 decoder는 동일한 layer의 stack으로 N = 6 개가 쌓여있으며

각 encoder/decoder는 내부에 각 2개의 sub-layer로 구성되어있다.

 


 

3.1 Scaled Dot-Product Attention

 

attention은  Scaled Dot-Product Attention을 사용하며, 기존 attention과 동일하게 query, keys, values 를 사용한다.

여기서 query, keys, values 는 1개 시점의 값이 아니라 전체 시점에 대한 벡터이다.

 

Q  query와 K  keys의 유사도를 내적 (Dot-Product)을 통해 표현한다 .

(

* 기존에 MLP로 표현한 것과 차이가 있다.  - 이를 additive attention 이라고 한다.

additive attention은 1개의 은닉층을 가진 피드포워드 신경망을 사용해 query와 key 사이 호환성 함수를 구한다.

이 둘의 이론적 복잡도는 동일하기만 matrix 연산으로,  최적화하기에 용이해,  Dot-product를 사용한다.

)

 

softmax를 사용해서 이를 확률로 바꾸어 준다 ( 0 ~ 1 )  - attention weight matrix 

 

이후 이를 value와 곱하여 출력이 계산된다. 

 

 

여기서 key의 dimension 인 dk 가 작으면 , scaled 를 제외하고 두 개 attention 방법의 성능이 유사한데

dk가 커지면 , dot product의 크기가 커져 softmax 함수의 기울기가 급격하게 작아지기 때문

-> 따라서 root dk로 스케일링 해준다.

 


 

3.2 Multi-head Attention 

Multihead attention 수식, 2번의 Linear projection이 진행된다.

 

Transformer 구조에서는 single attention으로 dmodel 차원의 Q,K,V를 만들어 내는 대신,

h개의 multi-head Attention을 통해, linear projection을 통해 dq,dk,dv차원의 Q,K,V를 만들어내고 이를 concat한 다음 또 한번 linear projection하여 결과를 만들어낸다. 

 

멀티헤드 어텐션을 사용하므로써, h개의 head가 서로 다른 representation subspace를 반영할 수 있는 장점이 있다.

싱글 헤드 어탠션은 representation을 한개의 subspace에 대해 표현하고 averaging하므로써 다양한 subspace에서의 정보가 noisy해진다. 

 

또한, computational cost 관점에서도 차원을 dq dk dv로 줄여서 h개의 head가 처리하고 합쳐 d model로 복원하므로 single-head attention과 큰 차이가 없다.

 

 


 

3.3 Position-wise Feed-Forward Networks

Fig1을 참고하면 encoder와 decoder의 각 구조 안에서 Feed-Forward가 있는 것을 확인할 수 있다.

위의 수식과 같이 2개의 linear transformation과 ReLU로 이루어져있고,

해당 가중치는 layer 단위로는 공유하지 않지만, layer 안에서 position에 대해서는 공유한다. (CNN의 Kernel을 생각하면 편하다).

또한 각 posion에 대해 seqpartely and identically 즉 , 각 posion끼리의 정보는 섞이지 않는다.

 

차원은 512 -> 2028 -> 512의 구조를 보이며, cnn에서 1x1 kernel의 convolution 구조와 같음을 논문에서 언급하고 있다.

 


 

3.4 Positional Encoding

 

모델에서 CNN, RNN의 구조를 사용하지 않아 순서 정보가 포함되지 않아 , 각 token간 상대적인/절대적인  위치 정보를 넣어주기 위해 Positional Encoding을 사용한다.

 

주어진 input에서 positional encoding을 진행하고 input embedding에 더하는 방식으로 구현되고 , 이러한 positional encoding을 위해 학습을 통한 방식 / 고정된 방식 등 여러 방식이 존재하지만 논문에서는 아래와 같이 서로 다른 주파수를 가지는 sin/cos 함수를 사용한다.

 

위에서 pos는 position이고, i는 dimention이다. 

요약하자면, 주기함수의 특징으로써 해당 pos가 늘어나도 encoding이 가능하고, 삼각함수의 성질으로써 선형ㅇ함수로써 표현이 가능하기에 해당 encoding 방식을 사용했다고 한다. ( 학습을 통한 방식에 대비해 성능은 유사하지만 seq 길이에 대해 더 자유로운 특성)


4. Why self-attention

 

왜 해당 모델에서 self-attention을 사용했는지 설명하는 부분이다.

먼저 self-attention에 대한 정의부터 다시 짚고 넘어가자. 

Self-attention, sometimes called intra-attention is an attention mechanism relating different positions of a single sequence in order to compute a representation of the sequence.

 

모델에서는 이러한 self-attention을 attention layer라는 개념으로 일반화하여 사용하며 사용의 근거를

1. computational complexity 2. amount of computation (can parraleized) 3. path length between long-range dependencies로 설명하고 이를 기존의 rnn과 cnn과 비교한다.

 

self- attention layer는 아래와 같이 동일한 input seq에 대해 , seq안에서 어떤 token끼리 관계가 있는 방식으로 단일 input seq에 대해 Q,K,V를 계산한다.

 

위에서 생략한 3.2.3 Applications of Attention in our Model을 다시 불러오자면,

encoder, decoder 단에서는 위와 같은 self - attention이 사용되고, decoder의 경우에는 자기 자신을 포함하여 이전 position에 대해서만 attention 하도록 미래의 값에 대해서는 masking out하고, encoder는 이러한 과정이 없다. 

 

encoder -> decoder  attention layer에서는 self - attention이 아니라 queries들은 이전 decoder layer의 output을 , key와 value들은 이번 encoder의 output에서 나오고, input seq의 모든 position에 대해 attention을 진행한다. (전형적인 seq2seq의 attention과 같다고 생각하면 된다.)

 

 


review

지금까지 Attention all you need 를 읽고 리뷰해보았습니다. 비록 전체 논문을 읽고 분석한거는 아니지만 , vision 분야 transformer 를 이해하기 위해 배경지식으로써 읽어보았고 Vit, Swin 등의 논문을 리뷰하고 다시 돌아와 어떤 부분이 초기 자연어 처리를 위한 transformer에서 영감을 얻어 만들어졌는지 확인해 볼 계획입니다. 

 

특히 , decoder의 masking out이나, position encoding의 작동 원리와 이유에 대해서는 직관으로써 이해하고 넘어갔으나 후에 다시 돌아와 자연어 처리에 대한 지식을 겸비하여 다시 읽어보려고 합니다.

지난번에 seq2seq에 대한 기본 개념, attention에 대한 기본 개념을 이야기해 본것이 더불어 attention is all you need라고 하는 

transformer라는 모델 구조에 대해 제안한 논문을 리뷰하고, 그 안의 self - attention 등의 개념에 대해 알아보고자 한다.

자연어 처리에 대한 직접적인 지식이 필요한 것이 아니기에,

해당 논문에서 필요한 개념만 발췌독하였고 핵심에 해당되는 부분은 영여원문을 전부 첨부하였다.

 

Vaswani, A., Shazeer, N., Parmar, N., Uszkoreit, J., Jones, L., Gomez, A. N., Kaiser, Ł., & Polosukhin, I. (2017).
Attention is all you need. arXiv preprint arXiv:1706.03762.


1. Introduction 

RNN , LSTM , GRU를 활용한 , 기계 번역 언어 모델링과 같은 Sequence Modeling & Transduction 문제 해결은 SOTA의 성능을 만들어 내었고, 이후 recurrnet language model과 encoder-decoder 아키텍쳐에서의 한계점을 해결하기 위한 많은 연구들이 진행되었다.

recurrent model ( RNN )

 

->

 

Sequence Modeling : input과 output의 순서적인 특징을 학습하여 다음의 seq 토큰을 맞추는 task

Transduction : input과 output의 길이가 다른 seq라 하여도 변환하는 task ( 번역 )

 

저자가 기존의 RNN 구조의 성능을 인정함과 동시에 기존 구조의 한계점을 극복하기 위한 연구가 진행됨을 서술하는 부분이다.

recurrnet language model과 encoder-decoder 아키텍쳐와 같은 개념이 후에 등장할 것을 짐작할 수 있다.

 

 


Recurrent models (RNN) 계열은 본질적으로 입력 시퀀스의 토큰에 따라 시간축을 분해하여 , 계산을 수행한다.

전 단계의 hidden state( h t-1 )와 해당 위치에서의 input 토큰을 가지고 해당 시점의 hiddent state t를 계산할 수 있다.

이러한 순차적 특성 sequential nature은 학습 내부에서의 병렬화를 불가능하게 만든다. (GPU를 활용한 연산이 어렵다)

또한 이는 시퀀스 길이가 길어질 수록 문제가 커지며, 메모리 한계로 인하여 batch 병렬 처리도 제한되기 때문이다.

이를 해결하기 위한 다양한 방법이 논의되었지만 해결하지 못하였다.

 

->

 

RNN 구조의 본질적인 문제 "순차적 특성"으로 인한 병렬 처리 불가, 메모리 제약을 문제의 본질로 짚고 있는 것이다.

 


attention weighted map



Attention 매커니즘은 이미 다양한 Transduction, sequence modeling에서 핵심 구성요소가 되었다. 또한 Attention은

가까운 것만 잘 기억하는 RNN의 특성을 극복하여, 거리와 관계없이 (seq상의 거리) 요소간의 관계성 (token간의 의존성)을 모델링하게 해주었다. 하지만, 해당 attention은 여전히 recurrent network와 함께 사용되고 있다.

 

-> 

 

attention의 기능 ( seq 상 거리와 관계없이 연관된 요소간의 관계성을 기술 ) 과 유용함을 언급함과 동시에 이가 여전히  recurrent network와 함께 사용되는 문제점을 지적하고 있다.

 


In this work we propose the Transformer, a model architecture eschewing recurrence and instead relying entirely on an attention mechanism to draw global dependencies between input and output. The Transformer allows for significantly more parallelization and can reach a new state of the art in translation quality after being trained for as little as twelve hours on eight P100 GPUs.

 

본 연구에서는 recurrence를 제거하고, 대신에 전체적으로 attention 매커니즘을 활용하여 입력과 출력 사이 global dependencies를 기술하는 Transformer를 제안한다. Transformer는 more parallelization , 병렬화를 통해 짧은 시간의 학습만으로도 SOTA의 성능을 달성하게 되었다.

 

->

** introtuction의 중요한 부분 ! transformer 구조의 제안

기존 문제가 되었던 Recurrent models들의 순차성을 해결하기 위해 attention을 단순 RNN의 보조 도구에서 전체 모델의 백본으로 사용함으로써 해당 문제를 해결함과 동시에 병렬성을 개선

 


2. Background

RNN의 순차성을 개선하기 위해 CNN 구조에서의 접근도 있었다. (CNN 구조는 병렬처리에 용이함)

그러나, 기존 CNN애서 멀리 떨어진 두 위치끼리 상호작용하려면 여러 레이어를 거쳐야하는 문제가 있었다. ( RNN과 같은 거리 의존성 존재) . 결과적으로 CNN을 활용한 접근은 장거리 의존성 학습에 있어서의 어려움이 있었다.

 

 

.. 이에 관련한 transformer의 해결방법 간략하게 소개

Self-attention, sometimes called intra-attention is an attention mechanism relating different positions of a single sequence in order to compute a representation of the sequence

 

****

self-attention은 한개 sequence상의 여러 다른 위치간의 관계를 서술하는 방식으로 seq를 표현하는 attention 매커니즘이다. 해당 방법은 다양한 분야에 있어서 이미 성공적인 성능을 보여주는데 기여하였다.

 

To the best of our knowledge, however, the Transformer is the first transduction model relying entirely on self-attention to compute representations of its input and output without using sequence-aligned RNNs or convolution.

 

Transforemer는 RNN이나 CNN에 의존하지 않은 체 , self-attention에만 의존한 최초의 transduction 모델이다.

 

In the Transformer this is reduced to a constant number of operations, albeit at the cost of reduced effective resolution due to averaging attention-weighted positions, an effect we counteract with Multi-Head Attention as described in section 3.2.

트랜스포머의 attention weight를 활용한 계산때문에 정보의 소실이 일어나지만, 3.2에서 나오는 Multi-Head Attention으로 극복한다.

 

-> 

 

해당 논문의 method에서 사용할 주요 요소들을 저자가 간략하게 소개한다.

첫번째로 거리 의존성을 해결하는 self - attention. 

두번째로 attention weight로 인한 가중합계산으로  해상도가 저하되는 것을 multi - head attention을 통해 극복한다는 것이다.

( attention 된 부분이 표시된 weight mat를 정보 행렬에 곱하면 정보가 섞이는 문제가 생김 -> noise 발생 , 이를 multi - head 다양한 관점에서의 attention을 동시에 행함으로써 극복한다는 것이다 . )

 


RNN에서의 거리 의존성, 병렬처리의 어려움을 단지 self-attention 구조만을 쓰는 것으로 해결했다는 것을 논문 제목 그대로 표현하였다.

Attention is all you need !

Attention is all you need를 읽기에 앞서 간단한 자연어 처리 , RNN , seq2seq 구조, attention에 대한 사전지식을 공부했습니다.


 

1. RNN , Seq2Seq

attention, transformer란 애초에 자연어 처리를 목적으로 하여 만들어진 개념이기에 해당 분야에 대한 기본지식이 필요하다. 

기본적으로 RNN이란 , CNN과 같은 신경망에서 순차적인 정보를 이해하지 못하는 것을 해결하기 위해 만들어진 기법이다.

(sung kim 거이 끝부분에서 한번 배웠는데 스터디원들과 다같이 이해는 안되었지만 어물쩍 넘어간 기억이 난다)

그림에서 볼 수 있는 것 과 같이 상대 h ( 표면적으로는 안보인다고 하여 hidden state h라고 부른다. 대충 deep learning의 hidden state같은 개념 )를 다음 시점으로 넘겨주고 그 다음 시점에서는 이전 시점에서 받은 h와 input x를 참조하여 output o를 만들어 내는 것을 알 수 있다 .

 

좌측 그림은 해당 과정을 재귀적으로 표현한 것이고, 우측은 그냥 해당 과정을 펼쳐놓은 것이다.

 

수식을 통해 이해해보자(perflexcity의 도움을 얻었다),

위 node로 표현된 그림에서 v,w,u를 연결해주는 부분에 각각 가중치가 붙어있다.

CNN과 같이 RNN 또한, 원하는 성능을 만들어내기 위한 해당 가중치를 얻는 것이 학습의 목적이 되는 것으로 생각할 수 있었다.

(정확하게는 RNN 단독으로는 backprop을 통한 학습이 어려워 후에 LSTM 등 보완된 구조가 제안되었다고 한다)

 

 

RNN에서 유의깊게 봐야 할 것은 해당 모델은 seqence 즉, 순서가 있는 것을 처리하는 모델이라는 점이다.

이어서 관련이 있는 seq2seq를 봐보자.

 

seq2seq 란 RNN을 활용하여 번역을 하는 것과 같은 task를 처리하는 모델을 말한다.

왜 seq2seq인가 하면 "나는 모니터입니다." 를 "I'm monitor" 로 바꾸어 주는 모델을 생각해보면 입력도 순서가 있는 순서가 입력 seqence  출력 또한 순서가 있는 출력 seqence 임을 알 수 있다. 따라서 seq2seq이다.

 

기본적으로 seq2seq 모델은 encoder - decoder 구조를 띈다.

encoder는 input seqence의 "의미"를 context vector로 압축한다.

그리고 decoder는 context vector를 사용해 출력 문장을 한개 토큰씩 생성한다.

 

Encoder가 만든 문장의 전체 의미 " context vector" 를 참조하고, 이전에 decoder 자기 자신이 만든 state( hidden state)를 참조하여 다음에 생성할 토큰 (output)을 생성하는 것이다.

 

(자꾸 토큰이라는 단어가 사용되는데, token은 모델이 처리하는 최소 단위의 simbol이라고 보면 된다.

때에 따라서 단어가 될 수 있고, 음절이나 숫자, 코드, 로봇의 행동 <MOVE> ,<TURN>등이 될 수 있다. 조합되는 기호의 단위 즉 가장 작은 퍼즐의 단위라고 보면된다. )

 

이러한 seq2seq 방법에서의 문제점은 초기 encoder가 input을 압축해 생성한 context vector가 input의 길이가 길어지는 경우 context vector가 해당 input을 전부 표현하지 못하거나, 중요한 정보가 소실되는 경우가 생긴다. 이를 해결하기 위해 나온게 attention이다.

 


2. attention

이전 seq2seq에서는 하나의 context vector로 문장 전체의 의미를 표현하려고 하다 보니, 정보의 손실과 표현의 한계가 발생하는 문제가 생겼었다. 

다시 정리하면 encoder에서 나온 하나의 context vector를 사용해, 각 time(state)마다

이전의 state + 전체 문장의 한 개 context vector를 사용해 decoder에서 각 token을 생성해낸다.

 

여기서 attention 기법을 사용하면,

각 time step 마다

input sequence의 가공된 정보를 재참조한다. (context vector)

그런데 , 이 context vector는 단순히 이전 seq2seq에서 문장을 하나의 벡터로 다 표현한 context vector 가 아니라 

해당 time step에서 주목할 부분에 대한 고려 attention을 참조해서 encoder에서 input seqence를 가공한 

context vector이다.

 

정리하면, 매 step에서 전체 input 문장의 의미를 담은 축약본을 참고하는 것이 아닌,

해당 step에서 input 문장서 중요한 부분을 중심적으로 attention한 의미 표현 context vector를 참조한다는 것이다.

 

encoder의 hidden state와 decoder의 현재 state를 참조해 e를 만들어 낸다. (encoder의 각 state에 집중하는 정도 - scaler)

이에 대해 softmax 해주어 0~1 사이 확률값으로 만들어준다 (attention weights)

해당 확률값과 encoder의 hidden state를 weighted sum하여 해당 시점의 context vector를 만든다.

 

<encoder hidden state + decoder의 현재 state > -> e 부분은 MLP를 통해 구현 

전체 과정은 backprop이 가능하여 학습이 가능하도록 한다.

 

1. binary prediction and sigmoid

추론값의 결과가 0 또는 1로 나타나는, 이진 모델binary classification 모델에 쓰이는 sigmoid함수에 대해 알아보자.

sigmoid

정의역이 실수 전체이고, 치역이 0 과 1 사이인 sigmoid 함수는 답이 True / False 형태로 나오는 문제에 적용하기 좋다.

정의역에서 -4 또는 4 밖으로 벗어나는 값을 가지면 함숫값이 0 또는 1에 근사하는 모습을 볼 수 있다.

 

또한 해당 함수는 값이 0~1 사이의 값으로 나온다는 점에서, 추론값이 확률로 필요할 때 쓰이기도 한다.

 

2. Logistic Regression(로지스틱 회귀)

로지스틱 회귀란, 선형 모델에 simoid함수를 결합하여 사용한 모델이라고 볼 수 있다.

사건의 발생 여부 (이진 분류)를 단순 선형 모델로 표현하는 경우, 새로운 값의 추가가 기존 분류 모델에 큰 영향을 미칠 수 있다.

기존의 선형 모델을 분류에 더 적합하게 완만한 곡선으로 나타내여, 이를 방지하는 것이다. 

로지스틱 회귀의 이진 분류

 

치역에서 0.5를 기준으로 TURE / FALSE를 결정한다. 아래에 로지스틱 회귀와 관련한 설명 블로그를 추가한다.

https://itstory1592.tistory.com/8

 

2. Binary Cross Entropy Loss(이진 교차 엔트로피 loss)

모델의 출력이 0~1인 확률값으로 나오므로 기존에 쓰던 MSE Loss 의 대안인 Binary Cross Entropy Loss를 사용한다.

\[
\mathcal{L}(y, \hat{y}) = - \left[ y \cdot \log(\hat{y}) + (1 - y) \cdot \log(1 - \hat{y}) \right]
\]

 

loss의 기본적인 원리는 모델의 예측값이 참에 가깝다면 loss가 작고, 참에서 멀어질 수록 loss가 큰 것을 이용한 것이다.

dataset에서 y의 값이 0 또는 1 인 점에 주목해며, 해당 식을 봐보자. 해당 식에서 y가 0또는1임에 따라 덧셈 기준 좌항과 우항이 활성화 되고, 나머지 항은 없어지는 것을 볼 수 있다.

 

  • y (참값) - 1인 경우 > -log(?)안에 y_pred 가 들어감 > log(y_pred) > y_pred가 1에 가까울 수록 loss 작음
  • y (참값) - 0인 경우 > log(1-?)안에 y_pred 가 들어감 > log(y_pred) > y_pred가 0에 가까울 수록 loss 작음

 

Binary Cross Entropy Loss
log 함수 - 해당 loss계산시에는 정의역이 sigmoid의 치역이므로 0~1인점을 고려해야 한다.

 

3. Code 

sigmoid 모델을 사용한 로지스틱 회귀 torch 구현 코드이다.

기존 선형 회귀 모델에서 model class 정의, loss function 의 종류만 다르다.

import torch

x_data = torch.tensor([[1.0],[2.0],[3.0],[4.0]])
y_data = torch.tensor([[0.],[0.],[1.],[1.]])


class Model(torch.nn.Module):
   def __init__(self):
      super().__init__()
      self.linear = torch.nn.Linear(1,1)

   def forward(self,x):
      y_pred = torch.nn.functional.sigmoid(self.linear(x))
      return y_pred

model = Model()
criterion = torch.nn.BCELoss(reduction='mean')
optimizer = torch.optim.SGD(model.parameters(), lr = 0.01)

with torch.no_grad():
   hour_var = torch.tensor([[7.0]])
   temp = model(hour_var)
   print(" 학습 전 7.0에 대한 추론값 ", temp.item())
   print(f'Prediction before 7.0 hours of training: {hour_var.item():.4f} | Above 50%: { temp.item() > 0.5}')

for epoch in range(100):

   y_pred = model(x_data)
   loss = criterion(y_pred,y_data)
   print("epoch loss",epoch, loss.item())
 
   optimizer.zero_grad()
   loss.backward() 
   optimizer.step()
 

with torch.no_grad():
   hour_var = torch.tensor([[7.0]])
   temp = model(hour_var)
   print(" 학습 후 7.0에 대한 추론값 ", temp.item())
   print(f'Prediction after 7.0 hours of training: {hour_var.item():.4f} | Above 50%: { temp.item() > 0.5}')







+ Recent posts