1. 파이토치의 nn.Linear와 nn.Sigmoid로 로지스틱 회귀 구현


import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim

torch.manual_seed(1)

우선 필요한 모듈을 불러온다.

x_data = [[1, 2], [2, 3], [3, 1], [4, 3], [5, 3], [6, 2]]
y_data = [[0], [0], [0], [1], [1], [1]]
x_train = torch.FloatTensor(x_data)
y_train = torch.FloatTensor(y_data)

Dataset을 설정한다.

model = nn.Sequential(
    nn.Linear(2,1),
    nn.Sigmoid()
)

이제 모델을 정의하는데, nn.Sequential()은 nn.Module 층을 차례로 쌓을 수 있도록 한다.

model(x_train)
tensor([[0.3600],
        [0.2872],
        [0.6801],
        [0.4389],
        [0.5216],
        [0.7473]], grad_fn=<SigmoidBackward0>)

현재 Wb는 랜덤으로 초기화가 된 상태이고, 훈련 데이터를 넣어 예측값을 확인해 보았다.
6x1의 크기를 가진 예측값 텐서가 출력된 것을 알 수 있다.

# optimizer 설정
optimizer = optim.SGD(model.parameters(), lr=1)

nb_epochs = 1000
for epoch in range(nb_epochs + 1):

    # H(x)계산
    hypothesis = model(x_train)

    # cost계산
    cost = F.binary_cross_entropy(hypothesis, y_train)

    # 최적화
    optimizer.zero_grad()
    cost.backward()
    optimizer.step()

    if epoch % 10 == 0:
        prediction = hypothesis >= torch.FloatTensor([0.5]) # 예측값이 0.5를 넘으면 True로 간주
        correct_prediction = prediction.float() == y_train # 실제값과 일치하는 경우만 True로 간주
        accuracy = correct_prediction.sum().item() / len(correct_prediction) # 정확도를 계산
        print('Epoch {:4d}/{} Cost: {:.6f} Accuracy {:2.2f}%'.format( # 각 에포크마다 정확도를 출력
            epoch, nb_epochs, cost.item(), accuracy * 100,
        ))
Epoch    0/1000 Cost: 0.614994 Accuracy 66.67%
Epoch   10/1000 Cost: 0.747550 Accuracy 83.33%
Epoch   20/1000 Cost: 0.633216 Accuracy 83.33%
Epoch   30/1000 Cost: 0.538123 Accuracy 83.33%
... 중략 ...
Epoch  970/1000 Cost: 0.020536 Accuracy 100.00%
Epoch  980/1000 Cost: 0.020340 Accuracy 100.00%
Epoch  990/1000 Cost: 0.020148 Accuracy 100.00%
Epoch 1000/1000 Cost: 0.019960 Accuracy 100.00%

경사하강법을 이용하여 100번의 epoch로 모델을 학습시키면 중간쯤부터는 정확도가 100%가 나옴을 확인할 수 있다.

model(x_train)
tensor([[2.8020e-04],
        [3.1770e-02],
        [3.9191e-02],
        [9.5600e-01],
        [9.9821e-01],
        [9.9968e-01]], grad_fn=<SigmoidBackward0>)

기존의 훈련 데이터를 입력하여 예측값을 확인해보았을 때, 0.5를 넘으면 True, 낮으면 False로 간주하기 때문에 실제값과 전부 일치함을 알 수 있다.

print(list(model.parameters()))
[Parameter containing:
tensor([[3.2477, 1.5151]], requires_grad=True), Parameter containing:
tensor([-14.4576], requires_grad=True)]

훈련 후의 모델 parameter Wb를 출력해보면 위와 같고, 앞 챕터에서 nn.Module을 사용하지 않고 로지스틱 회귀를 구현했을 때의 결과와 거의 일치한다.

2. 전체코드


import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim

torch.manual_seed(1)

# Dataset
x_data = [[1, 2], [2, 3], [3, 1], [4, 3], [5, 3], [6, 2]]
y_data = [[0], [0], [0], [1], [1], [1]]
x_train = torch.FloatTensor(x_data)
y_train = torch.FloatTensor(y_data)

# model 설정
model = nn.Sequential(
    nn.Linear(2,1),
    nn.Sigmoid()
)

# optimizer 설정
optimizer = optim.SGD(model.parameters(), lr=1)

nb_epochs = 1000
for epoch in range(nb_epochs + 1):

    # H(x)계산
    hypothesis = model(x_train)

    # cost계산
    cost = F.binary_cross_entropy(hypothesis, y_train)

    # 최적화
    optimizer.zero_grad()
    cost.backward()
    optimizer.step()

    if epoch % 10 == 0:
        prediction = hypothesis >= torch.FloatTensor([0.5]) # 예측값이 0.5를 넘으면 True로 간주
        correct_prediction = prediction.float() == y_train # 실제값과 일치하는 경우만 True로 간주
        accuracy = correct_prediction.sum().item() / len(correct_prediction) # 정확도를 계산
        print('Epoch {:4d}/{} Cost: {:.6f} Accuracy {:2.2f}%'.format( # 각 에포크마다 정확도를 출력
            epoch, nb_epochs, cost.item(), accuracy * 100,
        ))
profile
예비대학원생

0개의 댓글