본문 바로가기
딥러닝&머신러닝/파이토치 기본 문법

파이토치 nn 모듈

by David.Ho 2023. 1. 9.
728x90
반응형

파이토치에는 torch.nn이라는 모든 신경망 아키텍처를 만들 수 있는 빌딩 블럭이 있는 전용 서브모듈이 있다.

 

파이토치에서는 빌딩 블럭을 모듈(module)이라 부든다.(다른 프레임워크에서는 계층(layer)이라고 일컫는다.)

 

파이토치 모듈은 nn.Module 베이스 클래스에서 파생된 파이썬 클래쓰다. 모듈은 하나 이상의 Parameter 객체를 인자로 받고, 텐서타입이며 훈련 과정을 통해 값이 최적화된다.

참고
서브 모듈은 list난 dict 객체에 들어간 형태가 아닌 최상위 레벨 속성이어야 한다! 그렇지 않으면 옵티마이저가 서브 모듈(파라미터)을 찾지 못한다. 모델이 리스트나 딕셔너리 형태의 서브 모듈을 요구하는 경우에 대응할 목적으로 nn.ModuleList와 nn.ModuleDict를 파이토치에서는 제공한다.

 

[nn 사용 예시]

 

1. forward 대신 __call__사용하기

nn.Module의 모든 서브클래스에는 __call__ 메소드가 정의되어 있어 nn.Linear를 인스턴화하여 마치 함수인 것처럼 실행할 수 있다.

import torch.nn as nn

linear_model = nn.Linear(1, 1)
linear_model(t_un_val)

#out:
tensor([[0.6018],
	[0.2877]], grad_fn=<AddmmBackwaed>)

여기에서 인자를 가지고 nn.Module 인스턴스를 호출하면 동일한 인자로 forward를 호출한다.

 

forward 메소드는 순방향 연산을 수행하는 반면

__call__은 forward를 호출하지 전후에 몇 가지 중요한 작업을 수행한다.

 

그래서 forward를 직접 호출할 수 있고 __call__과 같은 결과를 얻겠지만, 유저 코드에서는 사용하지 않는 편이 좋다.

 

y = model(x) # 맞음!!

y = model.forward(x) # 티도 안나는 오류. 이렇게 하지 말자!!!

Module.__call__의 구현은 다음과 같다

def __call__(self, *input, **kwargs):
	
    for hook in self._forward_pre_hooks.values():
    	hook(self, input)
        
    result = self.forward(*input, **kwargs)
    
    for hook in self._forward_hooks.values():
    	hook_result = hook(self, input, result)
        #...
        
    for hook in self._backward_hooks.values():
    	#...
        
    return result

코드를 보면 알겠지만 직접 .forward(...)를 호출하면 제대로 수행되지 않을 훅(hook)들이 엄청 많다.

 

2. 다시 선형 모델로

nn.Linear 생성자는 세 개의 인자를 받는다.
입력 피처의 수와 출력 피처의 수 그리고 선형 모델이 편향값을 포함하는지 여부(기본값은 True다)이다.

import torch.nn as nn

linear_model = nn.Linear(1, 1)
linear_model(t_un_val)

#out:
tensor([[0.6018],
	[0.2877]], grad_fn=<AddmmBackwaed>)

우리의 경우 피처 수는 모듈에 대한 입출력 텐서 크기와 같아서, 값이 각각 1, 1이다. 만일 온도와 기압을 입력받는다면 입력 피처는 둘이고 출력 피처는 하나다.
나중에 중간 규모의 모듈을 가진 복잡한 모델을 다루게 되면 피처의 수는 모델의 용량과 연관이 있음을 보게 될 것이다.

 

밑에 하나의 입력 피처와 하나의 출력 피티를 가진 nn.Linear 인스턴스가 있다.
이 인스턴스를 하나의 가중치와 편향값을 요구한다.

linear_model.weight

# out
# Parameter containing:
# tensor([[-0.0674]], requires_grad=True)

linear_model.bias

# out
# Parameter containing:
# tensor([[0.7488]], requires_grad=True)

이제 입력값으로 모듈을 호출할 수 있다.

x = torch.ones(1)
linear_model(x)

# out
# tensor([0.6814], grad_fn=<AddBackward0>)

 

728x90
반응형

댓글