Gluon으로구현해보는 한영기계번역 모형 – 마이크로소프트웨어 기고문

2월 초에 마이크로소프트웨어에 기고한 원고를 공개한다.

소스코드는 이곳에 공개되어 있다.  Gluon을 공부하면서 코드를 구성하고 모델이 동작 가능하게 하는데 주말 퇴근 후 여가시간을 활용해 약 1.5개월이 소요되었다. 그래도 1.5개월만에 이정도 동작 가능하게 한건  딥러닝 덕분이다.

원고를 청탁 받으면 항상 주제를 상향시켜서 진행하는 습관이 있는데, 신경망 기계번역글도 마찬가지였다. 아무 경험 없는 상태에서 시작해서 글을 마칠때까지 믿고 맡겨준 조병승 편집장에게 감사의 마음을 전한다.

공개된 글의 초반에 쓰여져 있지만 딥러닝은 해당 문제 영역의 도메인에 대한 진입 장벽을 획기적으로 줄여준 매우 위협적이지만 고마운 기술이다.  어떤 사람들은 위협이라 느낄것이고 어떤 사람들은 기회라 생각할 것이다. 이 글을 보시는 많은 분들이 기회라고 생각하길 바라며 원고를 공유해본다.

Gluon으로 만나는 영한기계번역_전희원

신경망 한영 번역기 코드 공개

딥러닝으로 구축한 한영 번역기 코드를 공개한다.

대부분 fixed length로 인코더 디코더를 구현하는 seq2seq 예제모형에서 좀더 나아가서 variable length를 인식해 학습이 되게끔 구현했다. 아마도 Gluon으로 해당 코드는 처음이지 않을까 한다.
모든 코드를 Symbol로 구현해 hybridize 모드로 학습이 될 수 있게끔 했고, 기본적으로 teacher forcing 방식으로 학습을 구성했다. 임베딩 학습도 다소 특이하게 한,영 단어를 모두 하나의 임베딩 매트릭스로 구성해 빠른 학습이 될 수 있도록 했다.

약 9만건의 학습셋은 기계번역기를 만들기 위한 학습셋으로 턱없이 부족하나, 어느정도 모형의 시작포인트는 만들었다고 자평하고 있다. 운이 좋아 수백만건의 학습 데이터를 확보할 수 있다면 좀더 발전시킬 수 있을 거라 예상한다.

이번 작업을 통해서 기계번역 모델링을 과거에 한번도 해보지 않았던 필자같은 사람도 딥러닝을 이용해서 한달여의 고군분투 끝에 만들어내게 하는 세상이 도래했다는데 개인적으로 큰 의미를 둔다. 딥러닝 덕분에 각 도메인 영역의 진입장벽이 낮아지고 있는건 어쩌면 기존 기술/경험을 가지고 있는 나같은 사람에게 불안감(본전생각)을 안겨줄 수 있으나 그런 생각 떨치고 항상 배우고 연마하는 자세로 살아야 된다고 생각한다.

번역 모형에 대한 코드레벨의 설명은 앞으로 출간될 마이크로소프트웨어에 수록하였으며, 출간 후 어느정도 시간이 지나면 블로그에 공개할 생각이다(항상 그래왔듯이…).  번역 모델링 한다고 몇주 주말동안 좋아하는 게임도 못하고 전기세만 축내면서 수도없이 GPU를 고문했는데 개인적으로도 상당히 좋은 경험이었다.

이정도 구현체라면 Keras에서 Gluon으로 넘어온 보람이 있다고 생각한다. 특히나 Attention 및 Variable Length 기반의 학습은 Keras로 구현하는건 상당한 난이도가 있는 작업이라는 생각을 해본다.

한달여 동안 퇴근 후 개발을 하면서 몇가지 경험적으로 얻은 부분을 정리하자면…

  1. 완성된 코드로부터 쓸만한 모형을 학습/도출하는데 전체 30% 이상의 리소스가 들어갔다.
  2. 실제 모델링 자체의 코드가 늘어나니 모델 개발이라는말이 과거처럼 학습 라이브러리에 정제된 속성/데이터만 넣는 작업과는 다른 차원의 의미로 다가온다. 이건 모델 알고리즘 개발인것이다.
  3. 이 다음부터는 양질의 데이터를 얼마나 많이 확보하느냐가 품질을 판가름할 것이다.
  4. 모델이 복잡해지니 모형에 대한 디버깅 경험/능력이 중요해진다. Tensor 기반의 코딩 능력에 대한 경험을 많이 쌓는것이 중요하다. 많이 고민하고 만들어보고 학습해보자!

 

 

 

 

MXNet 혹은 Gluon으로 모형을 개발할때 반드시 맞닥뜨릴 한가지 이슈

최근 한달 동안 Gluon으로 이런 저런 모형을 개발하면서 MXNet에 대해서도 어느정도 경험을 쌓았고, 이런 저런 상황을 맞닥들이면서 이슈 해결도 해왔다.

이 도구를 사용하면서 가장 황당했던 부분은 모델링 코드를 작성한 이후 막 학습을 하기 시작했을때 Python 프로세스 자체가 죽어버리는 경험이었다. 주로 주피터 노트북에서 작업을 하기 때문에 그러한 상황시 주피터 로그 메시지를 확인하곤 하는데 아래와 같은 메시지를 떨구며 프로세스가 주로 죽어버린다.

사실 MXNet 백엔드를 사용하면서 많은 분들이 이러한 경험을 할 수 있는데, 이는 MXNet 백엔드로 모형을 개발하는 방식에 대해서 익숙하지 않아서가 원인이다.

위에서 이야기하는것 처럼 MXNET_ENGINE_TYPE 환경 변수를 NaiveEngine으로 하여 상세한 로그를 보면 이슈를 확인할 수 있고 게다가 프로세스가 절대 죽지 않는다. 따라서 모형을 개발할 당시엔 반드 시 NaiveEngine으로 진행해야 황당한 경우를 피할 수 있고 디버깅을 하기 쉬워진다. 아무것도 지정하지 않으면 GPU마다 별도의 스레드풀을 생성하는 ThreadedEnginePerDevice 모드로 동작하게 되며 갑작스런 메모리 사용량 증가 등 여러 이슈에 프로세스가 죽어버리는 현상을 일으키게 된다.

결국 MXNet백엔드로 모형을 개발하는 방식은 아래와 같다.

  1. NaiveEngine으로 설정해서 코드를 구현한다.
  2. 1에폭 정도 테스트하면서 별도의 에러가 나지 않으면  ThreadedEnginePerDevice 로 변경해 학습을 계속 진행한다.

위와 같은 과정으로 모형을 개발하면서 갑작스럽게 프로세스가 죽는 현상을 겪지 않았다. 혹자는  NaiveEngine으로 개발하고 학습하면 안되는지 생각할 수 있는데, NaiveEngine은 일종의 디버깅 모드로 동작해 상당히 느린 학습 속도를 보인다. 특히나 멀티 GPU에서 동작할때 1개의 GPU를 사용할때와 같은 마법과 같은 효과를 보여준다.