태그 보관물: PyTorch

PyTorch v0.1.12

파이토치PyTorch의 0.1.12 버전이 릴리즈되었습니다. 이 버전은 0.1.x의 마지막 버전으로 알려져 있습니다. 넘파이NumPy 스타일을 따르도록 API 가 조금 변경되었고 CUDA의 희박행렬 연산 지원이 추가되었습니다. 그 외에 성능향상과 버그들이 많이 수정되었다고 합니다. 다음 버전은 0.2 버전으로 분산 처리와 그래디언트의 그래디언트를 계산하는 기능이 추가될 예정입니다.

때맞춰 텐서플로우 성능 테스트 자료가 공개되었습니다. 이는 얼마전 발표된 Caffe2성능 자료에 대한 반격으로 보입니다. NVidia DGX-1 에서 테스트한 결과를 보면 카페2와 텐서플로우가 앞서거니 뒤서거니 합니다. 하지만 여전히 초당 훈련 이미지 처리수가 중요한 성능지표인지에 대해서는 논란의 여지가 있습니다. 여기에 사용된 텐서플로우 벤치마크를 위한 코드는 상당히 최적화시킨 것 같습니다.

perf_summary_p100_single_server

18-caffe2-chart

파이토치를 설치하려면 리눅스와 맥OS에서 콘다 명령을 사용할 수 있습니다. 맥OS에서 CUDA 지원을 사용하려면 소스 컴파일을 해야합니다. 아직 윈도우즈 환경은 지원하지 않고 있습니다.

conda install pytorch torchvision -c soumith

Caffe2: Mobile first DL Framework

스크린샷 2017-04-19 오후 4.57.55

페이스북이 딥러닝 프레임워크 카페(Caffe)의 새로운 포크인 카페2(Caffe2)를 오늘 공개하였습니다. 카페2는 페이스북과 NVidia를 비롯해 많은 회사들과 협력한 결과라고 합니다. 특별히 NVidia에서도 블로그를 통해 카페2 소식을 알렸습니다. 카페를 개발한 양칭 지아Yangqing Jia가 버클리를 나와서 구글 브레인으로 갔었는데 어느새 페이스북으로 옮겼군요. 이미 작년에 카페2의 개발 소식이 흘러나왔던 것 같습니다. 카페2는 파이토치와는 다르게 모바일과 대용량 스케일의 상용 제품을 위한 프레임워크로 촛점을 맞추고 있다고 합니다. 그렇다고 파이토치와 명확하게 선을 그을 수는 없지만, 파이토치 보다는 더 성능과 다양한 디바이스 포팅에 중점을 두고 있습니다. 파이토치는 연구자들이 다양한 네트워크를 실험할 수 있는 높은 자유도가 장점입니다. 하지만 카페2와 파이토치의 저수준 라이브러리들은 앞으로 계속 머지되거나 아이디어를 공유할 것 같습니다. 바이두가 텐서플로우의 패치를 보냈는데 구글이 이를 거부했다는 소식에서 부터 구글이 사용하는 텐서플로우와 오픈소스 텐서플로우에는 차이가 있다는 것이 카페2와 함께 레딧해커뉴스에서 회자되고 있습니다.

현재 카페2가 안정화된 상태는 아닙니다. 양칭에 의하면 페이스북이 먼저 개밥먹기를 하고 있답니다. 파이썬 바이너리 패키지가 준비되어 있지 않아 설치도 번거롭습니다. 하지만 카페의 Model zoo를 이용할 수 있다는 것과 모바일 퍼스트 정책은 많은 사람들의 관심을 끌것 같습니다. OpenCL와 iOS의 Metal을 지원하려고 준비 중에 있다고 합니다.

누가 Caffe가 죽었다고 했던가요? 🙂

(업데이트) 구글 브레인의 리더 Rajat Monga 가 바로 댓글로 의견을 냈네요. 구글이 텐서플로우에 대해 감추고 있는 것은 없답니다.

