Module
torch.nn.Module, forward
Input, Output, Forward, Backward을 정의하는 Pytorch에서 모델을 만드는데 필요한 base class
class MyLiner(nn.Module):
def __init__(self, in_features, out_features, bias=True):
super().__init__()
self.in_features = in_features
self.out_features = out_features
self.weights = nn.Parameter(
torch.randn(in_features, out_features))
self.bias = nn.Parameter(torch.randn(out_features))
def forward(self, x : Tensor):
return x @ self.weights + self.bias
기본적으로 이와 같은 형태로 정의한다.
x = torch.randn(5, 7)
layer = MyLiner(7, 12)
print(layer(x))
print(layer(x).shape)
tensor([[-1.0976, -3.7846, -0.3487, 0.6130, -1.4488, -2.3584, 1.9038, -1.8659,
-2.0500, 3.6289, -3.1050, 1.0894],
[-1.6706, 0.3755, -1.5286, 2.5324, -1.1470, -2.9243, 0.6232, -1.3477,
-2.9759, -0.7234, -2.1702, 1.6472],
[-0.6848, -3.1662, 1.6751, 2.8280, 0.0547, -7.0330, 4.6043, 0.4106,
2.5847, 2.0780, -2.8696, -2.6945],
[-2.6873, 5.5187, 0.4022, 0.9746, -2.5212, -1.7941, -5.1957, 1.9673,
5.3406, 0.0358, -0.6157, -1.8670],
[-0.6576, -4.4255, -3.1510, -3.5183, -0.8047, 3.2060, 0.0453, -1.6277,
0.4563, -0.6117, -0.9793, -0.9038]], grad_fn=<AddBackward0>)
torch.Size([5, 12])
보시다시피 instance호출시 결과로 x에 forward연산을 진행한 값을 리턴해준다.
Module class를 직접 뜯어보지는 않았지만 아마도
객체 호출시 연산이 자동적으로 실행되는 forward를 미리 정의해두어서 이를 overriding하여 연산을 넣어주는것 같다.
x = torch.randn(3, 5, 7)
layer = MyLiner(7, 12)
print(layer(x).shape)
torch.Size([3, 5, 12])
batch_size를 앞에 붙여줘도 이에 맞춰서 동작한다.
Backward
Backward연산은 특히 중요하므로 따로 떼서 설명해보겠다.
backward
매개변수의 기울기를 반환한다
x = torch.ones(5) # input tensor
y = torch.zeros(3) # expected output
w = torch.randn(5, 3, requires_grad=True)
b = torch.randn(3, requires_grad=True)
z = torch.matmul(x, w)+b
loss = torch.nn.functional.binary_cross_entropy_with_logits(z, y)
loss.backward()
print(w.grad)
print(b.grad)
tensor([[0.1868, 0.2503, 0.2583],
[0.1868, 0.2503, 0.2583],
[0.1868, 0.2503, 0.2583],
[0.1868, 0.2503, 0.2583],
[0.1868, 0.2503, 0.2583]])
tensor([0.1868, 0.2503, 0.2583])
loss가 목적함수이고 w와b를 requires_grad=True로 설정했으니
loss.backwart( )로 loss에 대한 w와b의 도함수를 구할 수 있다(도함수 구하는 공식을 몰라 어째서 값이 저렇게 똑같이 나왔는지는 모르겠다...)
이 backward를 Pytorch의 모듈 클래스에 적용하려면 하는 방식은 아래와 같다
class LinearRegression(torch.nn.Module):
def __init__(self):
super(LinearRegression, self).__init__()
self.w = torch.nn.Parameter(torch.rand(1, requires_grad=True))
self.b = torch.nn.Parameter(torch.rand(1, requires_grad=True))
def forward(self, x):
out = x * self.w
out = x + self.b
return out
criterion = torch.nn.MSELoss()
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)
print(list(model.parameters()))
print(print(model.w, model.b))
[Parameter containing:
tensor([0.7073], requires_grad=True),
Parameter containing:
tensor([0.0711], requires_grad=True)]
Parameter containing:
tensor([0.7073], requires_grad=True) Parameter containing:
tensor([0.0711], requires_grad=True)
먼저 Parameter에 w와b를 넣어주고 forward연산을 정의한다.(실제로 torch.nn.Parameter로 파라미터를 추가하는 경우는 거의 없다 그저 예시를 위해 가장 근본적인 attribute를 사용했을뿐이다)
model이 parameter로 저 둘을 추적하고 있는걸 확인할 수 있다.
for epoch in range(epochs):
inputs = torch.from_numpy(x_train)
labels = torch.from_numpy(y_train)
# Clear gradient buffers because we don't want any gradient from previous epoch to carry forward, dont want to cummulate gradients
optimizer.zero_grad()
# get output from the model, given the inputs
outputs = model(inputs)
`
# get loss for the predicted output
loss = criterion(outputs, labels)
print(loss)
# get gradients w,b to parameters
loss.backward()
# update parameters
optimizer.step()
print('epoch {}, loss {}'.format(epoch, loss.item()))
tensor(40.4280, grad_fn=<MseLossBackward0>)
epoch 0, loss 40.427982330322266
tensor(39.2230, grad_fn=<MseLossBackward0>)
epoch 1, loss 39.2230339050293
tensor(38.0658, grad_fn=<MseLossBackward0>)
epoch 2, loss 38.065799713134766
tensor(36.9544, grad_fn=<MseLossBackward0>)
epoch 3, loss 36.95439147949219
tensor(35.8870, grad_fn=<MseLossBackward0>)
epoch 4, loss 35.88699722290039
tensor(34.8619, grad_fn=<MseLossBackward0>)
......
실제로 사용시에는 torch내부에 구현되어 있는 loss와 optimizer를 사용하게 된다.
loss에 모델의 출력과 라벨값을 넣어주면 모델의 손실이 나오고 backward( )를 통해 w와b의 gradient를 계산한다
optimizer.step( )은 미리 넣어준 model.parameters( )들을 gradient만큼 optimizer공식대로 이동시켜준다.
실제로 이 과정을 통해 epoch별로 loss가 줄어드는 것을 확인할 수 있다.
설명이 길어졌지만 막상 모델을 만들때는 마지막 부분만 응용해서 만들 느낌이다
출처: https://tutorials.pytorch.kr/beginner/basics/autogradqs_tutorial.html
'Deep Learning' 카테고리의 다른 글
[Pytorch] ImageFolder label기준으로 split하기 (0) | 2023.04.10 |
---|---|
[Pytorch]Datasets and dataloaders (0) | 2023.03.23 |
[Pytorch]Pytorch Basic (0) | 2023.03.19 |