본문 바로가기

Machine Learning/Dev Env

1. Pytorch 기본 용어 및 2-layered NN 구성- Tensor, Variable, Module

반응형

PyTorch는 기본적으로 크게 3개의 추상화된 객체를 제공합니다.

  1. Tensor : n-d array (numpy처럼 작성), GPU에서 동작 (Deep Learning과 직접적인관련은 없음)
      => numpy array유사

  1. Variable : computational graph의 Node역할을 함. data나 gradient를 저장
      => tensor flow의 Tensor, Variable, Placeholder 유사

  1. Module : NN에서의 layer에 해당. 상태나 학습가능한 weight을 저장 
      => (조금 더 high level의 문법)tf.layers, TFSlim또는 TFLearn...등과 유사



* Pytorch 0.4가 릴리즈된 이후로는 Tensor가 Variable을 완전히 대체하여 현재는 Variable없이 Tensor로 구축하는 편입니다.




  1. Tensor

(2-layered-Neural Network, random data, weight으로 초기화하고, FP, BP, Sgd update하는 과정)

(Pytorch 0.4 이전)

기본적으로, tensor를 지원하므로써, numpy를 import할 필요가 없어짐. 

dtype = torch.cuda.FloatTensor
GPU를 통해 계산을 하기 위해선, data type이 torch.FloatTensor가 아닌 위 문장을 통해, 데이터타입을 캐스팅해줘야 한다.

위의 문장만 실행해준다면, Tensor는 numpy+GPU라고 생각해도다.




*(Pytorch 0.4 이후)
Tensor가 Variable을 완전히 대체하여 위의 numpy array의 특징과 뒤에 나올 Variable 특징을 Tensor에 내장하게 됩니다.




  1. Variable (Autograd 패키지에서 제공)

이제 tensor(단순 행렬)에서 variable(node)로 이동하면, autograd패키지에서 제공하는 (gradient를 연산에 따라 BP를 이용해 자동적으로 계산) computational graph를 구성해야한다.
(*참고로, variable 역시, autograd 패키지에서 제공하는 객체로, tensor를 감싸는 역할을 한다.)


간단한 예시로, x가 Variable일때... ( node )
x.data는 Tensor (행렬)
x.grad는 해당 Tensor의 loss에 대한 gradient를 포함하는  Variable이다.
이에 따라, x.grad.data는 gradient에 대한 Tensor (행렬)이다.


쉽게 말하면, node를 variable이라는 객체로 보고 variable(node)의 속성값으로 실제 값(원시 데이터)을 확인할때는 .data라는 attribute를 사용하여 tesor(행렬)로 반환하면 된다.
또한, x에는 loss에 대한 gradient 정보를 .grad를 통해 또 다른 variable(node객체)로 제공하고 이를 다시 실제 값(원시 데이터)을 확인할때 는 .data를 쓰면 된다.


사실, Pytorch에서는 tensor와 variable이 정확히 같은 API를 제공한다.
따라서, 코드가 tensor(행렬)를 통해 연산되었다면, 이 객체를 variable로 바꾸기만 하면, 똑같이 동작하면서, computational graph를 구성할 필요도 없어진다.
    



Variable을 생성하면, vaiable을 생성자를 호출하게 되는데 이때 파라메터로, tensor와 , gradient를 연산할지에 대한 flag를 전달하게 된다.

같은 API를 제공하므로, FP에서는 tensor때와 동일하다.
prediction과 loss를 계산한다.


 
BP에선 별다른것 없이 loss.backward를 사용한다.
이를 통해 gradient가 추출된다.


마찬가지로 최종적으로 gradient update


정리하면, autograd 패키지의 variable객체를 사용하면, gradient에 대한 걱정없이 numpy를 활용한 신경망 코딩방식과 동일하게 설계할 수 있다.


*Pytorch 0.4버전 이후로는 위의 Variable에 있는 Attribute가 Tensor에도 존재하기 때문에, Variable객체로 Tensor를 감싸주는 작업 없이 바로 Tensor를 Variable처럼 사용한다.



*PyTorch vs TensorFlow?

TensorFlow는 전체적인 그래프를 명시적으로 한번 생성하고 이 그래프를 수차례 동작(session)시킨다.
반면에, PyTorch그래프를 매 Forward Path시에 새로운 그래프를 만든다. 이 때문에, 코드가 간결해진다.
간혹 모델을 여러번 반복하여 사용하려면 for문을 통해 적절하게 iteration을 하면 된다.



  1. Module



새로운 autograd function은 forward와 backward를 tensor에 대해 정의해줌으로서 만들 수 있고 이를 module이라고 한다. 다시말해, module은 NN의 layer이거나 computational graph속 하나의 component로 사용자 입맛에 맞게 커스터마이징하여 생성할 수도 있다. 


실제 user define ReLU를 computational graph에 포함시켜도 정상적으로 작동한다.

