본문 바로가기

카테고리 없음

pytorch 공부

import torch
import torch.nn as nn
import torch.optim as optim

# 데이터셋 정의 (OR 게이트)
X = torch.tensor([[0, 0], [0, 1], [1, 0], [1, 1]], dtype=torch.float32)
Y = torch.tensor([[0], [1], [1], [1]], dtype=torch.float32)

# 퍼셉트론 클래스 정의
class Perceptron(nn.Module):
    def __init__(self):
        super(Perceptron, self).__init__()
        # 가중치와 바이어스를 수동으로 정의
        self.weights = torch.randn((2, 1), dtype=torch.float32, requires_grad=True)
        self.bias = torch.randn(1, dtype=torch.float32, requires_grad=True)

    def forward(self, x):
        # 선형 변환 (Wx + b)
        x = torch.matmul(x, self.weights) + self.bias
        # 활성화 함수 (시그모이드)
        x = torch.sigmoid(x)
        return x

# 모델, 손실 함수, 옵티마이저 정의
model = Perceptron()
criterion = nn.BCELoss()
optimizer = optim.SGD([model.weights, model.bias], lr=0.1)

# 학습
num_epochs = 1000
for epoch in range(num_epochs):
    # 순전파
    outputs = model(X)
    loss = criterion(outputs, Y)

    # 역전파 및 최적화
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()

    if (epoch + 1) % 100 == 0:
        print(f'Epoch [{epoch+1}/{num_epochs}], Loss: {loss.item():.4f}')

# 학습 후 테스트
with torch.no_grad():
    outputs = model(X)
    predicted = (outputs > 0.5).float()
    accuracy = (predicted == Y).sum() / Y.shape[0]
    print(f'Predicted:\n{predicted}\nAccuracy: {accuracy.item() * 100:.2f}%')
 
 
이런식으로 모델을 만들어 볼 수 있는데 forward는 이해가 되는데 학습할때 loss계산하고 backward하고 step으로 수정하는게 어떤 식으로 되는지 모르겠어서 찾아보았다
torch.randn((2, 1), dtype=torch.float32, requires_grad=True)
이건 2x1 랜덤값이 들어있는 행렬을 만드는건데 dtype은 데이터 타입이 32bit float형이라는 뜻이고 requires_grad는 이게 중요한 것이었는데 autograd라는걸 true로 하게한다는 것이다 
 
https://velog.io/@ss-hj/PyTorch%EC%97%90%EC%84%9C-autograd-%EB%8F%99%EC%9E%91-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0

PyTorch에서 autograd 동작 이해하기

Autograd ; Automatic gradient calculating API forward와 backward가 가능하게 해줌

velog.io

https://velog.io/@bismute/Pytorch%EC%9D%98-Autograd%EB%A5%BC-%EC%A0%9C%EB%8C%80%EB%A1%9C-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0

Pytorch의  Autograd를 제대로 이해하기

근래에 NAS(Neural Architecture Search)로 주제를 바꾸며 pytorch를 더 자유자재로 구현할 필요성이 생겼다.그런데 공부를 하다가 autograd 관련 예제의 결과를 예측하는데 실패한 것들이 있어서 정리할겸

velog.io

 
위 글들을 읽고 어느정도 이해했지만 행렬의 이해가 아직 부족해서 야코비 행렬을 아직 잘 모르겠다.
 
이어가자면 requires_grad가 true인 경우 그 행렬으로부터 계산이 될 때마다 그 계산을 그래프 형태로 기록해서 미분할 수 있게 하는 것이다. 
forward에서 계산이 이루어지면 그 계산까지 다 기록을 해두고 
loss = criterion(outputs, Y)와 같이 계산해도 기록이 되고 
 
loss.backward()할때 처음부터 loss를 계산한 순간까지의 계산들에 대해서 chain rule을 적용해서 미분을 해서 loss 계산에 이용된 requires_grad가 true인 변수들이 grad 값이 추가된다.
backward()는 스칼라값일때만 된다 입력이 없을경우
 
loss.backward()할때마다 누적되니까 optimizer.zero_grad()를 통해 grad를 0으로 만들어주고 backward한다 optimizer.step()는 optimizer 생성할때 requires_grad가 true인 class들을 넣어주면 그 grad에 대해 optimizer의 계산식대로 그 행렬을 변화시킨다.
 
이번에 공부를 통해 파이토치의 텐서가 그저 행렬이 라고 생각해서 최적화 과정이 이해되지 않았다는걸 알았다.
텐서에 대해 더 알아 보고 야코비 행렬, 행렬의 미분을 좀 공부해야겠다고 생각했다.