지난 강의보다 더 심도 깊은 모델입니다.
**기존 모델에 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)

**기존 모델에 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%