GANs in 50 lines of pytorch

이안 굿펠로우(Ian Goodfellow)의 GANs(Generative Adversarial Networks) 페이퍼를 파이토치로 구현한 블로그가 있어서 재현해 보았습니다.(제목과는 달리 전체 코드는 100줄이 넘습니다) 이 블로그에 있는 파이토치 소스는 랜덤하게 발생시킨 균등 분포를 정규 분포 데이터로 만들어 주는 생성기(G, Generator)와 생성기가 만든 데이터와 진짜 정규 분포를 감별하는 분류기(D, Discriminator)를 학습시키는 것입니다.

분류기에는 감별하려는 분포의 데이터 한 벌이 모두 들어가서 참, 거짓의 이진 판별을 내 놓습니다. 생성기는 한번에 하나의 데이터 포인트가 들어가서 출력값도 하나입니다. 원하는 분포를 얻기 위해서 생성기에 필요한 만큼 데이터를 계속 주입하면 됩니다. 행렬로 생각하면 분류기에는 하나의 행이 들어가고, 생성기에는 배치 효과를 위해 하나의 열 벡터가 들어갑니다.

그런데 기대한 것처럼 정규분포와 비슷한 생성기를 학습시키기가 어려웠습니다. 하이퍼파라미터 세팅에 많이 민감하여 종종 에러가 폭주하기도 했습니다. 그리고 학습이 되어도 정규분포의 모양을 가진다기 보다 평균과 표준편차만 같은 분포를 만들어 내었습니다. 즉 평균과 표준편차를 학습한 것 같은 모습니다(물론 이 코드는 결과보다 예시를 위한 것이라고 합니다만..). 그래서 생성기의 출력을 한번에 전체 분포를 얻을 수 있도록 마지막 레이어의 노드 수를 늘렸습니다. 이렇게 했더니 손쉽게 정규 분포와 비슷한 결과물을 얻었습니다만 생성기의 목적을 제대로 수행한 것인지는 확신이 서지 않네요. 🙂

전체 노트북은 깃허브에 있습니다. 코드의 중요 부분은 아래와 같습니다.

학습시키고자 하는 정규 분포는 평균이 4, 표준 편차가 1.25 입니다. 분류기는 입력 유닛이 100개이고 히든 유닛의 수는 50, 출력 노드는 하나입니다. 생성기는 100개의 입출력 유닛을 가지고 히든 유닛 수는 50개 입니다. 이 예제의 분류기, 생성기는 모두 각각 두 개의 히든 레이어를 가지고 있는데 두 개의 히든 레이어의 노드 수는 동일합니다.

data_mean = 4
data_stddev = 1.25

d_input_size = 100
d_hidden_size = 50
d_output_size = 1

g_input_size = 100
g_hidden_size = 50
g_output_size = 100

분류기와 생성기의 클래스 정의입니다.

class Discriminator(nn.Module):
    def __init__(self, input_size, hidden_size, output_size):
        super(Discriminator, self).__init__()
        self.map1 = nn.Linear(input_size, hidden_size)
        self.map2 = nn.Linear(hidden_size, hidden_size)
        self.map3 = nn.Linear(hidden_size, output_size)

    def forward(self, x):
        x = F.relu(self.map1(x))
        x = F.relu(self.map2(x))
        return F.sigmoid(self.map3(x))

class Generator(nn.Module):
    def __init__(self, input_size, hidden_size, output_size):
        super(Generator, self).__init__()
        self.map1 = nn.Linear(input_size, hidden_size)
        self.map2 = nn.Linear(hidden_size, hidden_size)
        self.map3 = nn.Linear(hidden_size, output_size)

    def forward(self, x):
        x = F.relu(self.map1(x))
        x = F.relu(self.map2(x))
        return self.map3(x)

렐루(ReLU)를 사용해서 레이어를 감싸고 분류기의 출력은 시그모이드로, 생성기의 출력은 마지막 레이어의 값을 그대로 뽑았습니다. 다음은 분류기와 생성기가 서로 학습하는 과정입니다.

