읽기일기

Learning PyTorch with Examples (2) – Autograd

http://pytorch.org/tutorials/beginner/pytorch_with_examples.html#autograd

Learning PyTorch with Examples

Autograd

PyTorch: Variables and autograd

앞의 예제에서는 신경망의 순전파와 역전파 과정을 직접 작성하였습니다. 2층을 가지는 신경망이라 역전파 과정을 손으로 작성하는 것이 어렵지는 않았지만, 크고 복잡한 망이라면 짜는게 쉽지 않을 것입니다.

고맙게도 자동 미분 기능이 있어 역전파 과정을 자동으로 계산할 수 있습니다. PyTorch의 autograd 패키지가 바로 그 기능을 제공합니다. autograd를 사용하면, 순전파를 실행할 때 계산 그래프를 정의합니다. Tensor가 그래프의 노드가 될 것이고, 입력 Tensor를 받아 출력 Tensor를 내놓는 함수가 그래프의 에지가 될 것입니다. 이 그래프를 통해 역전파를 하면 쉽게 그래디언트를 계산할 수 있습니다.

설명만 보면 꽤 복잡해 보이지만, 실제 사용은 매우 쉽습니다. PyTorch Tensor를 Variable 객체로 감싸면 됩니다. Variable은 계산 그래프의 노드를 나타냅니다. x가 Variable이라면, x.data는 Tensor이고 x.grad는 어떤 한 스칼라 값에 대한 x의 그래디언트를 가지는 또다른 Variable입니다.

PyTorch Variable은 PyTorch Tensor와 동일한 API를 가집니다. Tensor에 적용할 수 있는 거의 모든 연산이 Variable에도 작동합니다. 다른 부분은 Variable을 사용할 경우 자동으로 그래디언트를 계산하기 위해 계산 그래프를 만든다는 것 뿐입니다.

이제 PyTorch Variable과 autograd를 이용한 2층 신경망을 보겠습니다. 이제 더 이상 역전파 과정을 손으로 구현할 필요가 없습니다.

PyTorch: Defining new autograd functions

PyTorch를 뜯어보면, autograd의 각 연산은 실제로 2개의 함수가 Tensor에서 작동하고 있습니다. forward 함수는 입력 Tensor로부터 출력 Tensor를 계산합니다. backward 함수는 출력 Tensor로부터 어떤 스칼라 값에 대한 그래디언트를 받고, 그 스칼라 값에 대한 입력 Tensor에 대한 그래디언트를 계산합니다.

PyTorch에서는 torch.autograd.Function의 서브클래스를 정의하고 forwardbackward 함수를 구현하기만 하면 원하는 autograd 연산을 쉽게 만들 수 있습니다. 이렇게 만들어진 새로운 autograd의 인스턴스를 만들고 함수를 부르는 것처럼 입력 데이터가 담긴 Variable를 넘겨주어 우리가 원하는 연산을 할 수 있습니다.

아래 예제에서는 사용자 정의 ReLU nonlinearity를 계산하는 autograd 함수를 정의하고, 그걸 2층 신경망에 사용해보겠습니다.

TensorFlow: Static Graphs

PyTorch의 autograd는 TensorFlow와 꽤 비슷합니다. 두 프레임워크 모두 계산 그래프를 정의하고, 자동으로 그래디언트를 계산하는 기능이 들어가 있습니다. 둘의 가장 큰 차이는 TensorFlow의 계산 그래프는 정적이고 PyTorch는 동적이라는 점입니다.

TensorFlow에서는 계산 그래프를 한번 정의하고 나면 그래프에 들어가는 입력 데이터만 다르게 할 수 있을 뿐이고 같은 그래프만을 실행할 수 있습니다. 하지만 PyTorch는 각 순전파마다 새로운 계산 그래프를 정의하여 이용합니다.

정적 그래프는 그래프의 초기 부분을 최적화 할 때에는 좋습니다. 예를 들어, 프레임워크는 효율성을 위해서 몇개의 그래프 연산을 조합하거나, 그래프를 여러 GPU나 컴퓨터로 나누어 실행할고자할 때가 있습니다. 만약 어떤 그래프를 계속적으로 사용해야 할 경우, 이에 따른 연산 부담이 가중될 수 있는데, 같은 그래프를 계속 재실행할 경우 이런 부담을 낮출 수 있습니다.

정적 그래프와 동적 그래프의 다른 한 차이는 제어 흐름입니다. 어떤 모델에서는 각 데이터 포인트마다 다른 계산을 하고 싶을 수 있습니다. 예를 들어 recurrent network는 각 데이터 포인트에대해 서로 다른 여러 타임 스텝에 대해서 언롤(unroll)됩니다. 이 언롤링은 루프로 구현되게 되는데, 정적 그래프를 사용하면 이 루프 자체가 그래프의 한 부분으로 구현되어 있어야 합니다. 이런 이유로 TensorFlow는 tf.scan와 같은 연산으로 그래프 내에 루프를 집어 넣습니다. 동적 그래프를 사용하면 이런 상황이 매우 간단해집니다. 각 상황에 따라 그래프를 on-the-fly로 다시 만들기 때문에, 각 입력에 따라 달라지는 계산을 평범한 명령형 흐름 제어(imperative flow control)을 이용할 수 있습니다.

위에서 PyTorch autograd를 사용한 것과 아래의 TensorFlow로 작성한 코드를 비교해봅시다.

 

 


Tags:
Add a Comment Trackback