지난 강의보다 더 심도 깊은 모델입니다.

    **기존 모델에 Hidden layer 추가**
class BinaryCircleV2(nn.Module):
    
    
    def __init__(self):
        
        super().__init__()
        
        self.hidden_1 = nn.Linear(in_features=2, out_features=10) # 2 -> 10 (there is no activation function yet.)
        self.hidden_2 = nn.Linear(in_features=10, out_features=10) # 10 -> 10 (there is no activation function yet.)
        self.hidden_3 = nn.Linear(in_features=10, out_features=1) # 10 -> 1 (-> sigmoid)
    
    
    def forward(self, x):
        
        result = self.hidden_1(x)
        result = self.hidden_2(result)
        result = self.hidden_3(result)
        
        return result
torch.manual_seed(42) # "Manually" set the "seed" for [ nn.Parameter ]

model_v2 = BinaryCircleV2().to(device) # 모델 초기화 

loss_fn = nn.BCEWithLogitsLoss() # Binary Cross-entropy + built-in Sigmoid (accepting "logits")

optimizer = torch.optim.Adam(params=model_v2.parameters(),  # "parameters" to optimize (apply gradient descent)
                             lr=0.01) # "l"earning "r"ate 
torch.manual_seed(42)

X_train, y_train = X_train.to(device), y_train.to(device)
X_test, y_test = X_test.to(device), y_test.to(device)

for epoch in range(1000): # epoch 변경 : 100 -> 1000
    
    # 모델을 training mode로 설정 (default state)
    model_v2.train()

    # 1. (x 데이터를 모델에 넣고) 순방향 계산 진행 (forward pass)
    logits = model_v2(X_train)
    y_predicted = torch.round(torch.sigmoid(logits)) #  logits -> predicted probabilities -> predicted class numbers

    # 2. Training cost 계산 (Cost function 계산)
    loss_train = loss_fn(logits, y_train) # <- nn.BCEWithLogitsLoss() : built-in Sigmoid
    # loss_train = loss_fn(torch.sigmoid(logits), y_train) # <- nn.BCELoss() : we need to apply sigmoid first

    # 3. Optimizer 내부의 이전 gradient 값 초기화 (Make "grad" to "zero")
    optimizer.zero_grad()

    # 4. Back-propagation ("Backward" propagation)
    loss_train.backward()

    # 5. Gradient descent 진행 (Take a "step" to update parameters)
    optimizer.step()

    
    # 모델을 evaluation mode로 설정
    model_v2.eval()
    
    with torch.inference_mode(): # Set "inference mode"
        
        # (x 데이터를 모델에 넣고) 순방향 계산 진행 (forward pass)
        logits_test = model_v2(X_test)
        y_predicted_test = torch.round(torch.sigmoid(logits_test))
        
        # Test cost 계산
        loss_test = loss_fn(logits_test, y_test)
        

    acc_train = get_accuracy(y_true=y_train, y_pred=y_predicted) 
    acc_test  = get_accuracy(y_true=y_test, y_pred=y_predicted_test)
    
    
    if epoch % 100 == 0:
        print(f"Epoch: {epoch} | Loss: {loss_train:.5f}, Acc: {acc_train:.2f}% | Test loss: {loss_test:.5f}, Test acc: {acc_test:.2f}%")

Epoch: 0 | Loss: 0.69379, Acc: 50.86% | Test loss: 0.69426, Test acc: 48.00% Epoch: 100 | Loss: 0.69279, Acc: 53.43% | Test loss: 0.69523, Test acc: 50.33% Epoch: 200 | Loss: 0.69279, Acc: 53.57% | Test loss: 0.69524, Test acc: 50.33% Epoch: 300 | Loss: 0.69279, Acc: 53.43% | Test loss: 0.69526, Test acc: 50.67% Epoch: 400 | Loss: 0.69279, Acc: 53.57% | Test loss: 0.69524, Test acc: 50.33% Epoch: 500 | Loss: 0.69279, Acc: 53.57% | Test loss: 0.69524, Test acc: 50.33% Epoch: 600 | Loss: 0.69279, Acc: 53.57% | Test loss: 0.69524, Test acc: 50.33% Epoch: 700 | Loss: 0.69279, Acc: 53.43% | Test loss: 0.69525, Test acc: 50.67% Epoch: 800 | Loss: 0.69279, Acc: 53.57% | Test loss: 0.69524, Test acc: 50.33% Epoch: 900 | Loss: 0.69279, Acc: 53.57% | Test loss: 0.69524, Test acc: 50.33%

plt.figure(figsize=(12, 6), dpi=150) # figure size & dot per inch

plt.subplot(1, 2, 1)
plt.title("Train")
plot_decision_boundary(model_v2, X_train, y_train)

plt.subplot(1, 2, 2)
plt.title("Test")
plot_decision_boundary(model_v2, X_test, y_test)

image.png

    **기존 모델에 Non-linearity (비선형성) 추가**
# # Activations @ <https://pytorch.org/docs/stable/nn.html#non-linear-activations-weighted-sum-nonlinearity>

torch.nn.ReLU
torch.nn.ELU 
torch.nn.PReLU 
torch.nn.LeakyReLU
torch.nn.Sigmoid 
torch.nn.Tanh 
torch.nn.Softmax

