Intro

참고글 : https://lilianweng.github.io/lil-log/2018/11/30/meta-learning.html

 

Meta-Learning: Learning to Learn Fast

Meta-learning, also known as “learning to learn”, intends to design models that can learn new skills or adapt to new environments rapidly with a few training examples. There are three common approaches: 1) learn an efficient distance metric (metric-based);

lilianweng.github.io

어린 아이들은 몇 장의 고양이와 코끼리 사진만을 보고도 둘을 이해하고 구분할 수 있다.

하지만 머신 러닝에서는 많은 데이터가 필요하다.

이 점에서 착안하여 신경망 또한 적은 데이터로 무언가를 할 수 있게끔 하고 싶다는 것이다.

이로 인해 배우는 법을 배우는 것이라고 표현하기도 한다.

개념적인 부분이므로 이를 이용해 분류나 강화학습 등 다양한 도메인에 접목할 수 있다.

 

이를 위한 세 가지 접근법이 존재한다.

1. Metric-based

2. Model-based

3. Optimization-based

 

RL 분야에 대해선 다음 시간에 정리하겠다.

Classification 문제로 구체화하여 볼 때를 생각하고, 아래에 차례대로 정리하겠다.

 

Metric-based

주어진 few shot data와 test data와의 유사성을 구하여 test data의 y 값을 구하는 방식이다.

그렇다면 유사성을 어떤 방식으로 구해낼 것인가가 주요점이라고 볼 수 있다.

이와 관련된 모델들을 간략한 소개와 함께 소개한다.

 

Convolutional Siamese Neural Network

 

Convolutional Siamese Neural Network 논문의 Fig.1

 

기능은 두 개의 이미지가 같은 클래스에 속하는 이미지인지를 구하는 모델이다.

이를 조금 응용하여 테스트 시에는 여러 클래스 객체가 포함된 여러 장의 few shot data 중에서 특정 클래스 객체가 포함된 한 장의 test data가 속하는 클래스를 찾아내게끔 한다.

사진 1과 사진 2를 같은 CNN 모델을 통해 Embedding 한 뒤 L1 거리를 구하고, 이를 MLP의 입력으로 넣어 최종적으로 1과 2이 같은 클래스에 속할 확률을 구해낸다.

즉 이 모델은 유사성을 임베딩 값의 L1 distance로 나타내었다.

 

 

Matching Network

어텐션을 적용하는 모델이다.

이 모델은 임베딩 값의 Cosine distance로 유사성을 계산하였다.

 

Relation Network

각 데이터 사이의 유사성을 구해내는 모델이다.

일단은 각각의 데이터를 임베딩한다. 

임베딩 후 sample data S와 test data x가 있다고 할 때, [S1, x], [S2, x], ... 로 concat하여 유사성 계산 모듈(relation module)에 입력으로 넣는다.

이를 통해 relation score가 나오게 되고, 이를 이용하여 test data가 어떤 sample data와 같은 클래스인지를 파악한다. 

임베딩 값을 concat하여 Relation module의 추가적인 입력으로 사용하여 나온 출력값을 유사성으로 표현했다.

 

Prototypical Network

각각의 클래스에 속하는 데이터들에 대해서 평균적인 feature vector를 클래스마다 뽑아낸다.

test data와 feature vector의 거리를 구해내어 최종적인 class를 판별한다.

거리는 L1 혹은 코사인 등 여러 가지 방법이 사용될 수 있다.

 

 

전체적으로 어떻게 임베딩을 실시하고, 어떻게 distance를 측정할 것인지에 집중되어 있다.

전체적으로 짧게 요약하자면, few-shot으로부터 학습하기 위해 meta적인 파라미터를 학습시켜놓는 것이며, 이를 알고리즘으로 표현한 것이다.

 

본 논문의 Fig.1

즉 위 그림처럼 Distribution of Task T에 대하여 메타적인 파라미터 세타가 있으면, 특정 Task Ti에 대해서 몇 개의 데이터(supervised) 혹은 탐험(강화학습)으로부터 얻어낸 로스를 활용하여 Task Ti에 맞는 파라미터 세타i가 될 수 있게끔 하는 것이다.

 

이를 대략적인 알고리즘으로 나타내면 아래와 같다.

본 논문의 Alg.1

대략적으로 단계를 표현하면,

1) 특정 Task에 맞게끔 로스를 이용하여 세타i 를 구해낸다.

2) 세타i가 정말 특정 Task에 맞는지 로스를 구해 세타를 수정한다.

 

이를 supervised나 강화학습에 구체화시키면 아래와 같다.

본 논문의 Alg.2
본 논문의 Alg.3

 

이 논문에서 실험한 내용 중 인상깊은 내용은 Supervised 관련 부분이다.

간단한 Regression 메타 러닝에 대한 실험이었다.

sinusoid 모양의 함수를 모델이 파악할 수 있으면 된다.

비교 대상은 1) MAML로 학습한 모델 2) 하나의 sinusoid에 대해 pretrain된 모델 이다.

두 모델이 얼만큼 빨리 특정 모델로 변할 수 있는가를 테스트한다.

본 논문의 Fig.2

MAML 모델의 pre-update 모양은 정확한 sinusoid 모양은 아니지만, 특정 모양으로 굉장히 빠르게 변하는 것을 확인할 수 있다.

이는 meta적으로 sinusoid 모양을 학습한 것이라고 볼 수 있다. 

반면 pretrain 모델은 GT 모양에 맞게끔 fine-tuning 되는 것이 쉽지 않아보인다.

 

결론적으로 든 생각은 MAML 알고리즘을 활용하여 다양한 부분의 메타 러닝에 접목할 수 있겠다는 것이다.

본 논문의 링크는 아래에 있습니다.

https://arxiv.org/abs/1709.04905

 

One-Shot Visual Imitation Learning via Meta-Learning

In order for a robot to be a generalist that can perform a wide range of jobs, it must be able to acquire a wide variety of skills quickly and efficiently in complex unstructured environments. High-capacity models such as deep neural networks can enable a

arxiv.org

 

Abstract

다양한 일에 대해서 로봇이 수행할 수 있게끔 하기 위해서는 일반화가 잘 되어야 합니다.

이를 위해서는 다양한 범위의 일에 대해서 빠르게 배울 수 있어야 하고, 복잡환 환경에서 효율적이어야 합니다.

Deep Neural Network는 로봇이 복잡한 기술을 수행할 수 있게끔 했지만, 각각의 기술들을 처음부터 배우는 건 어렵습니다.

이 논문에서는 단지 하나의 데모만을 이용하여 새로운 기술을 습득하는 효율적인 방법인 meta-imitation learning method를 소개합니다.

이전의 one-shot imitation과는 다르게, 이 방법은 raw pixel input을 사용하며, 이전에 배웠던 기술을 새로운 기술을 배우기 위해 효율적으로 사용합니다.

시뮬레이션과 실제 환경에서의 실험을 통해 하나의 visual demo만을 이용하여 새로운 기술을 end-to-end로 학습할 수 있다는 점을 증명할 것입니다.

 


* one-shot visual demo로 어떻게 학습을 시킬 수 있을까요?

보통 사용되는 state-action의 one-shot demo를 이용한다면 어느정도 납득할 수 있겠지만, 어떻게 하면 visual state에서 어떤 액션과 상태인지 파악할 수 있을까요?

 

1. Introduction

Deep Neural Network를 사용하여 복잡한 task 하나를 학습시키기 위해선 많은 양의 supervised 데이터, 혹은 경험이 필요합니다.

그러면서도, 다음으로 배울 task의 좀 더 빠른 학습을 위해서 이전에 배운 task를 활용하는 방법은 사용되질 않았습니다. 

위 방법을 사용하면 데이터를 효율적으로 학습할 수 있고, 각 task에 대해 최소한의 supervision만 주어지면 됩니다.

그렇다면, 어떻게 하면 이전의 task에서 정보를 탐색하여 새로운 task에 대해 빠르게 학습할 수 있을까요?

 

이 논문은 로봇이 이전의 경험을 재사용하여 결과적으로 새로운 기술을 단 하나의 데모를 통해서 배울 수 있는 meta-learning with imitation 방법을 제안합니다. 

이 논문에서의 접근 방법은 parameterized policy 입니다.

위 policy는 기울기 업데이트를 통해 다른 task들에 적용될 수 있고, 효과적으로 imitation learning이 가능하게 합니다.

 


* 모델과 하나의 중앙 파라미터가 존재하고, 이를 데모를 통해 gradient를 계산하고 바꿔서 모델이 task를 할 수 있게끔 합니다.

그러므로 어떤 task를 하려면 그 task에 대한 데모가 하나 무조건 필요한 것으로 보입니다.

 

3. Meta-Imitation Learning Problem Formulation

<MAML>

위 모델과 관련된 논문은 아래 링크입니다.

https://arxiv.org/pdf/1703.03400.pdf

불러오는 중입니다...

Model-Agnostic Meta-Learning, 본 논문은 위 모델을 기반으로 하여 사용했다고 합니다. 

MAML을 간단히 설명드리면 하나의 뉴럴 네트워크가 있고, 가중치가 있습니다.

이 가중치를 특정 task에 쓸 수 있게끔 조금씩 바꿔서 다양한 도메인에 적용할 수 있게끔 하는 개념입니다.

 

대략적인 이해를 도울 수 있는 그림, MAML 논문의 Fig.1

그림은 대략적인 흐름을 보여주는 것으로 각각의 task 1, 2, 3에 대해 코어 가중치인 세타가 각각의 로스로 인해 세타* 1, 2, 3으로 변하는 것을 볼 수 있습니다. 

 

MAML 논문의 Alg.1

알고리즘으로 표현을 해보자면, 각각의 task에 대해 로스를 이용하여 특화된 세타를 만들어내고 이렇게 만들어낸 세타에 대해 로스를 계산하여 코어 가중치를 다시 한번 수정합니다(meta update). 대략적인 개념이 이해되면 어떤 식으로 이 논문이 MAML을 적용하였는지 파악해보겠습니다.

 

MAML을 접목한 imitation learning, 본 논문의 Alg.1

imitation learning, 즉 데모를 보고 따라하게끔 코어 가중치를 수정해야 합니다.

