파이토치에서 멀티 손실 처리 방법
파이토치에서 멀티 손실 처리 방법
가중치 조합
가장 간단한 방법은 각 손실 함수에 가중치를 부여하고 그 합을 최소화하는 것입니다.
import torch
def my_loss(y_pred, y_true):
loss1 = torch.nn.CrossEntropyLoss()(y_pred, y_true)
loss2 = torch.nn.MSELoss()(y_pred, y_true)
return loss1 + 0.5 * loss2
# 모델 학습
model = torch.nn.Sequential(
torch.nn.Linear(10, 10),
torch.nn.ReLU(),
torch.nn.Linear(10, 1)
)
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)
for epoch in range(100):
# ...
outputs = model(x)
loss = my_loss(outputs, y)
optimizer.zero_grad()
loss.backward()
optimizer.step()
손실 함수 정의
여러 손실 함수를 하나의 함수로 정의할 수 있습니다.
import torch
def my_loss(y_pred, y_true):
loss1 = torch.nn.CrossEntropyLoss()(y_pred, y_true)
loss2 = torch.nn.MSELoss()(y_pred, y_true)
return loss1, loss2
# 모델 학습
model = torch.nn.Sequential(
torch.nn.Linear(10, 10),
torch.nn.ReLU(),
torch.nn.Linear(10, 1)
)
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)
for epoch in range(100):
# ...
outputs = model(x)
loss1, loss2 = my_loss(outputs, y)
# 각 손실 함수에 대한 가중치를 설정
loss = loss1 + 0.5 * loss2
optimizer.zero_grad()
loss.backward()
optimizer.step()
nn.ModuleDict 사용
nn.ModuleDict
를 사용하면 여러 손실 함수를 딕셔너리 형태로 관리할 수 있습니다.
import torch
class MyModel(torch.nn.Module):
def __init__(self):
super().__init__()
self.loss_dict = nn.ModuleDict({
"loss1": torch.nn.CrossEntropyLoss(),
"loss2": torch.nn.MSELoss()
})
def forward(self, x):
# ...
def loss(self, y_pred, y_true):
losses = {}
for name, loss_fn in self.loss_dict.items():
losses[name] = loss_fn(y_pred, y_true)
return losses
# 모델 학습
model = MyModel()
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)
for epoch in range(100):
# ...
outputs = model(x)
losses = model.loss(outputs, y)
# 각 손실 함수에 대한 가중치를 설정
loss = sum(losses.values())
optimizer.zero_grad()
loss.backward()
optimizer.step()
추가 정보
예제 코드
가중치 조합
import torch
def my_loss(y_pred, y_true):
loss1 = torch.nn.CrossEntropyLoss()(y_pred, y_true)
loss2 = torch.nn.MSELoss()(y_pred, y_true)
return loss1 + 0.5 * loss2
# 모델 학습
model = torch.nn.Sequential(
torch.nn.Linear(10, 10),
torch.nn.ReLU(),
torch.nn.Linear(10, 1)
)
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)
for epoch in range(100):
# ...
outputs = model(x)
loss = my_loss(outputs, y)
optimizer.zero_grad()
loss.backward()
optimizer.step()
손실 함수 정의
import torch
def my_loss(y_pred, y_true):
loss1 = torch.nn.CrossEntropyLoss()(y_pred, y_true)
loss2 = torch.nn.MSELoss()(y_pred, y_true)
return loss1, loss2
# 모델 학습
model = torch.nn.Sequential(
torch.nn.Linear(10, 10),
torch.nn.ReLU(),
torch.nn.Linear(10, 1)
)
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)
for epoch in range(100):
# ...
outputs = model(x)
loss1, loss2 = my_loss(outputs, y)
# 각 손실 함수에 대한 가중치를 설정
loss = loss1 + 0.5 * loss2
optimizer.zero_grad()
loss.backward()
optimizer.step()
nn.ModuleDict 사용
import torch
class MyModel(torch.nn.Module):
def __init__(self):
super().__init__()
self.loss_dict = nn.ModuleDict({
"loss1": torch.nn.CrossEntropyLoss(),
"loss2": torch.nn.MSELoss()
})
def forward(self, x):
# ...
def loss(self, y_pred, y_true):
losses = {}
for name, loss_fn in self.loss_dict.items():
losses[name] = loss_fn(y_pred, y_true)
return losses
# 모델 학습
model = MyModel()
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)
for epoch in range(100):
# ...
outputs = model(x)
losses = model.loss(outputs, y)
# 각 손실 함수에 대한 가중치를 설정
loss = sum(losses.values())
optimizer.zero_grad()
loss.backward()
optimizer.step()
추가 정보
멀티 손실 처리 방법의 대체 방법
가중치 조합 (동적)
위 코드에서 각 손실 함수에 대한 가중치를 고정하는 대신 학습 과정에서 동적으로 변경할 수 있습니다.
import torch
def my_loss(y_pred, y_true):
loss1 = torch.nn.CrossEntropyLoss()(y_pred, y_true)
loss2 = torch.nn.MSELoss()(y_pred, y_true)
# 가중치를 학습 변수로 설정
w1 = torch.nn.Parameter(torch.ones(1))
w2 = torch.nn.Parameter(torch.ones(1))
return w1 * loss1 + w2 * loss2
# 모델 학습
model = torch.nn.Sequential(
torch.nn.Linear(10, 10),
torch.nn.ReLU(),
torch.nn.Linear(10, 1)
)
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)
for epoch in range(100):
# ...
outputs = model(x)
loss = my_loss(outputs, y)
optimizer.zero_grad()
loss.backward()
optimizer.step()
손실 함수 스케일링
각 손실 함수의 출력 범위가 다를 경우 스케일링을 통해 동일한 범위로 맞춰줍니다.
import torch
def my_loss(y_pred, y_true):
loss1 = torch.nn.CrossEntropyLoss()(y_pred, y_true)
loss2 = torch.nn.MSELoss()(y_pred, y_true)
# 손실 함수 스케일링
loss1 = loss1 / 100
return loss1 + loss2
# 모델 학습
model = torch.nn.Sequential(
torch.nn.Linear(10, 10),
torch.nn.ReLU(),
torch.nn.Linear(10, 1)
)
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)
for epoch in range(100):
# ...
outputs = model(x)
loss = my_loss(outputs, y)
optimizer.zero_grad()
loss.backward()
optimizer.step()
손실 함수 선택
문제에 따라 적합한 손실 함수를 선택하는 것이 중요합니다. 예를 들어, 분류 문제에는 CrossEntropyLoss, 회귀 문제에는 MSELoss를 사용하는 것이 일반적입니다.
여러 손실 함수를 결합하여 새로운 손실 함수를 만들 수 있습니다. 예를 들어, 다음과 같이 L1 and L2 regularization을 사용할 수 있습니다.
import torch
def my_loss(y_pred, y_true):
loss1 = torch.nn.CrossEntropyLoss()(y_pred, y_true)
loss2 = torch.nn.MSELoss()(y_pred, y_true)
# L1 and L2 regularization
reg_loss = torch.nn.L1Loss()(y_pred, y_true) + torch.nn.L2Loss()(y_pred, y_true)
return loss1 + loss2 + reg_loss
# 모델 학습
model = torch.nn.Sequential(
torch.nn.Linear(10, 10),
torch.nn.ReLU(),
torch.nn.Linear(10, 1)
)
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)
for epoch in range(100):
# ...
outputs = model(x)
loss = my_loss(outputs, y)
optimizer.zero_grad()
loss.backward()
optimizer.step()
- [Loss Functions in Py
python pytorch