for epoch in range(num_epochs):
    # 분류기와 생성기의 학습 횟수가 서로 다를 수 있습니다.
    for d_index in range(d_steps):
        D.zero_grad()  # 그래디언트를 비웁니다.
        real_data = Variable(real_sampler(d_input_size)) # 정규분포
        real_decision = D(real_data) # 정규분포 판별
        real_error = loss(real_decision, Variable(torch.ones(1))) # 무조건 참이어야 합니다
        real_error.backward() # 역전파

        fake_input = Variable(fake_sampler(g_input_size)) # 균등분포
        fake_data = G(fake_input) # 생성기가 정규분포로 변조시킵니다
        fake_decision = D(fake_data) # 가짜인지 구분해야 합니다
        fake_error = loss(fake_decision, Variable(torch.zeros(1))) # 무조건 거짓이어야 합니다
        fake_error.backward()  # 역전파
        d_optimizer.step()     # 분류기 파라미터 업데이트

    # 생성기 학습 차례
    for g_index in range(g_steps):
        G.zero_grad()  # 그래디언트를 비웁니다.
        fake_input = Variable(fake_sampler(g_input_size)) # 균등분포
        fake_data = G(fake_input) # 생성기가 정규분포로 변조합니다
        fake_decision = D(fake_data) # 가짜인지 구분합니다.
        fake_error = loss(fake_decision, Variable(torch.ones(1))) # 생성기 입장에서는 분류기가 참으로 속아야 합니다.
        fake_error.backward()  # 역전파
        g_optimizer.step()     # 생성기 파라미터 업데이트

이렇게 학습시키게 되면 초기에는 평균과 표준편차가 잠시 널뛰지만 반복이 어느 시점을 넘어서면 거의 변동이 없는 상태가 됩니다. 아래 그림에서 파란색이 평균, 붉은 색이 표준편차 입니다.

gan-pytorch-1

에러는 총 세가지로 분류기가 학습할 때 계산하는 정답 분포에 대한 에러(파란)와 가짜 분포(녹색)에 대한 에러, 그리고 생성기가 학습할 때 계산하는 가짜 분포에 대한 에러(적색) 입니다. 아래 그래프에서 볼 수 있듯이 세 에러가 거의 변동이 없이 일치하고 있습니다.

gan-pytorch-2

학습이 끝난 후 만들어진 생성기로 랜덤한 균등 분포를 입력해서 정규 분포로 바꾸어 보았습니다. 눈으로 볼 때에도 구분할 수 없을 만큼 비슷했습니다. 깃허브에 있는 노트북 코드원본 코드와는 조금 다르며 코드를 간소화하기 위해 람다 함수 등을 수정했습니다.

MILA DL Summer School

mila-dlss-2017

작년에 이어 올해에도 몬트리올 밀라(MILA)랩에서 주최하는 딥러닝 서머 스쿨이 6월 26일 부터 7월 4일 까지 열립니다. 이번에는 조금 더 확장되어 딥러닝 파트가 6/26~7/1, 강화학습 파트가 7/2~7/4 까지 열리며 두 세션을 각각 등록할 수 있도록 되어 있습니다. 올해 강좌도 녹화되어 공개될 것으로 예상됩니다. 그런데 작년 강의도 아직도 못봤다는 게 문제네요. 😦

TensorFlow v1.0.0 Release

텐서플로우 Dev Summit 에 맞추어 1.0 버전이 릴리즈되었습니다. 특별히 1.0 버전은 리서치 블로그에도 소개가 되었습니다. 텐서플로우 홈페이지에는 퍼포먼스 가이드 페이지가 새로 생성이 되었습니다.

맥, 리눅스, 윈도우 버전 모두 PyPI 에서 손쉽게 설치할 수 있습니다.(사실 코드는 며칠전에 이미 프리징된 것 같습니다. 릴리즈와 패키지 등록까지 서밋과 때를 맞추었네요:)

##### CPU 버전
$ sudo pip install --upgrade tensorflow

##### GPU 버전
$ sudo pip install --upgrade tensorflow_gpu