1) 가중치를 얼마나 수정할지에 대해 로스 함수를 통해 구하고, 이를 이용하여 가중치를 수정합니다.

2) 수정된 가중치에 대해 로스를 구하고, 이를 이용하여 코어 가중치를 수정합니다.(meta-update)

이를 살펴보면 코어 가중치가 각 task들에 대한 가중치에 대하여 접근할 수 있는 pretrain 가중치라고 볼 수 있을 것 같습니다.

 

그렇다면, 로스는 어떤 식으로 설정하였는지 알아보겠습니다.

 


* Pretrain이 되어있으면 학습이 좀 더 빠르듯이, MAML 개념은 모든 task에 접근할 수 있는 pretrain 가중치를 미리 설정해두는 느낌입니다.

 

4. Meta-Imitation Learning with MAML

 

코어 가중치의 목표, 본 논문의 수식.1

코어 가중치가 향하는 방향은 각각 만들어낸 가중치들에 대한 로스를 더했을때 최소가 되게끔 하는 것입니다.

 

로스 함수, 본 논문의 수식.2

로스 함수는 Observation o가 나올 때 예측한 Action a와 ground-truth를 비교한 mean squared error를 사용합니다. 

여기서의 a는 로봇 환경이므로 각 joint에 가하는 힘이라고 생각하시면 됩니다.

 

학습을 위해서는 각 task별로 두 개의 demo를 이용합니다.

첫 번째 데모를 이용하여 특정 가중치로 코어 가중치를 업데이트합니다.

두 번째 데모를 이용하여 특정 가중치와의 로스를 계산하고, 이를 이용하여 코어 가중치를 업데이트합니다.

 

테스트 단계에서는 각 task별로 하나의 demo가 존재하며 이를 이용해 특정 가중치로 업데이트하고, 테스트합니다.

 

<Two-Head Architecture : Meta-Learning a Loss for Fast Adaptation>

코어 가중치로부터 나오는 폴리시를 최종적인 출력 레이어 직전에서 두 개로 구분합니다.

pre-updated, post-updated : 이를 Two-Head라고 이 논문에서는 말하고 있습니다.

pre-updated는 최종적인 가중치에 영향을 끼치지 않습니다.

post-updated는 데모를 이용하여 업데이트되지 않습니다.

 

알고리즘에서도 살펴보았듯이 코어 가중치를 이용해서 특정 가중치를 만들고, 특정 가중치를 이용해서 코어 가중치를 수정하는 2단계로 이루어져 있습니다. 

이렇게 구분하는 이유는 각 단계별 로스를 조금 더 명확히 구분함으로써 학습에 도움을 주기 위함으로 보입니다.

 

이 개념으로 접근하여 로스 함수를 다시 정의할 수 있습니다.

 

본 논문의 수식.3

y는 가장 마지막의 hidden layer의 출력이며, W는 output layer의 가중치, b는 bias입니다.

사실 로스함수까지만 보면 이전의 로스 함수를 풀어썼다고 볼 수 있습니다.

이를 통해 모델의 목적 함수도 새로이 정의될 수 있습니다.

본 논문의 수식.4

눈여겨 볼 점은 목적 함수가 코어 가중치 세타만을 찾는 것이 아니라 로스를 줄여줄 최종 레이어의 적절한 W, b 값 또한 찾습니다.

 

 

<Learning to Imitate without Expert Actions>

위의 로스함수를 보시면 데모는 지금까지 액션과 스테이트의 페어가 저장되어 있는 것으로 했었습니다.

하지만 visual demo를 통해 task를 배우기 위해서는 위 사항들이 없다고 봐야합니다.

학습 과정에서는 액션이 있다고 해서 그대로 사용할 수 있습니다.

그렇다면 test 시에 1단계, 특정 가중치를 로스를 이용해 찾을 때 어떻게 로스를 계산할 수 있을까요?

 

본 논문의 수식.

본 논문에서는 위 식, 단순히 기존 로스 함수에서 액션 a를 식에서 제거한 식을 사용합니다.

이렇게 할 수 있는 이유는 위에서 W, b가 포함된 마지막 레이어가 로스 함수를 meta-learn하기 때문이라고 합니다. 

 


* pre-updated post-updated 의미를 정확히 파악하지 못했습니다.

 

5. Model Architectures for Meta-Imitation Learning

 

 

Two-Head Architecture에 대한 그림, 본 논문의 Fig.2

policy network로 CNN 구조를 사용했습니다.

모델에게 들어오는 입력은 카메라로부터의 영상과 로봇의 현재 configuration입니다.

아래는 대략적인 순서도입니다.

1) 영상으로부터 feature를 추출합니다.

2) image feature와 robot configuration을 concat합니다.

3) FC layer를 통해 결과(액션)를 출력합니다.

 

이 모델은 추가적으로 bias transformation이라는 입력과 상관없는 상수 벡터를 사용합니다.

이는 간단히 소개하면, bias 역할을 해 줄 벡터를 입력에 concat하는 것입니다.

이를 통해서 좀 더 gradient의 표현력을 높일 수 있다고 합니다. (제 생각에는 Z로 인해 파라미터의 갯수가 늘어난 것 때문으로 보입니다.)

 


* 편향을 적극적으로 활용할 수 있다는 점은 좋은 아이디어인 거 같습니다.

 

6. Experiments

위 논문은 세 가지 환경에서 실험을 진행합니다.

각각의 환경에서 비교 대상이 될 모델은 아래와 같습니다.

1) random policy : 정규 분포에 따른 랜덤한 액션을 사용합니다.

2) contextual policy : feedforward policy로 task의 골을 가리키기 위한 데모의 최종 이미지와 현재의 이미지를 입력으로 주어 액션을 출력합니다.

3) LSTM : RNN으로, 데모와 현재의 observation을 주면 액션을 출력합니다.

4) LSTM+attention : attention 구조가 추가되었습니다.

 

<Simulated Reaching>

시뮬레이터 환경에서 3가지 색깔 중 특정 색깔에 닿아야 하는 task입니다.

 

<Simulated Pushing>

시뮬레이터 환경에서 특정 물체를 타겟 위치에 놓아야 하는 task입니다.

 

본 논문의 Fig.4

MIL은 본 논문에서 제안한 Meta Imitation Learning을 의미합니다. 

전체적인 성공률이 MIL이 높은 것을 확인할 수 있습니다. 

 

본 논문의 Table.1

데모가 어떠한 정보를 포함하는가에 따른 성능 비교 실험입니다.

LSTM은 순차적인 모델이기에 순차적인 액션 나열이 주어질 때는 나름 강력한 능력을 보여주지만, 액션이 데모 정보에서 빠져버리면 contextual보다도 낮은 성능을 보이는 점이 인상깊습니다.

이 실험 또한 MIL의 학습 능력을 보여줍니다.

 

 

<Real-World Placing>  

현 세계에서의 작업입니다.

특정한 물체를 특정한 받침대 위에 놓아야 합니다.

로봇이 테스트 시에 학습 시 나오지 않았던 unseen object에 대해서도 잘 작업을 수행할 수 있는지도 테스트할 수 있습니다.

본 논문의 Table.2

LSTM과 contextual 모델은 unseen 물체에 대해 굉장히 약한 모습을 보여주는 것에 반해 MIL은 90%라는 놀라운 성공률을 보여줍니다.

이는 어쩌면 1300개의 데모 훈련 데이터가 부족하여 그런 것일수도 있습니다.

이는 one-shot demo learning을 하기 위해 MIL이 필요한 데이터도 더 적다는 점을 보여줍니다.

 


* 실험 자체는 딱히 평범해보입니다. MIL의 성능이 굉장히 좋은 것 같습니다. 원리를 좀 더 이해하면 좋았을 거 같은데 아쉽네요.. 특히 Visual demo가 어떤식으로 반영이 되는건지에 대한 설명이 없는 것 같아 의문이네요..

원 논문은 여기서 확인하실 수 있습니다.

https://arxiv.org/abs/1805.04276

 

Leveraging Grammar and Reinforcement Learning for Neural Program Synthesis

Program synthesis is the task of automatically generating a program consistent with a specification. Recent years have seen proposal of a number of neural approaches for program synthesis, many of which adopt a sequence generation paradigm similar to neura

arxiv.org

 

Abstract

Program Synthesis는 specification에 맞는 프로그램을 자동적으로 생성하는 작업입니다. 

보통 이를 위해 LSTM을 이용하여 프로그램 토큰들을 순차적으로 출력하게끔 학습시키는 Seq2Seq 모델을 많이 사용하며, 학습을 위해서는 Maximum Likelihood Estimation(MLE)을 사용합니다.

하지만 이런 방법에는 두 가지 한계점이 있습니다.

 

1) Program Aliasing - 이루어진 토큰은 다르지만, 같은 내용을 의미하는 프로그램이 큰 로스로 다가올 수 있습니다.

 

같은 일을 하는 프로그램이지만 코드 구성은 다릅니다. 본 논문의 Fig.1

MLE를 사용한 supervised 학습은 이런 의미적인 부분을 무시하게 됩니다.

 

2) Strict Program Syntax  - 프로그램 토큰을 차례로 나열하는 Seq2Seq 모델은 프로그램의 문법적인 부분에 대해 캐치하지 못한 채로 잘못된 문법의 프로그램을 만들어낼 수 있습니다.

문법이 맞지 않는 프로그램은 실행시킬 수도 없고, 의미가 없기 때문에 이 점을 모델에게 어떤 식으로라도 도와줄 수 있다면 좋을 것입니다.

 

이 논문에서는 이 문제들에 대한 해결을 위해

1) 순수한 Supervised Learning이 아닌 강화 학습을 추가로 적용하여 학습시킵니다.

강화 학습의 리워드는 의미적으로 맞는 프로그램을 생성하였는가가 됩니다. 

2) 모델에 Syntax Check를 도와주는 추가적인 작업을 적용시킵니다.

LSTM의 Output으로 나오는 다음으로 나올 토큰들의 확률들에 대하여 Syntax가 맞지 않는 토큰의 확률은 없애서 올바른 문법의 프로그램을 출력할 수 있게 도와줍니다. 

 


Introduction

Program Synthesis는 Input-Output 예시라던지 하는 어떠한 specification에 대하여 그에 맞는 프로그램을 자동적으로 생성해내는 작업입니다.

