PyTorch는 MNIST 연구에 많은 업적을 남긴 LeCun이 현재 AI 연구그룹 리더로 활동 중인 Facebook에서 오픈소스로 제공하는 머신 러닝 지원 언어로서 오래 전에 나온 TensorFlow 보다 성능이 뛰어나다는 소문이 있다. LeCun 이 1990년대부터 CNN의 선구자였다는 사실을 알면 그가 활동하는 공간에서 생성된 PyTorch 도 뭔가를 보여 줄 수 있는 소프트웨어 일 것으로 기대된다.
요즈음의 머신 러닝 소프트웨어는 보다 큰 데이터를 신속하게 처리하기 위해서 GPU를 지원하는 것이 일반적이지만 필자처럼 가난한 취미 프로그래머에게는 오래 된 앤티크 윈도우즈 7 PC에 단지 CPU 밖에 없으므로 CPU 버전을 설치해서 사용법을 알아보기로 한다.
아나콘다가 깔려 있으나 TensorFlow 1.6 버전 설치에 실패했던 윈도우즈 7 Anaconda Prompt 창에서 conda install pytorch-cpu -c pytorch 코맨드 라인 명령을 실행하자.
그 다음 pip3 install torchvision 코맨드 라인 명령을 실행하도록 되어 있으나 실행해 보면 pip3 명령이 없다는 에러 메시지가 뜬다. pip3 는 python3 와 관련된 패키지 설치 명령이지만 현재 설치되어 있는 아나콘다에 없을 수도 있다.
우선 conda list 명령을 사용하여 pip 와 Python이 설치되었는지를 확인해 보자.
pip 과 아울러 python 3.6 버전이 설치되어 있으면 pip install torchvision 코맨드 라인 명령을 실행하고 다시 conda list 명령에 의해 pytorch-cpu 가 설치되었음을 확인하자.
바로 위의 conda list 명령 실행 결과를 찾아 보면 pytorch-cpu 버전이 이미 설치되어 있었음을 확인할 수 있다.
2018년 3월경에 아나콘다 텐서플로우 1.6 버전 설치과정에서 파이선 3.5 버전으로 재조정하다가 실패한 아나콘다 Navigator를 실행하자. 물론 텐서플로우 1.6 버전 설치는 실패했으나 다른 나머지 기능들은 OK 인 상태이다.
pytorch 사용법은 다음과 같이 스파이더3 IDLE를 열어서 한 줄짜리 import pytorch 명령을 코딩하여 실행 해보면 된다.
TensorFlow 코드 실행 때와 비교해서 코드 헤더 영역에 import torch 가 한줄 있는 것 외에는 아무런 차이가 없다.
윈도우즈 7에 설치가 가능했으면 윈도우즈 10에서의 설치는 그다지 어렵지 않아 보인다. 하지만 해보니 방법이 완전히 달랐음에 유의하자. 윈도우즈 10 사용자라면 직접 도전해 보기 바란다. 혹 잘 안되는 분도 있을 수 있기에 별도로 블로그에 필자의 경험을 올릴 예정이다.
인터넷에서 가져온 다음의 예제코드를 실행해보자. 내용은 현재로서는 전혀 모르는 상태이다. 단지 pytorch가 제대로 실행되는지 보기 위한 예제이다. Anaconda Navigator 에서 Application on 이 반드시 root(base) 에 설정되었는지 확인하고 Spyder 편집기를 Launch 시킨다.
#pytorch_example_01
import torch
dtype = torch.float
device = torch.device("cpu")
#device = torch.device("cuda:0") # Uncomment this to run on GPU
#N is batch size; D_in is input dimension;
#H is hidden dimension; D_out is output dimension.
N, D_in, H, D_out = 64, 1000, 100, 10
#Create random input and output data
x = torch.randn(N, D_in, device=device, dtype=dtype)
y = torch.randn(N, D_out, device=device, dtype=dtype)
#Randomly initialize weights
w1 = torch.randn(D_in, H, device=device, dtype=dtype)
w2 = torch.randn(H, D_out, device=device, dtype=dtype)
learning_rate = 1e-6
for t in range(500):
# Forward pass: compute predicted y
h = x.mm(w1)
h_relu = h.clamp(min=0)
y_pred = h_relu.mm(w2)
# Compute and print loss
loss = (y_pred - y).pow(2).sum().item()
print(t, loss)
#Backprop to compute gradients of w1 and w2 with respect to loss
grad_y_pred = 2.0 * (y_pred - y)
grad_w2 = h_relu.t().mm(grad_y_pred)
grad_h_relu = grad_y_pred.mm(w2.t())
grad_h = grad_h_relu.clone()
grad_h[h < 0] = 0
grad_w1 = x.t().mm(grad_h)
#Update weights using gradient descent
w1 -= learning_rate * grad_w1
w2 -= learning_rate * grad_w2