파이토치에서 크로스 엔트로피 손실 사용 시 출력에 소프트맥스를 사용해야 할까요? (Python, PyTorch, MNIST)
- 일반적으로 네, 크로스 엔트로피 손실 함수와 함께 소프트맥스 활성화 함수를 사용하는 것이 좋습니다.
- 하지만, 사용하는 손실 함수에 따라 다릅니다.
nn.CrossEntropyLoss
함수는 내부적으로 로그 소프트맥스를 포함하고 있으므로 별도의 소프트맥스 활성화 함수가 필요하지 않습니다.nn.NLLLoss
함수는 로그 소프트맥스를 포함하지 않으므로 직접 소프트맥스 활성화 함수를 사용해야 합니다.
- MNIST 분류 예시 코드를 통해 각 경우의 구현 방법을 확인할 수 있습니다.
소프트맥스와 크로스 엔트로피 손실
- 소프트맥스는 다중 클래스 분류 문제에서 예측 확률을 계산하는 활성화 함수입니다.
- 크로스 엔트로피 손실은 예측 확률 분포와 실제 레이블 간의 차이를 측정하는 손실 함수입니다.
두 함수는 서로 밀접하게 연관되어 있으며, 함께 사용하면 모델의 성능을 향상시키는 데 도움이 됩니다.
파이토치에서의 구현
1 nn.CrossEntropyLoss 사용
import torch
import torch.nn as nn
# MNIST 데이터 로드
train_loader, test_loader = mnist_loaders()
# 모델 정의
class Net(nn.Module):
def __init__(self):
super().__init__()
self.fc1 = nn.Linear(784, 10)
def forward(self, x):
x = x.view(-1, 784)
x = self.fc1(x)
return x
# 모델 생성 및 학습
model = Net()
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)
for epoch in range(10):
for images, labels in train_loader:
outputs = model(images)
loss = criterion(outputs, labels)
optimizer.zero_grad()
loss.backward()
optimizer.step()
# 모델 평가
with torch.no_grad():
correct = 0
total = 0
for images, labels in test_loader:
outputs = model(images)
_, predicted = torch.max(outputs.data, 1)
total += labels.size(0)
correct += (predicted == labels).sum().item()
print(f'Accuracy of the network on the 10000 test images: {100 * correct / total}%')
2 nn.NLLLoss 사용
import torch
import torch.nn as nn
# MNIST 데이터 로드
train_loader, test_loader = mnist_loaders()
# 모델 정의
class Net(nn.Module):
def __init__(self):
super().__init__()
self.fc1 = nn.Linear(784, 10)
def forward(self, x):
x = x.view(-1, 784)
x = self.fc1(x)
return x
# 모델 생성 및 학습
model = Net()
criterion = nn.NLLLoss()
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)
for epoch in range(10):
for images, labels in train_loader:
outputs = model(images)
outputs = nn.functional.softmax(outputs, dim=1)
loss = criterion(outputs, labels)
optimizer.zero_grad()
loss.backward()
optimizer.step()
예제 코드
1 nn.CrossEntropyLoss 사용
import torch
import torch.nn as nn
# MNIST 데이터 로드
train_loader, test_loader = mnist_loaders()
# 모델 정의
class Net(nn.Module):
def __init__(self):
super().__init__()
self.fc1 = nn.Linear(784, 10)
def forward(self, x):
x = x.view(-1, 784)
x = self.fc1(x)
return x
# 모델 생성 및 학습
model = Net()
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)
for epoch in range(10):
for images, labels in train_loader:
outputs = model(images)
loss = criterion(outputs, labels)
optimizer.zero_grad()
loss.backward()
optimizer.step()
# 모델 평가
with torch.no_grad():
correct = 0
total = 0
for images, labels in test_loader:
outputs = model(images)
_, predicted = torch.max(outputs.data, 1)
total += labels.size(0)
correct += (predicted == labels).sum().item()
print(f'Accuracy of the network on the 10000 test images: {100 * correct / total}%')
2 nn.NLLLoss 사용
import torch
import torch.nn as nn
# MNIST 데이터 로드
train_loader, test_loader = mnist_loaders()
# 모델 정의
class Net(nn.Module):
def __init__(self):
super().__init__()
self.fc1 = nn.Linear(784, 10)
def forward(self, x):
x = x.view(-1, 784)
x = self.fc1(x)
return x
# 모델 생성 및 학습
model = Net()
criterion = nn.NLLLoss()
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)
for epoch in range(10):
for images, labels in train_loader:
outputs = model(images)
outputs = nn.functional.softmax(outputs, dim=1)
loss = criterion(outputs, labels)
optimizer.zero_grad()
loss.backward()
optimizer.step()
# 모델 평가
with torch.no_grad():
correct = 0
total = 0
for images, labels in test_loader:
outputs = model(images)
outputs = nn.functional.softmax(outputs, dim=1)
_, predicted = torch.max(outputs.data, 1)
total += labels.size(0)
correct += (predicted == labels).sum().item()
print(f'Accuracy of the network on the 10000 test images: {100 * correct / total}%')
- 위 코드는 MNIST 분류 예시이며, 다른 문제에 적용하기 위해서는 수정해야 할 수도 있습니다.
nn.CrossEntropyLoss
함수는log_softmax
연산을 내부적으로 수행하므로, 따로softmax
연산을 수행할 필요는 없습니다.nn.NLLLoss
함수는log_softmax
연산을 포함하지 않으므로,softmax
연산을 직접 수행해야 합니다.
소프트맥스 대신 사용할 수 있는 방법
Sigmoid:
- 이진 분류 문제에서 사용됩니다.
- 출력 값은 0과 1 사이의 확률을 나타냅니다.
import torch
import torch.nn as nn
# 이진 분류 모델 정의
class Net(nn.Module):
def __init__(self):
super().__init__()
self.fc1 = nn.Linear(784, 1)
def forward(self, x):
x = x.view(-1, 784)
x = self.fc1(x)
x = torch.sigmoid(x)
return x
# 모델 생성 및 학습
model = Net()
criterion = nn.BCEWithLogitsLoss()
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)
for epoch in range(10):
for images, labels in train_loader:
outputs = model(images)
loss = criterion(outputs, labels)
optimizer.zero_grad()
loss.backward()
optimizer.step()
# 모델 평가
with torch.no_grad():
correct = 0
total = 0
for images, labels in test_loader:
outputs = model(images)
outputs = (outputs > 0.5).float()
total += labels.size(0)
correct += (outputs == labels).sum().item()
print(f'Accuracy of the network on the 10000 test images: {100 * correct / total}%')
Gumbel Softmax:
- 샘플링 과정을 통해 다양한 예측 결과를 생성합니다.
import torch
import torch.nn as nn
import torch.distributions as dist
# 확률적 분류 모델 정의
class Net(nn.Module):
def __init__(self):
super().__init__()
self.fc1 = nn.Linear(784, 10)
def forward(self, x):
x = x.view(-1, 784)
x = self.fc1(x)
return gumbel_softmax(x, temperature=1.0)
# 모델 생성 및 학습
model = Net()
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)
for epoch in range(10):
for images, labels in train_loader:
outputs = model(images)
loss = criterion(outputs, labels)
optimizer.zero_grad()
loss.backward()
optimizer.step()
# 모델 평가
with torch.no_grad():
correct = 0
total = 0
for images, labels in test_loader:
outputs = model(images)
_, predicted = torch.max(outputs.data, 1)
total += labels.size(0)
correct += (predicted == labels).sum().item()
print(f'Accuracy of the network on the 10000 test images: {100 * correct / total}%')
Noisy Softmax:
- 데이터 증강 효과를 제공합니다.
- 모델의 일반화 성능을 향상시킬 수 있습니다.
import torch
import torch.nn as nn
import torch.distributions as dist
# 데이터 증강 효과를 제공하는 모델 정의
class Net(nn.Module):
def __init__(self):
super().__init__()
self.fc1 = nn.Linear(784, 10)
def forward(self, x):
x = x.view(-1, 784)
x = self.fc1(x)
return noisy_softmax(x, temperature=1.0)
# 모델 생성 및 학습
model = Net()
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)
for epoch in range(10):
python pytorch mnist