이와 비슷한 작업인 Neural Program Induction 분야는 최근 굉장한 발전이 있었지만, 이는 명시적으로 해석이 가능한 프로그램을 생성하지 않습니다. (프로그램의 형식으로 작업을 하긴 하는데, 프로그램을 처음부터 끝까지 쫙 만드는 게 아니라 그때그때 환경에 필요한 프로그램을 호출하는 형식입니다. NPI가 이 분야에 속합니다.)

그 외에도 각각의 프로그램을 배우기 위해 많은 예시가 필요한다던지 하는 문제들이 있습니다.

이런 문제들에 대해 해결하기 위해 나온 방식이 Neural Program Synthesis입니다.

이는 5개 정도 되는 몇 개 안되는 예시(few examples)에 대해서도 Domain-Specific Language(DSL)를 통해 프로그램으로 표현을 해내는 것이 가능합니다.

 

하지만 이 모델도 두 가지의 한계점들이 있었습니다.

1) Program Aliasing

몇 개 안되는 예시로부터 프로그램을 만들기에 만들 수 있는 프로그램의 수는 굉장히 많습니다. 하지만 supervised 학습은 ground-truth 프로그램을 출력하게끔 하기 때문에 다른 가능한 프로그램들에 대해서는 높은 loss를 내게 됩니다.

가능한 어떤 프로그램이라도 만들 수 있게끔 하는 본래의 Program Synthesis 목적에 맞게끔 이 문제를 해결하기 위해 MLE를 대신하여 강화 학습을 접목할 것입니다.

2) Strict Program Syntax

프로그램은 엄격한 문법 구조를 지켜야 합니다. 하지만 단순한 seq2seq 모델로는 이 문법 구조를 알게 하기가 쉽지 않습니다.

이를 위해 본 모델을 도와줄 syntax checker를 추가적으로 사용하고, 이를 통해 pruning이 가능하게 합니다. 

 

위 방법들에 대한 효과를 검증하기 위해 Karel 환경에서 실험을 진행합니다.

Karel은 교육용 프로그래밍 언어로써 if 구절 같은 control flow를 포함하고 있고, 이는 program synthesis 작업을 좀 더 어렵게 합니다.

 

이 논문이 기여하는 바를 다시 한번 정리하면,

1) 순수한 supervised 학습에 비해 일반화된 프로그램 생성에서 좋은 성능을 보이는 강화 학습 방법을 제시합니다. 

2) syntax checker를 통한 탐색 공간의 축소화 방법을 제시합니다.

3) syntax checker가 없을 수 있기 때문에, 이를 위해 프로그램 생성과 더불어 자체적으로 syntax를 학습하는 모델 또한 소개합니다.

 


 

Problem Overview

<Program Synthesis Formulation>

 

본 논문의 exp.1

데이터셋은 위 수식으로 표현이 가능합니다. IO는 input/output 쌍을 나타냅니다. input과 output은 상태로 표현할 수 있습니다.

 

Karel example, 구글 검색

예를 들어 Karel에서는 각각의 격자 칸의 상태를 상태로 표현이 가능합니다.

람다는 프로그램을 나타냅니다.

즉, 프로그램 i에 대해서 k개의 Input/output 쌍이 존재한다고 설명이 가능합니다.

 

본 논문의 exp.2

위 논문에서 Program Synthesis 모델이 세타입니다.

k개의 IO가 주어질 때 그에 맞는 프로그램을 생성해내는 일을 하게 됩니다.

 

본 논문의 exp.3

테스트 셋은 spec과 test로 나누어지는데, spec은 모델의 입력으로 주어지는 IO이며, test는 모델이 출력한 프로그램을 실행하여 맞게 만들어졌는지 테스트하기 위한 IO입니다.

 

본 논문의 exp.4

즉 이 모델의 목표는 위 식으로 표현이 가능합니다.

테스트 데이터셋에 대하여 모델이 만들어낸 프로그램에게 input 상태에서 시작할 때 최종적으로 정답 output 상태가 나오게끔 만들면 됩니다.

 

<Neural Program Synthesis Architecture>

가장 기본적인 LSTM 기반의 seq2seq 모델로,

Input : Embedding(IO) + Embedding(이전의 토큰) 

Output : 다음으로 나오게 될 토큰들의 확률 (출력값이 추가적으로 softmax layer를 거칩니다) 

표현이 가능합니다. Karel의 상태에 대한 임베딩은 CNN을 활용하였습니다.

모델을 식으로 표현하면 아래와 같습니다.

본 논문의 exp.5

s는 토큰을 의미하고 L은 토큰의 길이를 의미합니다.

K개의 IO가 주어질 때 올바른 프로그램 세타를 예측하게 될 확률을 높이는 과정은 위 수식의 오른쪽으로 표현이 가능합니다.

 

테스트시에는 Beam Search를 활용하여 프로그램을 얻습니다.

program synthesis의 장점으로는 실행할 수 있는 프로그램을 만들어낸다는 점입니다.

실행을 통해 문법적으로 오류가 있거나 예시와 일치하지 않는 프로그램을 제거하며, 남아있는 프로그램들 중 가장 높은 확률의 프로그램을 모델에게 전달합니다.

 

모델 아키텍쳐, 본 논문의 Fig.2

Syntax checker까지 존재하는 모델의 전체적인 구조와 흐름을 설명드리겠습니다.

 

Input>

IO는 concat, CNN과 FC 레이어를 통해 임베딩 됩니다.

위 임베딩 벡터에 이전에 나온 토큰의 임베딩 값이 concat 되어 LSTM의 입력값으로 들어가게 됩니다.

IO는 변함이 없지만, 토큰 임베딩 값은 상황마다 변하게 됩니다.

각 프로그램마다 K개의 IO쌍이 있습니다.

각각의 IO쌍에 대해 각각의 LSTM을 입력으로 주게 됩니다.

 

Output>

K개의 LSTM으로부터 나온 값에 MaxPooling을 적용합니다.

이와 별개로 이전의 토큰을 Syntax checker에게 넣어 mask 벡터를 구합니다.

위 두 개의 벡터를 곱하고, 이에 softmax를 적용하여 최종적으로 다음에 나오게 될 토큰을 구하게 됩니다.

 


 

Objective Function

<Maximum Likelihood Optimization>

모델의 가중치(파라미터) 세타에 대해 supervised 학습을 적용한 기본적인 방법은 MLE입니다.

 

본 논문의 exp.6

MLE를 적용한 목적함수가 위 식이라고 할 수 있습니다.

하지만 위에서도 말했듯이, 위 식만을 이용하면 여러 문제가 생깁니다.

학습 과정에서 모델은 오로지 훈련 데이터에 대해서만 노출되지만, 테스트 과정에서는 자신이 출력한 토큰이 입력으로 들어오게 됩니다.

Natural Language Processing에서 이런 문제는 Exposure Bias라고 합니다. 

게다가 이 loss는 program synthesis의 진정한 목적이라고 할 수 없습니다.

MLE 학습 과정에서는 Program Aliasing 문제가 발생할 수 있기 때문입니다.

이 문제를 해결하기 위해 ground-truth 프로그램과 일치하지는 않더라도 맞는 프로그램에 대해서 loss 함수가 페널티를 주는 것을 막을 것입니다.

 

<Optimizing Expected Correctness>

Program Synthesis의 진정한 목적에 맞게 하기 위한 목적 함수의 첫 번째 수정은 아래와 같습니다. 

 

본 논문의 exp.7

R은 리워드 함수를 의미합니다.

리워드 함수는 여러 가지로 설정할 수 있습니다.

감마가 시그마 아래에 있는 건 만들어질 수 있는 프로그램이 강화 학습에서는 정말 다양하게 나올 수 있기 때문에 저렇게 표현한 것으로 보입니다.

 

하지만 위 식의 문제점은 너무 다양한 프로그램이 나올 수 있기 때문에 어떻게 기준을 잡아 계산하기 어렵다는 점입니다.

이 점을 해결하기 위해 몬테 카를로 방식을 사용하여 몇 개에 샘플에 대한 식으로 바꿀 수 있습니다.

 

본 논문의 exp.8

여기서 S는 샘플의 개수입니다. 

 

하지만 위 방식 또한 문제점을 찾을 수 있는데, 기울기를 추정하며 샘플을 뽑아낼 때 반복적으로 같은 프로그램을 만들어낼 확률이 높다는 점입니다.

이는 특히나 supervised 학습을 통해 pre-train 된 경우 도드라집니다.

이를 위해 살짝 다른 변경을 통해 학습을 도와줄 수 있습니다. 

 

 

Beam Search 적용 예시, 본 논문의 Fig.3

 

이 변화는 S 개의 샘플을 만들어낼 때 Beam Search에서 S개의 가장 높은 확률의 샘플을 뽑아내는 것입니다.

위 그림에서 S는 3이며, 각각의 타임 스텝마다 3개의 후보에 대해 Beam Search를 진행합니다.

BS(p세타, S)는 파라미터가 세타일 때 Beam Search를 통해 S개의 샘플을 뽑아낸 최종적인 결과를 의미하며, 초록색은 End Token을 의미합니다.

이렇게 나오게 된 S개의 프로그램은 확률 p를 가지고 있는데, 이 p를 softmax 비슷하게 적용하여 확률 q로 리스케일링 해줍니다.

이를 통해 중복적인 프로그램이 나오는 경우를 방지할 수 있습니다.

 

위 과정을 Exp.7과 비슷하게 표현이 가능합니다.

 

본 논문의 exp.9

전체 수식은 pq로 변경된 점뿐입니다.

하지만 Beam Search를 이용한 샘플링을 한다는 점이 추가되었습니다.

참고로 주의할 점은 S가 과도하게 커지게 되어 모든 생성될 만한 프로그램을 커버할 수 있게 되면 7번 수식과 다를 게 없다는 점입니다.

 

여기서 조금 더 다루기 쉽게 하기 위해 더 복잡한 목적 함수를 정의할 수 있습니다.

Program Synthesis에서 입력으로 들어온 Specification을 통해 몇몇 예측값들을 pruning 할 수 있습니다.