scikit-learn 개발자에게 물어봅시다!

지금 번역하고 있는 책(Introduction to Machine Learning with Python)의 저자 안드리아스 뮐러(Andreas Müller)는 사이킷런(scikit-learn)의 핵심 개발자로 사이킷런 개발과 운영에 모두 깊게 참여하고 있습니다. 또 앤디는 뉴욕대학교의 리서치 엔지니어였는데 올해부터는 콜롬비아 대학에서 머신 러닝 강의를 맡고도 있습니다.

책을 번역하면서 저자에게 직접 이메일 인터뷰를 할 기회를 얻었습니다. 머신 러닝과 사이킷런에 관한 것이라면 무엇이든지 보내 주세요! 재미있고 또 다른 독자에게도 유익한 질문이면 더 좋겠지요. 보내주신 질문을 정리해서 저자에게 보내겠습니다. 이 질문과 저자의 대답은 번역서에도 부록으로 실을 예정입니다. haesunrpark+sklearn at gmail.com 으로 보내 주셔도 되고 아래 입력 폼을 사용하셔도 됩니다!

  • Kwak ** 님: IncrementalPCA 처럼 LDA(Linear Discriminant Analysis)에 온라인 러닝을 할 수 있는 기능을 추가할 계획은 없나요?
  • Choi ** 님: 실전에서 Bagging 만으로 충분하기 때문에 Jackknife(Leave-one-out) 방식의 회귀 모델이 없는 것인가요?
  • piper 님: 딥러닝이 큰 붐을 일으키고 있습니다. 딥러닝(뉴럴 네트워크)외에 다른 지도학습 알고리즘을 사용했을 때의 장점은 무엇일까요? 딥러닝 엔지니어도 머신 러닝을 꼭 알아야 하는 지 궁금합니다.
  • lunrot 님: Hidden Markov Model 이 사이킷런 0.17 에서 제외된 이유는 무엇인가요? 혹시 다시 추가될 가능성은 없는지요?

Chainer, MXNet, CNTK, TF benchmarking

체이너(Chainer)는 일본에서 만들어져 널리 사용되는 딥러닝 프레임워크입니다. 지난 1월 샌프란시스코에서 열린 딥러닝 서밋을 통해 발표한 체이너의 분산버전의 체이너(Chainer Multi-Node)를 이용해 다른 프레임워크와 비교를 한 결과가 체이너 블로그에 올려졌습니다. 블로그에서도 언급했지만 이는 완벽하게 공정한 벤치마킹이 아닐 수 있습니다. 비교적 체이너가 실험 환경에 최적화되어 있고 다른 프레임워크는 그러지 못했을 수도 있습니다. 그렇더라도 GPU가 증가함에 따라 거의 선형적으로 퍼포먼스가 증가하는 그래프는 대단한 것 같습니다. 이 벤치마킹의 결과는 텐서플로우가 CNTK나 MXNet 과 비교해도 많이 성능이 뒤쳐진 것을 보여 줍니다.

dlsummit_06_framework-samples-per-second

체이너 멀티 노드 프레임워크는 Nvidia 의 니켈(NCCL) 라이브러리를 사용하여 GPU간 데이터 전송을 직접 처리합니다. MXNet과 CNTK가 단일 서버(4 코어까지는 단일 서버입니다)에서 조금 더 높은 성능을 내는 이유는 C++ 구현이기 때문이고 체이너는 파이썬 구현이라는 차이 때문으로 보고 있습니다. CNTK는 체이너 멀티노드처럼 니켈 라이브러리를 사용하지만 서버가 늘어남에 따라 MXNet과 성능 차이가 엇갈리고 있습니다. 텐서플로우가 느린 주된 요인으로는 분산 모드에서 파라미터 서버와 워커 서버간의 gRPC 통신의 오버헤드로 추측하고 있습니다. 스탠드얼론(standalone)일 경우엔 이와 다른 결과가 나올 수 있습니다. 이 벤치마킹에는 분산 기능이 내장되지 않은 씨아노(Theano)나 토치(Torch)는 포함되지 않았습니다.