또 페이스북에서 F8 행상 이후에 몇몇 대학 교수를 초빙해서 카페2에 대한 워크샵을 열 예정이라고 밝혔습니다. 이미 많은 대학의 딥러닝 커리큘럼이 텐서플로우로 가고 있어서 더 늦기전에 변화가 필요하다고 생각했을 것 같습니다.

PyTorch v0.1.11 Release

파이토치 0.1.11 버전이 릴리즈 되었습니다. 텐서플로우와 케라스와 일관되게 하려고 Adamax 옵티마이저의 기본 파라미터 값이 변경되었습니다(lr=2e-3, eps=1e-8). 또 CuDNN v6 지원과 성능 향상 이외에도 많은 기능이 추가되고 버그가 수정되었습니다. 자세한 내용은 릴리즈 노트를 참고하세요.

아나콘다를 사용하면 맥과 리눅스에서 파이토치를 쉽게 설치할 수 있습니다. 맥OS에서 CUDA 지원을 사용하려면 소스 컴파일을 해야합니다. 아직 윈도우즈 환경은 지원하지 않고 있습니다.

conda install pytorch torchvision -c soumith

DiscoGAN [1703.05192]

SKT T-Brain 팀의 첫 페이퍼 “Learning to Discover Cross-Domain Relations with Generative Adversarial Networks”(DiscoGAN, 1703.05192) 공개되었습니다. DiscoGAN은 한 종류의 이미지에서 학습하여 비슷한 스타일의 다른 종류의 이미지를 생성해 줍니다. T-Brain 페이스북 페이지에서 친절하게 자세히 설명하고 있습니다. DiscoGAN은 파이토치(!)로 구현되어 있으며 깃허브에 공개되어 있습니다. 하지만 번개같은 속도로 데브시스타즈의 김태훈님이 더 깔금하게 파이토치 구현을 만들었습니다. 이외에도 두 개의 체이너 구현(1, 2)도 만들어졌습니다.

Visdom: Visualization for ML & DL

visidom2

페이스북에서 Torch, PyTorch, NumPy 를 위한 시각화 도구인 Visdom을 오픈소스로 공개했습니다. 자연스럽게 이는 텐서플로우의 텐서보드TensorBoard의 대항마일 것으로 여겨집니다. 비즈돔은 토치용 시각화 서버인 display에 영감을 받았다고 합니다. 비즈돔은 웹브라우저로 사용할 수 있으며 웹서버는 오래전 페이스북이 인수한 프렌드피드FriendFeed가 만든 토네이도Tornado를 사용하고 있고 실제적인 그래픽 처리는 plotly.js를 이용합니다. API 를 봐서는 계산 그래프를 시각화시키는 도구는 아닌 것으로 보입니다. 하지만 앞으로 어떤 기능이 추가될지 기대가 됩니다.

PyTorch v0.1.10 Release

파이토치 0.1.10 버전이 릴리즈 되었습니다. 이번 버전에서는 텐서의 인덱싱과 브로드캐스팅 기능이 많이 추가 되었고 가변길이variable-length RNNs, 희박 텐서sparse tensor도 추가 되었습니다. 또한 CPU 기반의 연산이 2~10배 가량 빨라져서 NumPy에 근접한 성능을 낸다고 합니다. 😀

0.1.10 버전 부터는 리눅스와 맥OS에서 콘다 명령을 사용해 pytorch, torchvision을 모두 설치할 수 있습니다. 맥OS에서 CUDA 지원을 사용하려면 소스 컴파일을 해야합니다. 아직 윈도우즈 환경은 지원하지 않고 있습니다.

conda install pytorch torchvision -c soumith

PyTorch 0.1.9 Release

파이토치(PyTorch) 0.1.9 버전이 릴리즈 되었습니다. 이 버전에서는 주로 버그가 수정되었으며 기능상에 큰 변화는 없습니다. 아나콘다를 사용하면 파이토치 바이너리를 편하게 설치할 수 있습니다.

### conda (linux, osx)
$ conda install pytorch torchvision -c soumith