그러므로, 하나의 프로그램을 샘플링할 때 기대되는 reward 값을 최적화하는 것 이상으로 프로그램들의 묶음 C를 샘플링하고 최상의 프로그램을 유지할 때 기대되는 reward 값을 최적화하는 것을 선택할 수 있습니다.

 

본 논문의 exp.10

Reward 함수는 프로그램이 올바르냐에 따라 0, 1의 값을 줄 수 있고, 이를 이용해 식을 좀 더 쉽게 표현하면 아래와 같습니다.

 

 

본 논문의 exp.11

 * 10번과 11번 수식은 자세히 이해되진 않습니다. 설명해주신다면 감사하겠습니다..

 


 

Model

<Conditioning On the Syntax>

Program Synthesis 작업은 문법적으로 맞지 않는 프로그램을 만들어낼 수 있다는 측면이 있는데, 예측하기 전에 선별해 줄 수 있습니다. 

 

본 논문의 exp.12

stx는 문법적으로 맞는 프로그램이라는 걸 의미합니다.

이를 신경 써서 모델링한다는 점은 위 식처럼 표현할 수 있습니다.

이를 조금만 더 분해해서 생각하여, t번째 토큰을 예측하는 걸 식으로 표현하면 아래와 같습니다.

 

본 논문의 exp.13

실제 모델 구현에서는 일종의 Mask를 모델이 softmax를 통해 최종 아웃풋을 출력하기 전에 더해주게끔 하였습니다.

각각의 타임 스텝마다 토큰 벡터에 대해 Mask M= {-INF, 0}으로 표현할 수 있습니다.

-INF는 현재 문맥에서 문법적으로 불가능한 토큰에 부여됩니다.

 

이를 통해 문법적으로 정확한 프로그램만을 찾게 되므로, Beam Search에서 탐색 범위를 줄여 효율적인 탐색이 가능합니다.

이는 문제를 좀 더 단순하게 만들고 학습을 쉽게 만듭니다.

 

<Jointly Learned Syntax>

하지만 항상 Syntax Checker가 존재한다고 가정할 수는 없습니다.

또한 모델이 그저 학습만으로도 Syntax를 파악하게 된다면 일반적으로 쓰기 더 좋을 것입니다.

이를 위해 이 논문에서는 Syntax Checker를 뉴럴 네트워크 모듈(syntaxLSTM)로 만들고, 함께 학습을 시킵니다.

몇 가지 특징은 아래와 같습니다.

1) syntaxLSTM은 IO 쌍과 상관없이 오로지 프로그램 토큰들이 중요하기 때문에 IO는 입력으로 받지 않습니다.

이를 통해 문법의 학습에 집중할 수 있게 합니다.

2) syntaxLSTM으로부터 나오게 된 출력 값은 x -> -exp(x) 활성화 함수를 통과하여 decoder LSTM의 출력 값에 더해지게 됩니다.

위에서 설명한 Mask처럼 -exp 함수 또한 문법적으로 맞지 않는 토큰에 대해 페널티를 부과합니다.

 

syntaxLSTM의 추가는 모델 구조의 간단한 변경이기 때문에 학습의 절차를 바꿀 필요는 없습니다.

하지만, supervised 학습에서는 문법적으로 맞는 프로그램에게 갈 수 있게 해줘야 하기 때문에 MLE에 더해 추가적인 loss를 사용합니다.

 

본 논문의 exp.14

이 loss는 문법적으로 유효한 프로그램들을 통해 syntaxLSTM에게  올바른 문법을 학습시킬 수 있게 도와줍니다.

 


 

Experiments

<The Domain : KAREL>

KAREL은 그리드 월드에서 에이전트가 움직이거나(move, turn{Left, Right}), 환경을 바꾸면서({pick, put}Marker), 또한 환경으로부터 정보를 얻으며(markerPresent, noMarkerPresent, frontIsClear, leftIsClear, rightIsClear) 진행해나갈 수 있는 실험 환경입니다.

위 토큰들 말고도 control flow로 for, while, if를 지원합니다. 실험을 위해 서브루틴을 정의할 수 있는 기능은 사용하지 않았습니다.

 

DataSet>

실험을 위해 랜덤 DSL 프로그램 생성을 하였으며, 간단한 몇 가지 휴리스틱 체크를 통해 환경에 변화를 주지 않는 프로그램이나, 의미 없는 행동(turnLeft, turnRight를 이어서 하는 경우처럼)을 하는 프로그램은 사용하지 않았습니다.

각각의 프로그램에 대해 많은 IO쌍을 만들고, 적어도 프로그램에 존재하는 모든 IF를 한 번은 지나가도록 선별하여 6개의 IO 쌍을 가지게끔 하였습니다.

첫 5개의 샘플은 입력으로 주어지며, 6번째 샘플은 테스트를 위해 사용됩니다. 5000개의 프로그램을 나누어 validation set과 test set으로 사용되었습니다.

 

모델의 입출력>

KAREL의 상태는 각각의 그리드마다 16개로 나타내어질 수 있었습니다.

실험에서 그리드는 18 * 18 크기를 사용했고, 따라서 IO는 16 * 18 * 18의 형태를 띄었습니다.

IO는 각각 CNN에 들어가 feature를 추출한 후 Concatenation 한 뒤, 다시금 두 개의 CNN과 하나의 FC를 거쳐 512 크기의 벡터를 최종적으로 출력하게끔 하였습니다.

모델의 출력 값은 step마다 K개의 Decoder의 출력 값을 Maxpooling을 한 값을 이용하여 최종 출력에 사용하였습니다.

 

<Results>

Full Dataset : 100만 개의 프로그램 데이터셋입니다.

Small Dataset : 1만 개의 프로그램 데이터셋입니다.

데이터셋을 나눠서 실험하는 이유는 실 세계의 program synthesis domain에서는 수많은 데이터를 모으기 어렵기 때문입니다. 

 

본 논문의 Table.1

첫 번째 실험은 학습 방법을 통한 결과 비교 실험입니다.

 

모델>

MLE : 수식 6을 이용하는 방법이며, 평범한 supervised 학습 방식 모델입니다.

아래의 RL은 모두 reward로 프로그램이 모든 샘플과 일치하면 1, 아니면 0을 사용합니다.

RL : 수식 7과 8을 loss로 이용하는 방법입니다. (샘플링 적용한 강화 학습)

RL_beam : 수식 9를 loss로 이용하는 방법입니다. (샘플링에서 같은 샘플 뽑히는 문제 해결한 방법)

RL_beam_div : 수식 10을 loss로 이용합니다. (output이 좀 더 다양하게 나올 수 있도록 개량한 방법)

RL_beam_div_opt : 수식 10을 loss로 이용하지만, time step에 따라 추가적으로 reward에 페널티를 주는 방법을 사용하였습니다.

RL 관련 모델은 supervised 학습을 통해 먼저 pretrain 되었습니다.

보통의 Neural Machine Traslation 방법에서 보편적으로 사용되는 방식이기도 하고, 아무래도 순수 RL만으로 하기에는 성능이 좋지 못했다고 합니다.

이는 DSL을 통한 탐색 공간이 너무 넓어서 그런 것으로 생각됩니다.

 

평가지표>

Generalization : 만들어진 프로그램이 모든 IO에 대하여 정확하게 매치되는지 확인합니다.

Exact Match : 만들어진 프로그램이 ground-truth 프로그램과 정확하게 매치되는지 확인합니다.

 

분석>

Full dataset : RL을 이용하였을 때, Exact Match는 줄어들지만, Generalization은 좋아지고 있습니다.

이를 통해 RL을 이용하면 supervised의 한계였던 기존의 ground-truth 프로그램과 정확하게 일치하는 프로그램을 생성하던 비율이 줄어든다는 의미로 볼 수 있습니다.

즉, Program Aliasing 문제를 해결한다고 볼 수 있습니다. 이는 특히 RL_beam에서 두드러집니다.

Small dataset : MLE로만 학습을 진행시켰을 때보다 강화 학습을 추후에 추가로 진행하였을 때 성능이 두 가지 지표에서 모두 올라가는 것을 확인할 수 있습니다.

이를 통해 데이터가 적을 때 강화학습을 이용하여 데이터의 효율성을 높일 수 있다는 점을 확인할 수 있습니다.

 

 

본 논문의 Table.2

두 번째 실험은 Full dataset에서 각각의 모델로부터 생성된 Top-k개의 프로그램에 대한 Generalization 비교 실험입니다. 

 

분석 >

위 실험을 통해 알아낼 수 있는 점은 같은 일을 하더라도 다른 코드로 표현할 수 있는 능력을 본다고 생각합니다.

특히 이런 능력은 Program Synthesis에서 중요한 부분이라고 생각합니다.

Top-1과 Top-5에서 RL_beam_div_opt 모델의 성능이 가장 좋은 점을 확인할 수 있는데, 이는 Beam Search의 다양성을 높이면서, time step에 따른 reward의 조정으로 의미 없는 액션의 반복을 피했기 때문이라고 생각합니다.

개인적으로 의미 없는 액션의 반복을 계속하다, 이상한 길로 빠질 수도 있다고 생각합니다.

Top-50에 대해서는 MLE가 성능이 가장 좋은 점을 확인할 수 있는데, 이 부분에 대해서는 강화 학습은 MLE에 비해 넓은 범위를 탐색하기 때문에 최적의 프로그램은 더 잘 만들 수 있지만, 그런 만큼 넓은 범위에 대해 탐색하기 때문에 50개를 뽑을 때는 전체 성능은 낮을 수밖에 없다고 생각합니다. 

 

본 논문의 Table.3

세 번째 실험은 Syntax Checker 방식에 따른 성능의 차이 유무입니다.

 

모델>

MLE_learned : syntaxLSTM을 학습시키는 모델입니다.

MLE_handwritten : syntax 규칙을 알고 있는 syntax checker를 사용하는 모델입니다.

MLE_large : 추가적인 syntaxLSTM을 사용하지는 않지만 그만큼 파라미터 수를 추가해서 학습하는 모델입니다.

 

분석>

Full dataset : MLE가 MLE-learned보다 성능이 높은 점을 알 수 있습니다.