최근에 나온 또 다른 벤치바킹 자료들에서도 텐서플로우의 성능은 그다지 뛰어나게 평가되지는 못하고 있습니다. 하나는 DyNet 의 페이퍼 ‘DyNet: The Dynamic Neural Network Toolkit‘ 이고 또 다른 하나는 ‘Benchmarking State-of-the-Art Deep Learning Software Tools‘ 입니다. 파이토치를 포함한 더 광범위한 벤치마킹이 진행되길 기대해 봅니다.

TensorFlow 1.0 RC2 Release & Keras 2

텐서플로우 1.0 RC2 버전이 릴리즈되었습니다. 다음주 텐서플로우 Dev Summit 위해 달리는 것 같습니다. 그리고 케라스(Keras)의 버전 2가 준비되고 있습니다. 케라스도 버전 2에서 API 변화가 있다고 합니다. 버전 1의 API 를 그대로 쓸 수 있지만 deprecated 경고가 뜨니 바꾸긴 해야할 것 같습니다. 그리고 마이크로 소프트의 CNTK도 케라스의 백엔드로 들어올 예정입니다.

또 프랑소와 숄레가 직접 예고한 대로 케라스가 텐서플로우 코드 베이스로 들어 갑니다. 다만 기존 케라스 깃허브는 그대로 유지되며 이로 인해 미치는 영향은 없을 것이라고 합니다. 텐서플로우로 들어간 케라스는 처음에는 tf.contrib 에 있다가 tf.keras 로 바뀔 것이라 합니다. 프랑소와가 케라스 코드를 4번째 재작성하고 있다는데 몇주만에 끝낼 모양입니다. @.@

텐서플로우 1.0 RC2 버전은 pip에 패키지 명을 직접 입력하여 설치할 수 있습니다.

##### 파이썬 2.7
# Ubuntu/Linux 64-bit, CPU only, Python 2.7
$ export TF_BINARY_URL=https://storage.googleapis.com/tensorflow/linux/cpu/tensorflow-1.0.0rc2-cp27-none-linux_x86_64.whl

# Ubuntu/Linux 64-bit, GPU enabled, Python 2.7
# Requires CUDA toolkit 8.0 and CuDNN v5.
$ export TF_BINARY_URL=https://storage.googleapis.com/tensorflow/linux/gpu/tensorflow_gpu-1.0.0rc2-cp27-none-linux_x86_64.whl

# Mac OS X, CPU only, Python 2.7:
$ export TF_BINARY_URL=https://storage.googleapis.com/tensorflow/mac/cpu/tensorflow-1.0.0rc2-py2-none-any.whl

# Mac OS X, GPU enabled, Python 2.7:
$ export TF_BINARY_URL=https://storage.googleapis.com/tensorflow/mac/gpu/tensorflow_gpu-1.0.0rc2-py2-none-any.whl

##### 파이썬 3.x
# Ubuntu/Linux 64-bit, CPU only, Python 3.3
$ export TF_BINARY_URL=https://storage.googleapis.com/tensorflow/linux/cpu/tensorflow-1.0.0rc2-cp33-cp33m-linux_x86_64.whl

# Ubuntu/Linux 64-bit, GPU enabled, Python 3.3
# Requires CUDA toolkit 8.0 and CuDNN v5.
$ export TF_BINARY_URL=https://storage.googleapis.com/tensorflow/linux/gpu/tensorflow_gpu-1.0.0rc2-cp33-cp33m-linux_x86_64.whl

# Ubuntu/Linux 64-bit, CPU only, Python 3.4
$ export TF_BINARY_URL=https://storage.googleapis.com/tensorflow/linux/cpu/tensorflow-1.0.0rc2-cp34-cp34m-linux_x86_64.whl

# Ubuntu/Linux 64-bit, GPU enabled, Python 3.4
# Requires CUDA toolkit 8.0 and CuDNN v5.
$ export TF_BINARY_URL=https://storage.googleapis.com/tensorflow/linux/gpu/tensorflow_gpu-1.0.0rc2-cp34-cp34m-linux_x86_64.whl