# # RReLu, SELU, CELU, GELU, ReLU6, 
# # Threshold, Hardshrink, HardTanh,LogSigmoid, Softplus, SoftShrink,
# # Softsign, TanhShrink, Softmin, Softmax2d, LogSoftmax, AdaptiveSoftmaxWithLoss

torch.nn.modules.activation.Softmax

class BinaryCircleV3(nn.Module):
    
    
    def __init__(self):
        
        super().__init__()
        
        self.hidden_1 = nn.Linear(in_features=2, out_features=10) # 2 -> 10 (there is no activation function yet.)
        self.hidden_2 = nn.Linear(in_features=10, out_features=10) # 10 -> 10 (there is no activation function yet.)
        self.hidden_3 = nn.Linear(in_features=10, out_features=1) # 10 -> 1 (-> sigmoid)
        self.relu = nn.ReLU() # ReLU Activation function (or ELU / PReLU / LeakyReLU / Sigmoid / Tanh / etc.)
    
    
    def forward(self, x):
        
        z = self.hidden_1(x) # x -> hidden_1
        z = self.relu(z) # hidden_1 -> ReLU
        z = self.hidden_2(z) # ReLU -> hidden_2
        z = self.relu(z) # hidden_2 -> ReLU
        z = self.hidden_3(z) # ReLU -> hidden_3
        
        return z
torch.manual_seed(42) # "Manually" set the "seed" for [ nn.Parameter ]

model_v3 = BinaryCircleV3().to(device) # 모델 초기화 

loss_fn = nn.BCEWithLogitsLoss() # Binary Cross-entropy + built-in Sigmoid (accepting "logits")

optimizer = torch.optim.Adam(params=model_v3.parameters(),  # "parameters" to optimize (apply gradient descent)
                             lr=0.01) # "l"earning "r"ate 
torch.manual_seed(42)

X_train, y_train = X_train.to(device), y_train.to(device)
X_test, y_test = X_test.to(device), y_test.to(device)

for epoch in range(1000): # epoch 변경 : 100 -> 1000
    
    # 모델을 training mode로 설정 (default state)
    model_v3.train()

    # 1. (x 데이터를 모델에 넣고) 순방향 계산 진행 (forward pass)
    logits = model_v3(X_train)
    y_predicted = torch.round(torch.sigmoid(logits)) #  logits -> predicted probabilities -> predicted class numbers

    # 2. Training cost 계산 (Cost function 계산)
    loss_train = loss_fn(logits, y_train) # <- nn.BCEWithLogitsLoss() : built-in Sigmoid
    # loss_train = loss_fn(torch.sigmoid(logits), y_train) # <- nn.BCELoss() : we need to apply sigmoid first

    # 3. Optimizer 내부의 이전 gradient 값 초기화 (Make "grad" to "zero")
    optimizer.zero_grad()

    # 4. Back-propagation ("Backward" propagation)
    loss_train.backward()

    # 5. Gradient descent 진행 (Take a "step" to update parameters)
    optimizer.step()

    
    # 모델을 evaluation mode로 설정
    model_v3.eval()
    
    with torch.inference_mode(): # Set "inference mode"
        
        # (x 데이터를 모델에 넣고) 순방향 계산 진행 (forward pass)
        logits_test = model_v3(X_test)
        y_predicted_test = torch.round(torch.sigmoid(logits_test))
        
        # Test cost 계산
        loss_test = loss_fn(logits_test, y_test)
        

    acc_train = get_accuracy(y_true=y_train, y_pred=y_predicted) 
    acc_test  = get_accuracy(y_true=y_test, y_pred=y_predicted_test)
    
    
    if epoch % 100 == 0:
        print(f"Epoch: {epoch} | Loss: {loss_train:.5f}, Acc: {acc_train:.2f}% | Test loss: {loss_test:.5f}, Test acc: {acc_test:.2f}%")

Epoch: 0 | Loss: 0.69276, Acc: 50.86% | Test loss: 0.69278, Test acc: 48.00% Epoch: 100 | Loss: 0.15637, Acc: 99.57% | Test loss: 0.18120, Test acc: 98.33% Epoch: 200 | Loss: 0.01240, Acc: 100.00% | Test loss: 0.02351, Test acc: 100.00% Epoch: 300 | Loss: 0.00495, Acc: 100.00% | Test loss: 0.01286, Test acc: 100.00% Epoch: 400 | Loss: 0.00279, Acc: 100.00% | Test loss: 0.00944, Test acc: 100.00% Epoch: 500 | Loss: 0.00181, Acc: 100.00% | Test loss: 0.00768, Test acc: 100.00% Epoch: 600 | Loss: 0.00128, Acc: 100.00% | Test loss: 0.00659, Test acc: 100.00% Epoch: 700 | Loss: 0.00096, Acc: 100.00% | Test loss: 0.00583, Test acc: 100.00% Epoch: 800 | Loss: 0.00074, Acc: 100.00% | Test loss: 0.00529, Test acc: 100.00% Epoch: 900 | Loss: 0.00059, Acc: 100.00% | Test loss: 0.00489, Test acc: 100.00%