스터디/AI

파이토치(2): 로지스틱 회귀와 클래스를 통한 구현

민서타 2023. 11. 5. 23:36

1. 로지스틱 회귀 구현

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

torch.manual_seed(0) # seed 고정
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)

# nn.Sequential: Wx+b와 활성화 함수를 연결해주는 함수
model = nn.Sequential(
   nn.Linear(2, 1), # input_dim = 2, output_dim = 1
   nn.Sigmoid() # 출력은 시그모이드 함수를 거친다
)

model(x_train)
tensor([[0.5427],
        [0.6331],
        [0.4456],
        [0.6306],
        [0.6294],
        [0.5362]], grad_fn=<SigmoidBackward0>)

-모델 훈련

#모델 훈련
optimizer = optim.SGD(model.parameters(), lr = 1e-2)
nb_epochs = 512

for epoch in range(1, nb_epochs+1):
    #H(x)
    h = model(x_train)
    #cost
    cost = F.binary_cross_entropy(h, y_train)
    
    #optimer로 h(x) 개선
    optimizer.zero_grad()
    cost.backward()
    optimizer.step()
    
    #epoch 20번 마다 출력
    if epoch % 20 == 0:
        pred = h >= torch.FloatTensor([0.5]) #예측값이 0.5를 넘으면 True
        correct_pred = pred.float() == y_train # 실제값과 일치하는 경우만 True
        Accuracy = correct_pred.sum().item() / len(correct_pred)
        print(f'Epoch : {epoch}, Accuracy : {Accuracy}')
        print(f'cost :{cost.item()}')
        
Epoch : 500, Accuracy : 0.8333333333333334
cost :0.2892662584781647

2. Class를 통한 모델 구현

class BC(nn.Module):
    def __init__(self):
        super().__init__()
        self.linear = nn.Linear(2, 1)
        self.sigmoid = nn.Sigmoid()
    
    def forward(self, x):
        return self.sigmoid(self.linear(x))
    
#모델 생성
model = BC()
#모델 훈련
optimizer = optim.SGD(model.parameters(), lr = 1e-2)
nb_epochs = 512

for epoch in range(1, nb_epochs+1):
    #H(x)
    h = model(x_train)
    #cost
    cost = F.binary_cross_entropy(h, y_train)
    
    #optimer로 h(x) 개선
    optimizer.zero_grad()
    cost.backward()
    optimizer.step()
    
    #epoch 20번 마다 출력
    if epoch % 20 == 0:
        pred = h >= torch.FloatTensor([0.5]) #예측값이 0.5를 넘으면 True
        correct_pred = pred.float() == y_train # 실제값과 일치하는 경우만 True
        Accuracy = correct_pred.sum().item() / len(correct_pred)
        print(f'Epoch : {epoch}, Accuracy : {Accuracy}')
        print(f'cost :{cost.item()}')

Epoch : 500, Accuracy : 0.8333333333333334
cost :0.421377569437027

3. Sigmoid, Softmax의 차이

-이진분류 vs 다중 분류문제 해결

Softmax: 각 회귀의 확률의 총합이 1이 되는 다중 클래스 분류 문제에 적용

#원핫 인코딩과 소프트 맥스
z = torch.FloatTensor([1, 2, 3])
h1 = F.softmax(z, dim = 0)
print(h1) # 0.0900, 0.2447, 0.6652

z = torch.rand(3, 5, requires_grad = True)
h1 = F.softmax(z, dim = 1)
print(h1)

y = torch.randint(5, (3,)).long()
y_one = torch.zeros_like(h1)
y_one.scatter_(1, y.unsqueeze(1), 1) #scatter: (차원, 인덱스, 할당값 텐서)
cost = (y_one * -torch.log(h1)).sum(dim = 1).mean()
print(cost) # 1.5770

class와 F.cross_entropy()로 한 번에 표현

class SoftmaxClassifierModel(nn.Module):
    def __init__(self):
        super().__init__()
        self.linear = nn.Linear(4, 3) # Output이 3!

    def forward(self, x):
        return self.linear(x)

x_train = [[1, 2, 1, 1],
           [2, 1, 3, 2],
           [3, 1, 3, 4],
           [4, 1, 5, 5],
           [1, 7, 5, 5],
           [1, 2, 5, 6],
           [1, 6, 6, 6],
           [1, 7, 7, 7]]
y_train = [2, 2, 2, 1, 1, 1, 0, 0]
x_train = torch.FloatTensor(x_train)
y_train = torch.LongTensor(y_train)
model = SoftmaxClassifierModel()

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

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

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

    # cost 계산
    cost = F.cross_entropy(prediction, y_train)

    # cost로 H(x) 개선
    optimizer.zero_grad()
    cost.backward()
    optimizer.step()

    # 20번마다 로그 출력
    if epoch % 100 == 0:
        print('Epoch {:4d}/{} Cost: {:.6f}'.format(
            epoch, nb_epochs, cost.item()
        ))
반응형