이는 충분한 데이터가 주어지면 모델이 따로 명시되어 있지 않아도 syntax에 대해 학습을 한다는 것으로 보입니다. 이에 대한 것은 MLE_large가 성능이 가장 좋은 점을 통해서도 알 수 있습니다.

Small dataset : 하지만 데이터셋이 충분하지 않을 때는 문법을 명시적으로 학습시키려 하는 MLE_learned 성능이 가장 좋았습니다.

특히 handwritten보다 성능이 좋은 점은 눈여겨볼 만 한데, 이 이유는 syntaxLSTM이 문법적으로 올바르지 못한 토큰을 거르는 것을 포함하여, 의미적으로 이상한 토큰마저도 거르는 걸 도와줄 수 있기 때문이라고 생각합니다.

다른 모델은 syntax를 자체적으로 학습하기에는 데이터가 충분하지 않은 점이 비교적 낮은 성능의 원인이라고 생각합니다. 

 

본 논문의 Table.4

네 번째 실험은 MLE_learned 모델이 full dataset에 대해 학습하였을 때 Top-k개에 대하여 문법적으로 맞는 프로그램을 만들어내는가를 확인하는 실험입니다. 

 

모델>

Joint Model : syntaxLSTM을 사용하여 프로그램을 생성하는 모델입니다.

Without Learned Syntax : syntaxLSTM으로부터 나온 mask를 사용하지 않는 모델입니다.

 

분석>

syntaxLSTM을 사용하지 않은 모델의 정확도가 급격하게 떨어진 점은 학습을 함에 있어서 syntaxLSTM에 의존하게 되었기 때문이라고 보입니다.

Joint Model을 보면 문법적으로는 거의 완벽한 프로그램들만을 생성하는 점을 볼 수 있습니다.

 

handWritten과 learned의 Mask 비교, 본 논문의 Fig.3

위 그림은 Fig1.a에 대해 handwritten model(Manual)과 learned model의 syntax mask에 대한 비교입니다.

하얀색은 문법적으로 가능한 토큰을 의미합니다.

(c)는 두 mask의 차이를 나타낸 것이며, 하얀색은 같고, 파란색은 learn이 문법적으로 틀린 토큰에 대해 가능하다고 판단한 부분이며, 빨간색은 문법적으로 가능한 토큰에 대해 불가능하다고 판단한 부분입니다.

빨간색이 세 번째 실험과 어느 정도 연관성이 있는, 가능하지만 의미적으로 이상하다고 학습된 부분으로 보입니다.

즉 syntaxLSTM이 문법 자체만 학습하는 것이 아닌 전체적인 토큰의 분포 또한 학습을 하는 것으로 이해할 수 있습니다.

 


 

Conclusion

이 논문은 현재의 최신 neural program synthesis에 있어 성능을 향상시킬 수 있는 두 가지의 새로운 기여를 하였습니다.

1) 출력되는 프로그램의 일반화를 위해 강화 학습을 사용하였습니다.

2) 추가적인 메커니즘으로 syntax check를 통해 탐색 공간을 줄였습니다. 이는 부족한 데이터셋에 대해서 눈에 띄는 성능 향상을 가져올 것입니다. (실험 3)

이번 글에서는 토큰 분석기, Lexer를 파이썬을 이용해 만들어 보는 내용을 담았습니다.

이 글은 https://riptutorial.com/en/python/example/31584을 참고하여 작성하였습니다.

 

Python Language - Part 1: Tokenizing Input with Lex | python Tutorial

python documentation: Part 1: Tokenizing Input with Lex

riptutorial.com


먼저 ply 모듈에 대한 설치가 필요합니다.

conda나 pip 명령어를 활용하여, ply 모듈을 다운로드하여 주세요.

다운로드가 잘 되어있는지 확인은

import ply.lex 를 통해 확인하실 수 있습니다.

 


Code

전체적인 코드입니다.

import ply.lex as lex

tokens = [  # 사용되는 토큰 정의하기, 필수
    'NUMBER',
    'PLUS',
    'MINUS',
    'TIMES',
    'DIVIDE',
    'LPAREN',
    'RPAREN',
]  # 토큰 별로 정규식이 정의되어야 한다 함수를 통해서 혹은 단순히 아래처럼, 둘 다 규칙은 t_이름

t_PLUS = r'\+'
t_MINUS = r'-'
t_TIMES = r'\*'
t_DIVIDE = r'/'
t_LPAREN = r'\('
t_RPAREN = r'\)'


# 값 변환 등 액션이 필요한 토큰은 함수로 정의한다.
def t_NUMBER(t):  # t가 인스턴스 토큰
    r'\d+'
    t.value = int(t.value)
    return t


def t_newline(t):
    r'\n+'
    t.lexer.lineno += len(t.value)


t_ignore = ' \t'


def t_error(t):
    print("Illegal character '%s'" % t.value[0])
    t.lexer.skip(1)


lexer = lex.lex()


while True:
    tok = lexer.token()
    if not tok:
        break  # No more input
    print(tok)

 

1) tokens 라는 리스트로 사용할 토큰들을 정의하는 과정이 필요합니다.

위 코드에서는 수식을 토큰들로 나누는 예제입니다.

 

2) 토큰들을 정의한 후, 각각의 토큰들이 어떤 형식으로 표현되는 토큰들인지를 정의해야 합니다.

어떤 토큰을 정의하는 것인지를 표현할 때는 < t_토큰 이름 > 형식으로 사용하시면 됩니다.

간단하게 정의를 할 때는 아래와 같이 정의할 수 있습니다. 표현은 정규식의 형태로 되어 있습니다.

t_PLUS = r'\+'
t_MINUS = r'-'
t_TIMES = r'\*'
t_DIVIDE = r'/'
t_LPAREN = r'\('
t_RPAREN = r'\)'

 

토큰을 표현하면서 추가적인 작업이 필요한 경우에는 함수로 구현할 수 있습니다.

def t_NUMBER(t):  # t가 인스턴스 토큰
    r'\d+'
    t.value = int(t.value)
    return t

함수 정의 맨 윗줄의 정규식이 토큰의 표현식이 됩니다. 이 함수의 매개변수로 들어오는 t는 인스턴스 토큰입니다. 위 같은 경우에는 숫자 자료형으로 변환시켜주기 위해서 함수로 정의를 했습니다.

 

t는 다음과 같은 속성값들을 가지고 있습니다.

1) t.type : 토큰의 타입을 의미합니다. 기본값으로는 t_ 전두어 다음으로 들어오는 이름입니다.

2) t.value : 실제 텍스트 값을 의미합니다.

3) t.lineno : 몇번째 줄인지를 표시하는 값인데, lexer 자체로는 라인을 알 수 없기 때문에 아래와 같은 함수를 정의하면 됩니다.

def t_newline(t):
      r'\n+'
      t.lexer.lineno += len(t.value)

4) t.lexpos : 들어오는 글의 시작부터 상대적인 위치를 나타냅니다.

 

 

만약에 무시하고 싶은 토큰이라면 아래 두 가지 방법 중 한 가지를 쓰면 됩니다.

def t_COMMENT(t):
       r'\#.*'
       pass
t_ignore_COMMENT = r'\#.*'

 

함수로 정의할 땐 반환값을 적지 않으면 됩니다. 혹은 < t_ignore_토큰 이름 > 으로 더 간편하게 정의할 수 있습니다. 딱히 토큰의 이름을 정의하지 않고도 무시하고 싶다면 < t_ignore > 로 정의할 수 있습니다.

 t_ignore  = ' \t'    # 스페이스와 탭을 무시하게 됩니다.

 

 

Literals : t.type 과 t.value가 문자 자체로 표현되는 토큰입니다. 

literals = [ '+', '-', '*', '/' ]
literals = "+-*/"

 

윗 줄과 아랫 줄은 같은 의미입니다. Literal 또한 함수로 정의하여 추가적인 작업을 하게끔 할 수 있습니다.  

 

literals = [ '{', '}' ]

def t_lbrace(t):
    r'\{'
    t.type = '{'  # 토큰 타입을 매칭되는 Literal로 설정합니다. (Literal이라면 꼭 필요합니다.)
    return t

 

에러는 t_error 함수로 다룰 수 있습니다. 

def t_error(t):
    print("옳지 않은 문자 '%s'" % t.value[0])
    t.lexer.skip(1) # 몇개의 문자를 넘어가는 함수입니다.

 

모든 준비가 끝나셨으면 lexer를 만드시면 됩니다.

lexer = lex.lex()

 

이런 지금까지의 준비 코드는 임의의 class 안에 정의하여 사용할 수도 있습니다. 

import ply.lex as lex  
 class MyLexer(object):            
       ...     # 위와 같은 내용들을 적습니다.

       # Build the lexer
       def build(self, **kwargs):
           self.lexer = lex.lex(module=self, **kwargs)

       def test(self, data):
           self.lexer.input(data)  # 데이터를 lexer에 넣는 함수입니다.
           for token in self.lexer.token():  # 토큰들을 확인할 수 있습니다.
               print(token)


 m = MyLexer()
 m.build() 
 m.test("3 + 4")  

 

추가적으로 반복문을 활용해서 분리해낸 토큰들을 얻을 수도 있습니다.

for i in lexer: 
    print(i)

 

 

다음 글로는 Lex와 연계되어 자주 사용되는 Yacc 모듈에 대해 알아보겠습니다.

 NAS라고 많이 불리는 모델을 소개하는 논문입니다.

 핫한 분야인 것 같아서 한번 리뷰를 해보려 합니다.

 논문은 2017년 ICLR에 기재되었습니다.

 

 Abstract

 이미지나 자연어 처리에 있어 뉴럴 네트워크는 강력하고 유연한 모델들입니다. 그럼에도 불구하고, 여전히 뉴럴 네트워크를 디자인하기란 여전히 어렵습니다. 이 논문에서는 뉴럴 네트워크의 모델을 만들어내는 RNN을 사용할 것이며, 이 RNN을 통해 만들어진 뉴럴 네트워크가 validation set에 예상되는 accuracy를 최대화하는 방향으로 강화학습을 진행할 것입니다.

 이 논문에서는 CIFAR-10 데이터에 대해 모델이 테스트를 진행하였을 때 3.65%의 에러율이 나왔는데, 이는 비슷한 구조를 사용했던 기존의 최신 모델보다 0.09퍼센트 나은 성능입니다. 거기에 1.05배 더 빠르다고 합니다.

 Pen Treebank(PTB) 데이터셋에 대해서, 이 모델은 다른 기존의 베이스라인들이나 널리 사용되는 LSTM cell을 능가하는 새로운 rnn cell을 만들어냈습니다. 

 이 rnn cell은 PTB 테스트 셋에 대해 62.4의 perplexity를 이루어냈습니다. 이는 이전의 최신 모델들보다 3.6 perplexity 나은 성능입니다. 이 cell은 또한 PTB에 대해 character language modeling task를 전달할 수 있으며, 1.214의 perplexity를 이루어냈습니다.