# Ubuntu/Linux 64-bit, CPU only, Python 3.5
$ export TF_BINARY_URL=https://storage.googleapis.com/tensorflow/linux/cpu/tensorflow-1.0.0rc2-cp35-cp35m-linux_x86_64.whl

# Ubuntu/Linux 64-bit, GPU enabled, Python 3.5
# Requires CUDA toolkit 8.0 and CuDNN v5.
$ export TF_BINARY_URL=https://storage.googleapis.com/tensorflow/linux/gpu/tensorflow_gpu-1.0.0rc2-cp35-cp35m-linux_x86_64.whl

# Ubuntu/Linux 64-bit, CPU only, Python 3.6
$ export TF_BINARY_URL=https://storage.googleapis.com/tensorflow/linux/cpu/tensorflow-1.0.0rc2-cp36-cp36m-linux_x86_64.whl

# Ubuntu/Linux 64-bit, GPU enabled, Python 3.6
# Requires CUDA toolkit 8.0 and CuDNN v5.
$ export TF_BINARY_URL=https://storage.googleapis.com/tensorflow/linux/gpu/tensorflow_gpu-1.0.0rc2-cp36-cp36m-linux_x86_64.whl

# Mac OS X, CPU only, Python 3.4 or 3.5:
$ export TF_BINARY_URL=https://storage.googleapis.com/tensorflow/mac/cpu/tensorflow-1.0.0rc2-py3-none-any.whl

# Mac OS X, GPU enabled, Python 3.4 or 3.5:
$ export TF_BINARY_URL=https://storage.googleapis.com/tensorflow/mac/gpu/tensorflow_gpu-1.0.0rc2-py3-none-any.whl

#### 설치
$ sudo pip install --upgrade $TF_BINARY_URL

윈도우즈 CPU:

C:\> pip install --upgrade https://storage.googleapis.com/tensorflow/windows/cpu/tensorflow-1.0.0rc2-cp35-cp35m-win_amd64.whl

윈도우즈 GPU:

C:\> pip install --upgrade https://storage.googleapis.com/tensorflow/windows/gpu/tensorflow_gpu-1.0.0rc2-cp35-cp35m-win_amd64.whl

DL for NLP by Oxford & DeepMind

지난달 말에 데미스 하사비스가 딥마인드에서 대학에 강의를 제공한다는 글을 블로그에 올렸었습니다. 이 때 언급한 강좌가 두개인데요. 하나는 유니버시티 칼리지 런던(UCL)의 ‘Advanced Topics in Machine Learning‘이고 다른 하나는 옥스포드 대학의 ‘Deep Learning for Natural Language Processing‘입니다. 이 중에 옥스포드 대학의 강의가 온라인으로 공개되고 있습니다! 이 강좌의 깃허브에 슬라이드와 함께 동영상 링크가 포함되어 있습니다. 그리고 이 강좌의 실습은 파이토치나 텐서플로우를 권장하고 있네요! 딥마인드는 여러 가지 방식으로 독일, 중국, 아프리카 등에 교육 지원을 할 것이라고 합니다. 우리나라에서는 꿈 같은 일이겠죠? 😎

(무슨 이유인지 제 맥북 크롬에서는 동영상 플레이가 되지 않고, 사파리 브라우저에서는 강좌 플레이가 잘 되었습니다. 참고하세요.)

TensorFlow Fold: DL With Dynamic Batching

image00

최근에 나온 동적인 계산 그래프(dynamic computation graph)를 만들어주는 DyNet이나 PyTorch와 같은 프레임워크에 대응하는 텐서플로우 폴드(TensorFlow Fold)가 오늘 구글 리서치 블로그를 통해 공개되었습니다. 텐서플로우 폴드는 텐서플로우에 동적인 배치(dynamic batching) 기능을 제공하기 위한 라이브러리입니다. 이미지에서 볼 수 있듯이 자연어 처리 등의 분야에서 서로 다른 길이의 배치 사이즈를 처리하기 위해 고안되었습니다. 텐서플로우 폴드의 소스 코드는 텐서플로우 레파지토리와 구분되어 있습니다.