### pip
# linux: python2.7 + cuda7.5
$ pip install https://s3.amazonaws.com/pytorch/whl/cu75/torch-0.1.9.post1-cp27-none-linux_x86_64.whl

# linux: python2.7 + cuda8.0
$ pip install https://s3.amazonaws.com/pytorch/whl/cu80/torch-0.1.9.post1-cp27-none-linux_x86_64.whl

# linux: python3.5 + cuda7.5
$ pip install https://s3.amazonaws.com/pytorch/whl/cu75/torch-0.1.9.post1-cp35-cp35m-linux_x86_64.whl

# linux: python3.5 + cuda8.0
$ pip install https://s3.amazonaws.com/pytorch/whl/cu80/torch-0.1.9.post1-cp35-cp35m-linux_x86_64.whl

# linux: python3.6 + cuda7.5
$ pip install https://s3.amazonaws.com/pytorch/whl/cu75/torch-0.1.9.post1-cp36-cp36m-linux_x86_64.whl

# linux: python3.6 + cuda8.0
$ pip install https://s3.amazonaws.com/pytorch/whl/cu80/torch-0.1.9.post1-cp36-cp36m-linux_x86_64.whl

# osx: python2.7
$ pip install https://s3.amazonaws.com/pytorch/whl/torch-0.1.9.post1-cp27-none-macosx_10_7_x86_64.whl

# osx: python3.5
$ pip install https://s3.amazonaws.com/pytorch/whl/torch-0.1.9.post1-cp35-cp35m-macosx_10_6_x86_64.whl

# osx: python3.6
$ pip install https://s3.amazonaws.com/pytorch/whl/torch-0.1.9.post1-cp36-cp36m-macosx_10_6_x86_64.whl

### torchvision
$ pip install torchvision

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

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

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

PyTorch 0.1.8 Release

페이스북의 파이토치(PyTorch) 버전이 빠르게 올라가고 있습니다. 지난번 포스팅 이후 두번의 릴리즈가 더 있었습니다. 0.1.7 버전에는 텐서플로우에는 없는 LBFGS 알고리즘이 추가 되었고 0.1.8 버전에는 분산 처리를 위한 THD 라이브러리가 추가 되었습니다. 콘다를 사용하면 파이토치 바이너리를 편하게 설치할 수 있습니다.

### conda (linux, osx)
$ conda install pytorch torchvision -c soumith

### pip
# linux: python2.7 + cuda7.5
$ pip install https://s3.amazonaws.com/pytorch/whl/cu75/torch-0.1.8.post1-cp27-none-linux_x86_64.whl

# linux: python2.7 + cuda8.0
$ pip install https://s3.amazonaws.com/pytorch/whl/cu80/torch-0.1.8.post1-cp27-none-linux_x86_64.whl

# linux: python3.5 + cuda7.5
$ pip install https://s3.amazonaws.com/pytorch/whl/cu75/torch-0.1.8.post1-cp35-cp35m-linux_x86_64.whl

# linux: python3.5 + cuda8.0
$ pip install https://s3.amazonaws.com/pytorch/whl/cu80/torch-0.1.8.post1-cp35-cp35m-linux_x86_64.whl

# linux: python3.6 + cuda7.5
$ pip install https://s3.amazonaws.com/pytorch/whl/cu75/torch-0.1.8.post1-cp36-cp36m-linux_x86_64.whl

# linux: python3.6 + cuda8.0
$ pip install https://s3.amazonaws.com/pytorch/whl/cu80/torch-0.1.8.post1-cp36-cp36m-linux_x86_64.whl

# osx: python2.7
$ pip install https://s3.amazonaws.com/pytorch/whl/torch-0.1.8.post1-cp27-none-macosx_10_7_x86_64.whl

# osx: python3.5
$ pip install https://s3.amazonaws.com/pytorch/whl/torch-0.1.8.post1-cp35-cp35m-macosx_10_6_x86_64.whl

# osx: python3.6
$ pip install https://s3.amazonaws.com/pytorch/whl/torch-0.1.8.post1-cp36-cp36m-macosx_10_6_x86_64.whl

### torchvision
$ pip install torchvision