일반적인 경우 autograd function (module)을 정의해서 사용하진 않는다. 대부분의 이러한 module이 이미 pytorch내에 정의되어 있기 때문이다. 따라서 module은 특별한 필요가 있을 때만 새로 정의해서 사용하면 된다.




  1. nn package

위에서 설명해온바와 같이 각 layer별 computational graph를 모두 구성하기에는 코드가 복잡해 질 수 있다. computational component에 대한 걱정을 덜기 위해 TensorFlow에서 제공되는 TF.learn이나 keras처럼 high level API를 PyTorch에서도 제공한다. 오직 nn이란 패키지에서만 이런 high-level API를 제공하는데, 매우 잘 동작하기 때문에 PyTorch 환경에서는 이를 사용해야한다.





케라스와 유사하게 layer의 squence로 model에 저장한다.
loss 역시 nn 패키지에 저장된 함수를 불러서 사용할 수 있다. 위의경우 mean squared error loss사용.



각각의 fp는 for문을 통한 iteration을 통해 표현된다. 




이전과 마찬가지로, loss.backward()를 통해 gradient에 대한 걱정없이 bp과정에서 얻어야할 gradient를 쉽게 얻을 수 있다.

이후에 최종적으로 gradient기반으로 parameter를 갱신하면 된다. 위의경우엔 SGD
 

하지만, 현실적으로 대부분의 학습에서는 SGD가 아닌 Adam을 사용하며 이는 별도의 복잡한 식구성이 필요하다. 따라서, 이를 다시 정의할 필요없이 TensorFlow와 마찬가지로 update 방식과 구현에 대한 것을 추상화한, optimizer operation을 제공한다. 
단순하게, optimizer object를 사용하려는 방식에 맞게 생성하고, 해당 객체의 .step메서드를 실행하면 된다.
생성시에 모델이나 learning rate과 같은 hyperparameter를 parameter로 전달하고, 기존코드의 update 단계에서 optimizer.step()을 수행하면 된다.





  • NN module class define


일반적으로 신경망 전체를 구성할 때, 전체 모델을 클래스로 정의해서 저장한다.
이를 새로운 단일 nn module 클래스로 정의할 수 있다. 

module은 neural Network의 layer로서, input과 output으로 Variable을 이용한다.
또한, module은 다른 module을 포함하거나 학습가능한 weight 또는, 상태를 저장할 수 있다.
따라서, 전체 모델은 단일의 module로 취급된다. 해당 module에서 layer(또 다른 module)들을 포함하는 방식으로 설계된다.


앞서 논의한 2-layered Neural Network를 nn module 클래스를 통해 정의하면 위와 같다.

initializer에서 새로운 module object에 대한 정의를 해준다.  위의 경우 총 두 개의 layer(module)이 생성될 것이다.
바로 다음으로 정의할 것이 forward path이다. 

forward path에서는 internal module을 통해 구성한다. 이때, autograd operation이 vaiable에 상응하게 진행될것이므로, bp에 대해서는 신경쓸 필요가 없다.

구체적인 과정으로는, x(input)를 받으면 layer1에 전달함과 동시에 .clamp를 통해 ReLU를 통과시킨다.
이후에 ReLU를 거친 결과를 layer2에 전달하면서 끝이난다.

이후 train 과정은 이전과 거의 동일하다.
loss와 optimizer를 정의하고 학습을 위한 for loop을 이용한다.
학습을 위한 for loop은 아래와 같이 구성된다.
  1. input data를 model에 feed하여 예측값과 loss를 구한다.
  2. loss를 구하고 난뒤에 backward()를 통해 autograd에서 연산된 gradient를 얻는다.
  3. optimizer.step을 통해 autograd operation에서 얻은 gradient 기반으로 optimizer를 통해서 parameter를 갱신한다.



정리 

아래 프로세스가 일반적인 PyTorch를 이용한 NN구성과 학습에서 사용되는 방식이다.

  1. nn module class 정의 (모델)
    1. initializer 정의 - layer 구성 (module)
    2. forward 정의 - initializer에서 구성한 Network기준으로 input x가 들어왔을때, FP정의
  2. 학습
    1. 정의한 nn module class기반으로 model 생성, loss 객체 생성, optimizer 객체 생성
    2. for loop을 통해 실제 학습 수행
      1. input data를 model에 feed하여 예측값과 loss를 구한다.
      2. loss를 구하고 난뒤에 backward()를 통해 autograd에서 연산된 gradient를 얻는다.
      3. optimizer.step을 통해 autograd operation에서 얻은 gradient 기반으로 optimizer를 통해서 parameter를 갱신한다.

*Pytorch 0.4이후 버전에서는 Variable에서 제공되는 attribute가 Tensor에도 존재하기 때문에, Variable 없이 Tensor로만 컴포넌트를 구성한다.




반응형