양자화 코드를 직접 구현해보기 전에, 먼저 정확히 알아야함!
만약, (1024,512) 크기의 weight가 있다면, 이걸 int8로 양자화 하기 위한 Scale Factor의 shape은 뭘까? 이거에 답변할 수 있어야, 정확히 이해한거임!
pytorch 깃허브에 torch/nn/modules/linear.py안에 코드가 존재한다.
https://docs.pytorch.org/docs/stable/generated/torch.nn.Linear.html
r"""Applies an affine linear transformation to the incoming data: :math:`y = xA^T + b`.
Shape:
- Input: :math:`(*, H_\text{in})` where :math:`*` means any number of
dimensions including none and :math:`H_\text{in} = \text{in\_features}`.
- Output: :math:`(*, H_\text{out})` where all but the last dimension
are the same shape as the input and :math:`H_\text{out} = \text{out\_features}`.
Attributes:
weight: the learnable weights of the module of shape
:math:`$(\text{out\_features}, \text{in\_features})$`. The values are
initialized from :math:`$\mathcal{U}(-\sqrt{k}, \sqrt{k})$`, where
:math:`$k = \frac{1}{\text{in\_features}}$`
bias: the learnable bias of the module of shape :math:`$(\text{out\_features})$`.
If :attr:`bias` is ``True``, the values are initialized from
:math:`$\mathcal{U}(-\sqrt{k}, \sqrt{k})$` where
:math:`$k = \frac{1}{\text{in\_features}}$`
추가적으로 bias도 존재한다.
__constants__ = ["in_features", "out_features"]
in_features: int
out_features: int
weight: Tensor
class Linear(Module):
def __init__(
self,
in_features: int,
out_features: int,
bias: bool = True,
device=None,
dtype=None,
) -> None:
factory_kwargs = {"device": device, "dtype": dtype}
super().__init__()
self.in_features = in_features
self.out_features = out_features
self.weight = Parameter(
torch.empty((out_features, in_features), **factory_kwargs)
)
if bias:
self.bias = Parameter(torch.empty(out_features, **factory_kwargs))
else:
self.register_parameter("bias", None)
self.reset_parameters()
def reset_parameters(self) -> None:
"""
Resets parameters based on their initialization used in ``__init__``.
"""
# Setting a=sqrt(5) in kaiming_uniform is the same as initializing with
# uniform(-1/sqrt(in_features), 1/sqrt(in_features)). For details, see
# https://github.com/pytorch/pytorch/issues/57109
init.kaiming_uniform_(self.weight, a=math.sqrt(5))
if self.bias is not None:
fan_in, _ = init._calculate_fan_in_and_fan_out(self.weight)
bound = 1 / math.sqrt(fan_in) if fan_in > 0 else 0
init.uniform_(self.bias, -bound, bound)
class Linear(Module):
...
def forward(self, input: Tensor) -> Tensor:
"""
Runs the forward pass.
"""
return F.linear(input, self.weight, self.bias)
def extra_repr(self) -> str:
"""
Return the extra representation of the module.
"""
return f"in_features={self.in_features}, out_features={self.out_features}, bias={self.bias is not None}"
forward
input이 들어왔을 때, 수행하는 연산으로 라고 짜도 되지만, PyTorch는 내부 C++/CUDA로 최적화된 F.linear 함.
이 함수가 백엔드에서 GEMM (General Matrix Multiply) 연산을 수행해서 엄청나게 빠른 속도로 를 계산해줌.
그냥 torch.tensor와 다르게 Parameter는 학습 가능한 변수로 등록되는 것이다.
(출력, 입력) 순으로 되어 있는데, 이는 메모리 구조때문이다. y1은 입력벡터 x와 가중치 행렬의 첫번째 행 전체를 곱해서 더해야 한다.
forward
extra_repr
단순히 print(model)을 했을 때 나오는 문자열을 정의하는 함수로 디버깅용 함수이다.
예시: print(nn.Linear(20, 30))을 입력하면, 이 함수 덕분에 Linear(in_features=20, out_features=30, bias=True)라고 정보가 출력된다.