欲速不達

일을 급히 하고자 서두르면 도리어 이루지 못한다.

Fantastic AI, Fantastic World

DS | Data Science/ML | Machine Learning

[Pytorch] Parameter : 매개변수 / Buffer

_껀이_ 2022. 9. 28. 12:34
728x90
반응형

1. Parameter란

정의로는 매개변수, 머신러닝에서는 모델이 사용할 수 있는 매개변수를 모델 내부에서 저장하는 것을 말한다. 일반적인 변수 지정 방식으로는 모델에서 반복적으로 로드할 수 없기 때문에 torch.nn.parameter.Parameter를 사용하여 torch 내부에 저장한다.

 

 

2. 모델 내부에서 Parameter 사용

import torch
from torch import nn
from torch.nn.parameter import Parameter

class Model_Param(nn.Module):
    def __init__(self, in_features, out_features):
        super().__init__()

        self.W = Parameter(torch.ones((out_features, in_features)),requires_grad=True)
        self.b = Parameter(torch.ones((out_features)),requires_grad=True)

    def forward(self, x):
        output = torch.addmm(self.b, x, self.W.T)

        return output
        
class Model_Tensor(nn.Module):
    def __init__(self, in_features, out_features):
        super().__init__()

        # torch.Tensor
        self.W = torch.ones((out_features, in_features))
        self.b = torch.ones(out_features)

    def forward(self, x):
        output = torch.addmm(self.b, x, self.W.T)

        return output

매개변수를 Parameter로 선언한 모델과 일반 텐서로 선언한 모델의 코드이다.

 

x = torch.Tensor([[1, 2],
                  [3, 4]])

Model_param = Model_Param(2, 3)
Model_tensor = Model_Tensor(2, 3)

output_param = Model_param(x)
output_tensor = Model_tensor(x)


print(output_param)
>> tensor([[4., 4., 4.],
           [8., 8., 8.]], grad_fn=<AddmmBackward0>)

print(output_tensor)
>> tensor([[4., 4., 4.],
           [8., 8., 8.]])

또, Parameter() 내부에 requires_grad=True를 명시해두면 해당 parameter도 역전파의 대상이 되어 gradient를 계산하고 업데이트 가능하게 된다. 반면에 Model_Tensor에서처럼 일반 tensor로 선언해둔 항목에 대해서는 gradient가 계산되지 않는다.

 

model_param.state_dict()
>> OrderedDict([('W', tensor([[1., 1.],
                              [1., 1.],
                              [1., 1.]])), ('b', tensor([1., 1., 1.]))])

model_tensor.state_dict()
>> OrderedDict()

Parameter로 선언했을 경우 모델 내부에 값이 저장된다. 이는 모델의 학습과정에서 반복적으로 호출될 수 있으며, gradient를 통해 업데이트 가능하다는 말과 같다.

반면에 일반 텐서로 선언했을 경우, 모델 내부에 저장되지 않으므로 반복적으로 호출이 될 수 없다.

 

 

이와 유사한 개념으로는 buffer가 있다.

buffer는 parameter와 유사하게 모델 내부에 값이 저장되지만, gradient를 계산하지 않고 업데이트도 되지 않는다.

class Model(nn.Module):
    def __init__(self):
        super().__init__()

        self.parameter = Parameter(torch.Tensor([6]))
        self.tensor = torch.Tensor([7])

        self.register_buffer('buffer',self.tensor)
        
model = Model()

buffer = model.get_buffer('buffer')

print(buffer)
>> tensor([7.])

print(model.state.dict())
>> OrderedDict([('parameter', tensor([6.])), ('buffer', tensor([7.]))])

위와 같이 self.register_buffer를 통해 'buffer'라는 이름으로 self.tensor를 저장하면, model.get_buffer('buffer')를 통해 값을 호출할 수 있다. 또, model.state.dict()를 확인해보면 buffer가 저장되어 있는 것을 볼 수 있다. 이때, buffer 값에 requires_grad가 없으므로 buffer는 업데이트 대상이 아니라는 것도 확인할 수 있다.

 

 

728x90
반응형