Introduction

 최근의 몇 년동안의 딥 뉴럴 네트워크의 발전으로 음성 인식이나 이미지 인식 등 많은 챌린지들이 성공하는 것은 기존의 feature design에서 architecuture design으로 패러다임을 변경시켰습니다. 비록 이전의 feature design보다는 쉬워졌지만, architecture design 또한 많은 지식과 시간이 요구되는 일입니다.

 

간단히 표현한 NAS 구조, 본 논문의 Fig.1

 이 논문은 좋은 architecture를 찾아주는 Neural Architecture Search(NAS)를 제시합니다. 이 논문은 뉴럴 네트워크의 구조를 가변 길이의 문자열로 표현할 수 있다는 관점에서 시작되었습니다. 이를 위해 NAS의 controller는 가변 길이의 문자열을 생성하기 위해 RNN 구조를 이용합니다. 문자열로부터 나오게 된 네트워크(child network)를 학습하면, validation set에 대해 accuracy가 나오게 됩니다. 이 accuracy를 강화학습에서의 reward의 관점으로 보아 controller의 policy를 업데이트하게 됩니다. 이를 통해 다음에 나오게 될 문자열로 표현된 네트워크가 높은 accuracy를 받을 확률을 높이게 됩니다. 

 


Methods

 아래에선 순서대로 다음에 대해 설명할 것입니다.

 1) cnn architecture를 rnn(controller)으로 생성하기 위한 방법

 2) rnn(controller)을 강화학습으로 훈련시키는 방법

 3) 모델의 복잡도와 훈련 시간을 줄이기 위한 몇몇 방법

 4) rnn architecture를 생성하기 위한 방법

 

<Generate model descriptions with a controller RNN>

 NAS에서는 controller가 뉴럴 네트워크의 구조적인 하이퍼 파라미터들을 생성하게끔 합니다. 유연성을 추가하기 위해 이는 RNN을 이용하여 구현되었습니다. 만약 convolutional layer로만 이루어진 뉴럴 네트워크를 생성한다고 가정해보면, 아래 그림과 같이 하이퍼 파라미터가 토큰들의 시퀀스로 생성되게끔 controller를 사용할 수 있습니다.

Controller의 출력 하나 하나가 architecture의 하이퍼 파라미터입니다. 본 논문의 Fig.2

 각각의 출력값들은 softmax를 통해 값을 정하게 되고, 이렇게 정해진 값은 다음 step에서의 input으로 들어가게 됩니다. 실험에서는 layer의 수가 특정 값을 초과하면 architecture 생성을 멈추게끔 하였습니다. 이 특정 값은 훈련이 진행됨에 따라 점차 늘려갑니다. RNN controller가 architecture 생성을 마쳤을 때, 이 architecture 기반의 child 모델이 생성되고 훈련을 실시합니다. 훈련이 끝나가 child 모델이 수렴하게 되었을 때 validation set에 대한 accuracy 값이 기록됩니다. RNN controller의 가중치는 생성한 architecture에게 기대되는 accuracy 값이 최대가 되도록 가중치를 업데이트합니다. 이 방법에 대해서는 아래 더 자세히 설명드리겠습니다.

 

<Training with reinforce> 

 chile network의 하이퍼 파라미터를 하나하나 예측하는 것 자체를 action이라고 볼 수 있습니다. 그러면 action들이 연속하여 나오게 된 것이 child network의 architecture이며, child가 최종적으로 내게 된 accuracy R이 데이터셋으로부터 나오게 됩니다. 이 R 값을 일종의 reward로 생각해서 RNN controller에 강화학습을 진행하게 됩니다. 좀 더 구체적으로, 최적의 architecture를 찾기 위해 controller에게 기대되는 reward를 최대화하게끔 합니다.

본 논문에서는 현재의 가중치에서 1부터 T까지의 액션 시퀀스 a가 주어졌을 때의 기대값 R을 왼쪽과 같이 표현합니다.

 

 이렇게 표현되는 R은 미분이 불가능하기 때문에, 지속적으로 가중치를 업데이트할 수 있는 policy gradient method가 필요합니다. 이 논문에서는 아래와 같은 식을 사용합니다.

  이는 아래의 식으로 추정될 수 있습니다.

 m : 한 번의 batch에서 controller가 만들어낸 architecture의 갯수

 T : architecture를 디자인하기 위해 controller가 생성한 하이퍼파라미터의 갯수

Rk : k번째 architecture의 accuracy

 

 하지만 위의 식은 분산이 굉장히 높습니다. 따라서 baseline을 추가한 아래의 식을 적용합니다.

 이 논문에서 baseline b 는 이전의 architecture들의 평균 accuracy를 이용하여 결정합니다. 

 

 추가적으로 학습을 빠르게 진행시키기 위하여 아래 방법을 사용했습니다.

 NAS에서 하나의 child network를 만든 뒤, accuracy 측정을 위해 이를 학습시키는 과정은 여러 시간이 소모됩니다. 따라서 controller의 학습 시간을 빠르게 하기 위해 분산 학습을 이용합니다. controller의 파라미터를 저장하는 파라미터 서버가 S개 존재하며, 이 서버들은 K개의 controller에게 파라미터를 보냅니다. 이를 통해 controller들은 m개의 architecture를 생성하고, 이를 병렬적으로 학습시켜 최종 gradient를 계산합니다. 그 뒤 이를 다시, 파라미터 서버에 보내며 업데이트 시킵니다. 이 과정을 정해진 값만큼의 epoch동안 반복합니다.

 

분산 학습의 구조, 본 논문의 Fig.3

 

<Increase architecture complexity with skip connections and other layer types>

 위에서 보았지만, controller의 탐색 공간은 skip connection 등의 최신 architecture에서 사용되는 기법들을 탐색하지는 못합니다. 이를 위해 탐색 공간을 넓힘으로써, controller가 이런 기법들에 대해서도 제안할 수 있게끔 하는 방법에 대해 소개하겠습니다. 

 

 skip connection 적용 방법 관련 그림, 본 논문의 Fig.4

 connection을 가능하게끔 하기 위해 set-selection attention을 사용합니다. 추가적으로 각 레이어에는 Anchor point가 생기게 됩니다. 현재의 레이어가 N일 때 1 ~ N-1 까지 이전의 레이어에서 연결할지 말지를 계산합니다. 계산식은 아래와 같습니다.

 vW는 학습해야 하는 벡터입니다.

 j의 범위는 1 ~ i - 1입니다.

위 식을 통해 j 레이어i 레이어에 연결이 될지 말지를 결정할 수 있습니다.  이를 적용해도 강화학습 방법은 별다른 수정 없이 그대로 사용이 가능합니다. 기존에는 무조건 순차적으로 연결되있던 모델만을 생성했다면, 이번엔 Anchor를 통해서만 레이어들이 연결되는 것으로 바뀌게 됩니다.

 다만 이런 connection을 추가하면 문제가 생길 수 있습니다. 예를 들어 하나의 레이어에 많은 레이어가 input으로 들어오게 될 때, 많은 레이어를 concatenation 하여 input으로 사용하게 되는데 이럴 때 차원 관련 문제가 생길 수 있습니다. 혹은 한 레이어에 input이 없는 경우가 있을 수도 있습니다. 이런 경우 컴파일 에러를 낼 수 있습니다. 따라서 이 논문에서는 세 가지 간단한 기술을 추가로 적용합니다.

1) 레이어에 input이 없는 경우 이미지를 input으로 넣습니다.

2) 최종 레이어는 output 레이어가 없는 모든 레이어를 연결합니다. 

3) 만약 인풋 레이어들끼리 다른 사이즈를 가지고 있다면, 작은 레이어는 제로 패딩을 적용하여 같은 사이즈로 만듭니다.

 

 위와는 다른 기술적 적용으로 learning rate 같은 파라미터에 대해서는 controller가 예측하지 못하는 제한적인 CNN 구조만 만들 수가 있었는데, 이런 것 또한 가능하게끔 할 수 있습니다. 그에 더해 pooling, normalization, batchnorm 등등을 추가하는 것 또한 가능하다고 합니다. 이를 위해서는 필요한 작업은 controller가 layer type을 출력하게끔 하면 됩니다.

 

 

<Generate recurrent cell architectures>

 

 위의 방식을 수정하여 RNN cell을 만들수도 있습니다. 기본적인 rnn 모델은 hidden state Ht를 입력값 X와 이전의 출력값 H(t-1)을 이용하여 계산합니다. 이를 수식으로 나타내면 아래와 같습니다.

 조금 더 복잡한 모델인 LSTM이 요즘엔 많이 쓰이기 때문에 이런 복잡한 모델을 생성하기 위해 어떻게 NAS를 사용해야 하는지 설명해드리겠습니다.

 

NAS의 RNN Cell 생성 과정 예시, 본 논문의 Fig.5

 하이퍼 파라미터들을 출력하는 점은 이전의 NAS와 비슷합니다만, 레이어별로 하이퍼파라미터를 출력하는 것이 아니라 필요한 연산들을 트리 구조로 나타내어 하이퍼 파라미터를 출력합니다. 위 그림에서 왼쪽의 트리는 기본적인 RNN의 틀을 만들어 준 트리입니다.

 각 트리의 노드마다 1) 계산 방법2) 활성화 함수NAS 모델이 출력하게 됩니다. 그런데 이 정도로는 복잡한 RNN 모델을 표현하기에 부족할 수 있기 때문에(LSTM 같은 경우에는 추가적으로 cell state를 활용) 추가적으로 cell inject와 cell indices 부분을 받습니다.

 cell inject는 cell state가 사용할 계산 방법과 활성화 함수를 출력하는 부분이며, cell indices는 각기의 cell state가 기존의 트리 노드에 끼어들 부분을 선택하는 부분입니다. 이를 통해 만들어진 rnn cell을 트리로 나타내면 왼쪽 그림이 됩니다. 이를 추가적으로 응용하면 좀 더 복잡한 모델 또한 만들 수 있을 것으로 보입니다.

 