그런데 레딧의 포스트를 보면 폴드에 대해 그다지 호의적이지 않은 것 같습니다. 다이넷이나 파이토치와 같은 동적 그래프 스타일에 대한 궁여지책 같아 보이고(텐서플로우 자체를 동적으로 만드는 것은 어렵다는 의견을 어디선가 읽은 것 같습니다), 특히 리서치 블로그에 다른 구현보다 10배에서 100배 빠르다고 언급한 것이 지적을 받고 있습니다. 텐서플로우 폴드(동적 배치)를 텐서플로우(정적 그래프)와 성능을 비교하는 것은 적절치 않다는 의견입니다. 그렇다고 파이토치와 같은 라이브러리와 비교하는 것도 곤란한 것 같습니다. 텐서플로우는 그래프 생성 속도가 느리다고 하니 파이토치 등과 비교해서 이득을 볼 게 없거든요. 🙂

현재는 리눅스용 바이너리만 제공하고 있습니다. 그리고 텐서플로우 폴드는 텐서플로우 1.0 이전 버전과는 호환되지 않습니다(API 변경 때문에). 따라서 폴드를 사용하려면 텐서플로우 1.0 rc0 이나 rc1 버전을 설치해야 합니다.

### python 2.7
pip install https://storage.googleapis.com/tensorflow_fold/tensorflow_fold-0.0.1-cp27-none-linux_x86_64.whl

### python 3
pip install https://storage.googleapis.com/tensorflow_fold/tensorflow_fold-0.0.1-py3-none-linux_x86_64.whl

YouTube-BB Datasets

image00

구글이 작년 가을에 공개한 YouTube-8M 데이터셋에 이어 이번에는 YouTube-BoundingBoxes 데이터셋을 공개하였습니다. 화면에 어떤 오브젝트가 있는지를 알아내는 것뿐만 아니라 오브젝트가 어디로 이동하고 있는지 시간에 따라 어떤 변화를 가지는지 연구하기 위한 데이터셋입니다. 무려 24만개 동영상에서 23개 오브젝트에 대해 백만개 이상의 사각 영역 좌표를 표시해 놓았습니다. 사람이 처리한 동영상 데이터셋으로는 최대라고 합니다. 브라우저로 데이터셋을 둘러 볼 수 있으며 동영상의 유투브 아이디와 오브젝트 좌표, 나타난 시간이 담겨 있는 훈련/검증 데이터를 다운받을 수 있습니다. 관련 페이퍼도 참고하세요. 그런데 다른 오브젝트는 그렇다쳐도 toilet 데이터는 왜 만든 걸까요? 🙂

TensorFlow Dev Summit 2017

tensorflow_devsummit-email-001

텐서플로우 Dev Summit이 다음 주로 다가 왔습니다. 전체 아젠다를 보면 텐서플로우 컴파일 XLA, 케라스(Kears), 분산 처리, 음악/미술에 접목 등 다양한 주제에 대해서 발표가 있을 예정입니다. 15일 오전9:30 분부터 열리며 우리 시각으로는 16일 오전 2시 30분 부터입니다. 아쉽게도 국내 구글 디벨로퍼 그룹(GDG)에서는 라이브 스트림 이벤트가 열리지는 않습니다만, 집에서 온라인으로 생중계를 볼 수 있고 다음날 녹화된 것을 볼 수도 있습니다. 🙂

(업데이트) GDG 서울에서 한주 뒤인 22일에 Dev Summit 의 내용을 정리해서 소개할 예정이라고 합니다. 섭외된 강사 분들이 Dev Summit 의 내용을 듣고 재 전달하는 방식이라 기대가 많이 됩니다. 자세한 소식이 생기면 다시 공유하겠습니다.

(2017.02.14) 22일에 열리는 GDG 서울의 텐서플로우 Dev Summit 참가 신청이 시작되었습니다. 조기 마감이 예상되니 관심있다면 서둘러야 할 것 같습니다.