Experiments and Results

 실험은 두 가지 데이터셋에서 진행됩니다. 첫 번째로는 CIFAR-10 데이터셋으로 이미지 인식에 대해 좋은 성능의 CNN 아키텍쳐를 찾기를 원하고, 두 번째로는 Penn Treebank 데이터셋으로 language modeling에 대해 좋은 성능의 RNN cell을 찾기를 원합니다. 

 

<Convolutional Architectures for CIFAR-10>

 

 데이터셋 : CIFAR-10 데이터셋에 전처리 과정과 augmentation 과정을 걸쳤습니다. 먼저 이미지들에 대해 whitening 과정을 걸치고 추가적으로 각각의 이미지들을 upsample 후 랜덤하게 32x32 크기로 잘랐습니다. 마지막으로, 이렇게 잘려진 32x32 이미지에 대해 랜덤한 horizontal flips를 사용했습니다. 

 

 Search space : 비선형 함수로 Relu를 사용하며 각 레이어마다 batch normalization과 skip connection이 존재합니다. 모든 convolutional 레이어에 대해, RNN controller는 filter의 height[1, 3, 5, 7]width[1, 3, 5, 7], 그리고 필터의 수[24, 36, 48, 64]를 선택합니다.

 stride에 대해서는 두 가지의 실험을 했습니다. 한 가지는 1로 고정시킨 것이며, 다른 건 controller가 [1, 2, 3]의 값 중 하나를 선택하게끔 하는 것입니다.

 

 Training details : RNN controller는 35개의 hidden unit을 가진 LSTM 레이어 두 개로 이루어집니다. 학습률은 0.0006으로 ADAM optimizer를 사용했으며, 균등하게 가중치를 -0.08과 0.08 사이의 값으로 초기화시켰습니다.

 학습은 위에서 설명드린 파라미터 서버를 이용하여 분산 환경에서 진행을 하였습니다. 파라미터 서버의 갯수는 20개이며, 컨트롤러의 갯수는 100개, 각 컨트롤러마다 child architecture는 8개를 만들었습니다. 즉 800개의 네트워크가 800개의 GPU를 통해 동시에 학습이 되는 방식이었습니다.

 각각의 child architecture는 만들어지면 50번의 epoch을 통해 학습을 진행하였습니다. 그 중 마지막 5 epoch 동안의 accuracy를 최대화하게끔 reward를 이용하여 파라미터를 업데이트했습니다. 

 validation set은 랜덤하게 5000개를 뽑았으며, 나머지 45000개는 훈련 데이터로 사용되었습니다.

 controller를 훈련시키는 동안, 점차 child network의 레이어 수를 늘려갔습니다. 이 실험에서는 6개의 레이어에서 시작하여 1600개의 child network마다 두 개의 레이어를 늘리게끔 진행되었습니다. 

 

 Results : controller가 12800개의 아키텍쳐에 대해 학습을 마친 후, 아키텍쳐가 가장 좋은 accuracy를 가지게 된다는 것을 발견했습니다. 그 뒤, 학습률, weight decay, batchnorm epsilon, epoch에 따른 학습률 감소 분야에 걸쳐 작은 범위에서 grid search를 진행하였고, 이를 통해 찾아낸 best model을 학습시킨 결과는 아래와 같습니다.

CIFAR-10 데이터셋에 대한 결과, 본 논문의 Table.1

 다른 기존 모델들과의 성능 비교가 함께 되어있는데, Error rate를 살펴보시면 기존에 가장 좋은 성능을 내던 Dense-Net과 어느 정도 비슷한 성능을 내는 것을 볼 수 있습니다. 이를 통해 NAS가 dataset에 대해서 잘 작동할 수 있는 아키텍쳐를 구축할 수 있다는 점이 증명되었다고 할 수 있습니다.

 표를 좀 더 살펴보시면 NAS에서도 추가적인 하이퍼파라미터나 레이어를 통해 성능을 높일 수 있다는 점이 눈에 띕니다. 그리고 v1의 경우에는 깊이가 15로 낮은 모델임에도 좋은 성능을 내고 있습니다. 그리고 또한 흥미로운 점은 v2와의 비교인데, strides를 예측하게 했더니 오히려 성능이 drop되었습니다. 이는 search space가 커지게 되어 controller 성능에 악영향을 끼친 것으로 파악이 됩니다.  

 v3의 경우는 13레이어와 24 레이어에 pooling layer를 추가하게끔 하는 모델로 controller는 39개의 레이어로 이루어진 모델을 만들었습니다. 성능 또한 4.47로 좀 더 좋아졌습니다. 여기서 search space를 줄이기 위해 controller가 만드는 레이어의 갯수를 13개로 줄이고, 그 대신 각 레이어마다 3개의 dense 레이어를 추가했습니다. 추가적으로 여기서 controller가 예측하는 필터의 갯수 범위를 [24, 36, 48, 64]에서 [6, 12, 24, 36] 로 변경하였습니다. 그 대신 각 레이어마다 40개의 필터를 추가하였고 이를 통해 error rate가 3.65로 기존 Dense Net 모델을 뛰어넘는 결과가 나왔습니다. Dense-Net의 가장 좋은 모델인 3.46은 1x1 convolution을 사용해서 정확한 경쟁 대상이 아니라고 합니다. 따라서 기존에 성능이 가장 좋던 모델보다 더 좋은 모델을 NAS가 만들어낸 것입니다.

 

NAS가 찾은 CNN 아키텍쳐, 본 논문의 Appendix.1

 위 그림은 NAS가 찾아낸 CNN 아키텍쳐 중 하나입니다. skip connection이 다양하게 불규칙적으로 이루어지는 것을 확인할 수 있습니다.

 

 

<Learning recurrent cells for penn treebank>

 

 Dataset : Language modeling에서 벤치마크로 잘 알려진 Penn Treebank(PTB) 데이터셋을 이용합니다. 이 데이터셋에 대해서는 LSTM 모델이 뛰어난 경향을 보이며, 이를 향상시키는 것은 어렵습니다. PTB는 작은 데이터셋이기 때문에, 오버피팅을 피하기 위해 regularization 방법들이 필요하기에, Embedding dropout과 Recurrent dropout를 사용합니다. 이 방법을 input과 output Embedding에도 공유합니다.

 

 Search space : 위에서 설명했듯이 RNN 모델을 만들기 위해 차례로 각 트리의 노드별로 계산 방법과 활성화 함수를 순차적으로 출력하게 됩니다. 계산 방법은 [Add, Elem_mult(곱)], 활성화 함수는 [identity, tanh, sigmoid, relu] 중 하나를 선택합니다. 

 

 Training details : 위 CIFAR-10 학습 과정과 몇 개의 수정사항을 제외하곤 거의 비슷합니다. 

 1) RNN controller의 학습률은 0.0005로 CIFAR-10보다 조금 높습니다.

 2) 파라미터 서버의 갯수는 20, 컨트롤러의 갯수는 400개이며, child 아키텍쳐는 단 1개입니다. 즉 400개의 모델이 동시에 학습됩니다.

 3) 파라미터 서버의 파라미터의 업데이트는 10개의 기울기가 컨트롤러에 축적되었을 때 실행됩니다.   

 

 각각의 만들어진 child 모델은 35 epoch를 통해 훈련되었습니다. child 모델은 두 개의 레이어를 가지고 있습니다. 이 실험에서 controller는 오로지 RNN cell 구조를 예측하기 위해 다른 하이퍼 파라미터들은 고정한 상태입니다. reward 함수는 c / (validation perplexity)^2 이며, c는 상수로 80으로 설정했습니다.

 

 위 실험과 마찬가지로 가장 좋은 성능의 RNN cell이 발견되었을 때, 학습률이나 weight 초기화, dropout rate, decay epoch에 대해서 그리드 서치를 진행하였습니다.

 

 Results : 아래의 표는 PTB 데이터셋에 대한 각 모델들의 성능을 비교한 것입니다. 표에서 확인할 수 있는 NAS로 생성된 모델이 기존의 모델을 능가하는 것을 확인할 수 있습니다. perplexity 지표만으로도 좋은 것이 확인되지만, 속도 면에서도 기존 모델보다 빠르다는 점도 주목할 만 합니다. (Zilly 모델에 비해 NAS의 모델이 2배의 속도를 가진다고 합니다.)

 

Penn Treebank에 관한 실험 결과, 본 논문의 Table.2
NAS가 찾은 RNN cell 구조, 본 논문의 appendix.2

 

<Transfer learning results>

  이번에는 같은 데이터셋에 대해 다른 task인 character language modeling을 해보면서 모델의 일반화 능력에 대해서 알아보겠습니다. 실험 환경은 Ha et al. 논문과 비슷하게 구성을 하였고, 이 모델과 비교를 합니다. 

 비교 결과가 아래의 테이블에 나와 있습니다.  

 

PTB character modeling 에 대한 비교, 본 논문의 Table.3

  이 부분에 대해선 아직 이해가 부족해서 정리를 못하겠습니다..

 

 Conclusion

 이 논문은 RNN을 활용한 뉴럴 네트워크 아키텍쳐를 찾아내는 아이디어, NAS에 대해 소개합니다.

 RNN을 사용함으로써 아키텍쳐 구조에 대해 유연하게 대응할 수 있습니다. 

 이 방법을 통해 여러 분야의 챌린저에서 가장 좋은 성능의 모델들보다 좋은 성능을 내는 아키텍쳐를 구해냈습니다.

 이를 통해 다양한 분야에서 좋은 아키텍쳐 구조를 찾는 데 도움이 될 것으로 보입니다.

 

 개인 의견

 사실 요즘 인공지능 딥러닝 분야는 여러 다양한 복합적인 모듈들이 섞여서 하나의 지능적인 task를 해내는 걸 주로 하는 듯 한데, 위 NAS를 이용하려면 꽤 많은 변경과 아이디어가 필요할 것으로 보입니다. 그래도 RNN을 강화학습으로 학습시키는 부분이나, 신경망의 파라미터들의 시퀀스를 출력하게끔 한다는 점은 훌륭한 아이디어로 보입니다. 

 경기대 생활을 어언 4년가까이 하면서, 배가 고플때 새록새록 생각나는 집이 하나 있습니다.

 비록 타지에서 찾아올만큼의 맛집은 아니더라도, 저렴하게 든든히 뱃속을 채워주는 냥푼 부대찌개입니다.  

 이 날도 갑자기 끌려 주말에 혼자 찾아가게 되었습니다.

 

 

 먼저 저를 맞이해주는 계란후라이.

 이 곳은 음식이 나오길 기다리는 동안 신선한 계란을 인당 하나씩 주십니다.

 계란후라이 솜씨를 뽐내고 싶으신 분들은 친구들과 함께 가서 몸소 보여주세요.

 

이쁘게 굽고 싶었는데, 미안합니다

 계란이 다 구워갈 때쯤 준비되는 기본 반찬들.

 기본적인 반찬의 맛이 식당의 수준을 보여준다고 생각하는데, 이 집은 그런 기준에서 최고라고 생각합니다.

 기본 반찬은 아래처럼 3종류가 고정되어 나옵니다. 

 반찬은 셀프바에서 계속 가져다 먹을 수 있습니다.

 맛있어서 계속 왔다갔다 하시게 될 겁니다.

 

어묵볶음, 이 집의 베스트 기본 반찬
김치, 김치는 평범합니다만 없으면 뭔가 아쉬울 것 같습니다.
요상한 샐러드, 하지만 요상하게 입맛을 끌어당깁니다.

 저는 제육볶음 1인분과 부대찌개 1인분을 시켰습니다. 사장님께서 "혼자서요?" 라고 물어보셨지만...

 둘 중 무엇도 포기하기 싫었습니다.

 19년 10월 기준 두 메뉴 모두 1인분 주문이 가능하고, 각 7000원씩 합니다.

 * 인당 1메뉴 주문 시 공기밥이 무한 리필입니다(중요)

 

 계란후라이와 반찬들로 밥을 이미 어느정도 해치운 상태에서 메인 요리가 나왔습니다.

 

제육볶음, 나오자마자 먹고 싶은 맘 참고 사진 찍느라 조금 흔들렸습니다.
부대찌개는 라면사리를 서비스로 주십니다. 라면사리가 쫄깃하게 익을 때까지 기다림이 필요합니다.

네, 혼자 먹기에 많긴 합니다. 점심으로 먹었는데 저녁까지 배가 땡땡 불러서 물마시기도 힘듭니다.

하지만 두 메뉴 중 하나만 골라서 먹기에는 너무 어려운 선택이기에, 맘 편하게 골랐습니다.

후회하지 않습니다. 살은 찌겠지만요. 

역시나 오늘도 대 만족입니다.

 

이 곳은 쿠폰제도를 운영하고 있습니다. 가격도 저렴한 편인데, 쿠폰까지 남는 게 있을 지 모르겠지만 일단 좋습니다.

친한 친구들과 후문에서 뭔가 먹기 애매할 때는 역시 이 곳이 최고인 것 같습니다. 

다음에도 또 가야겠습니다.

 


* 글쓴이와 식당과의 아무 이해관계 없이 주관적으로 작성된 글입니다.

* 저번 NPI 논문에서의 영감을 받은 모델 구조, NTP입니다. 바로 들어가겠습니다.

* 혹시 NPI에 대해 모르신다면 먼저 아래글을 읽어보시는 걸 추천드립니다.

  2019/10/01 - [AI/논문 리뷰] - [논문 리뷰] Neural Programmer-Interpreter

 

Abstract

 이 논문은 새로운 로봇 학습 프레임워크인 Neural Task Programming(NTP)를 제안합니다.

 Neural Program Induction과 few-shot demo learning 두 가지 분야를 합쳤습니다.

 NTP의 핵심 흐름은 아래와 같습니다.

본 논문의 Fig.1 (top)

 NTP는 입력으로 task specification(예를 들어 비디오 데모)을 받습니다. 이 task specification을 재귀적으로 분해하면서 sub-task의 task specification으로 나눕니다. 재귀적이라고 말했듯이 이는 반복됩니다.

 즉 비디오 데모라고 한다면, 전체 비디오를 부분부분 잘라서 sub task가 언젠가 최소의 Action이 될때까지 계속해서 분해하는 방식입니다. NTP 모델은 task specification을 보고 다음으로 실행해야 될 프로그램이 무엇인지 파악하고 호출합니다. 이 모델은 NPI와 닮았습니다. Compositional한 모델로 다음 프로그램을 호출할 때 새로운 NTP와 새로이 분해된 task specification을 입력으로 줍니다. 이 말은 아래에서 다시 설명드리겠습니다.

 NTP는 순차적인 task에서 강력한 일반화 능력을 가지고 있다고 합니다. 이 논문에서는 이를 증명하기 위해 3가지의 로봇 조작 task에서 실험을 진행합니다. 

 

본 논문의 Fig.1 (C)

 위 그림은 로봇 조작 task 중 하나인 Object Sorting task의 예시입니다. NTP는 이 환경에서 변화가 일어나 옮겨야 될 블록의 갯수가 많아지거나, 블록마다 할당된 바구니가 달라지거나 하는 unseen task에서도 강력한 일반화로 인해 잘 동작한다고 합니다.

 간단한 training 환경 코드는 이곳에서 확인하실 수 있습니다. stanfordvl.github.io/ntp/

 

Neural Task Programming: Learning to Generalize Across Hierarchical Tasks

Neural Task Programming

stanfordvl.github.io


Introduction

 이 논문이 제안하는 NTP는 계층적인 구조의 task들에 대해서 적용이 가능한 학습 알고리즘을 가지고 있습니다.

 

Task Variation 종류, 본 논문의 Fig.4

 NTP는 위 세 종류의 변화에 대해 일반화가 가능하다고 합니다.

 1) Semantics Variaitona - Goal의 변화입니다

 2) Topology Variation - Goal을 달성하기 위한 작업의 순서 변화입니다.

 3) Length Variation - Goal을 이루기 위해 해야할 일의 길이 변화입니다.

 이 세가지의 일반화가 가능한 것에 대해 이 논문에서는 일종의 meta-learning으로 보고 있습니다.

 

 이 논문이 전하는 바는 3가지로 정리하면 이렇습니다.

 1) 새로운 프레임워크 NTP - 계층적인 task에 대하여 meta-learning이 가능합니다

 2) NTP는 새로운 task(task 길이 변화, task goal 변화, task 순서 변화)에 대하여 강력한 일반화 능력으로 하나의 데모만으로 작업이 가능합니다.

 3) NTP가 visual input을 통해 end-to-end로 학습이 가능한 것을 증명합니다.


 

Neural Task Programming

NTP의 구조, 본 논문의 Fig.2

 위 그림에 나온 모듈들을 간단하게 설명해드리겠습니다.

 1) Observation Encoder : 현재 환경을 보고 feature를 출력하는 인코더입니다.

 2) Task Specification Interpreter : 현재의 상황과, 프로그램, 그리고 주어진 task_specification을 통해 5나 6의 일을 합니다.

 3) Task Specification Encoder : task specification에서 feature를 출력하는 인코더입니다.

 4) Core Network : 코어 네트워크로 LSTM 기반이 아닌, Reactive 기반의 네트워크를 사용한다고 합니다. 다음 프로그램과, 프로그램의 종료 확률을 출력으로 내게 됩니다.

 5) API Decoder : 다음에 실행할 프로그램이 Primitive한 API일 경우에 API를 위한 매개변수를 생성하는 Decoder입니다.

 6) Task Specification Selection : 다음 하위 프로그램에게 줄 task specification을 적절하게 선택하는 과정입니다. 여기서 나온 task specification이 다음 프로그램에게 주어지게 됩니다. 

 

 전체적인 흐름은 NPI와 많이 유사합니다. 차이점은 아래와 같습니다.

 1) NPI의 Primitive Action을 NTP는 Robot API를 사용합니다. 이는 task의 적용을 실제 환경같은 더 넓은 범위에 할 수 있게 합니다.

 2) NPI는 LSTM 기반의 코어 네트워크를 가졌습니다만, NTP은 Reactive 코어 네트워크를 사용한다고 합니다. 자세한 내용은 나와있지 않아 알 수가 없지만, 이를 통해 Error로부터의 회복에 더 강하다고 합니다. 이는 예외 상황이 발생하기 쉬운 로봇 환경에서 이점이 됩니다. 

 3) NPI는 다음 프로그램을 생성할 때 input으로 기존의 h state를 사용했지만, NTP는 적절한 task specification을 받습니다. 이를 통해 다양한 Task variation들에 대해서도 적절한 프로그램을 뽑을 수 있다고 합니다.

 

실제 NTP가 돌아가는 Flow, 본 논문의 Fig..3

 위 그림은 NTP가 돌아가는 흐름이라고 보실 수 있습니다. 맨 위의 영상들의 Sequence는 task specification을 의미하고 있습니다. 맨 처음 프로그램을 호출할 때는 빨간 색의 범위에 있는 task specification을 입력으로 넣습니다. 그 뒤 호출하게 될 프로그램에 대해서는 주황 색 범위의 task specification이 입력으로 들어가게 됩니다. 이런 식으로 하위 프로그램에게는 그 프로그램이 필요한 task specification을 제공하여, 필요한 정보만을 입력으로 줄 수 있습니다.

 

<Task Specification Scoping>

 그렇다면 과연 task specification을 적절하게 자르는 과정은 어떤 방식으로 이루어지는 걸까요?

 task specification은 time step마다의 값이라고 볼 수 있습니다.

 

 이렇게 나온 값마다 {'Start', 'End', 'Inside', 'Outside'} 확률을 구하기 위해 softmax를 적용합니다. inside와 outside 확률도 구하지만, 실전에서는 가장 높은 확률의 start와 end를 기준으로 자르는 것이 좋은 성능을 보여주었다고 합니다. 

 

 

 

 

 


Experiments

+ Recent posts