본문 바로가기
Artificial Intelligence/60. Python

[PYTHON] Multi-Task Learning 손실 함수 가중치 동적 조절 방법과 3가지 성능 차이 해결 전략

by Papa Martino V 2026. 4. 15.
728x90

Multi-Task Learning
Multi-Task Learning

 

딥러닝 모델이 한 번에 여러 개의 작업을 수행해야 하는 멀티태스크 학습(Multi-Task Learning, MTL)은 자원 효율성과 일반화 성능 측면에서 강력한 장점을 가집니다. 하지만 실무에서 MTL 모델을 설계할 때 가장 큰 걸림돌은 "어떤 태스크의 손실(Loss)에 더 비중을 둘 것인가?"라는 문제입니다. 단순히 각 손실을 더하는 방식(Naive Sum)은 각 태스크의 규모(Scale)나 학습 난이도 차이로 인해 특정 태스크만 학습되고 나머지는 무시되는 결과를 초래합니다. 본 가이드에서는 이러한 수동 튜닝의 한계를 극복하기 위해 제안된 Uncertainty Weighting(불확실성 가중치) 기법을 심층적으로 다룹니다. 각 태스크의 동적인 불확실성을 학습 파라미터로 설정하여 최적의 손실 가중치를 스스로 찾아가는 수학적 근거와 이를 파이썬(PyTorch)으로 구현하는 7가지 핵심 실무 전략을 상세히 공유합니다.


1. 수동 가중치 vs 동적 가중치(Uncertainty)의 구조적 차이 비교

MTL 모델의 성능 차이를 결정짓는 핵심은 태스크 간의 '경쟁'을 어떻게 중재하느냐에 있습니다. 아래 표는 전통적인 방식과 동적 조절 방식의 기술적 차이를 요약한 것입니다.

비교 항목 Uniform Weighting (고정) Uncertainty Weighting (동적) 비고
최적화 방식 사용자가 $w_1, w_2$ 직접 할당 모델이 로그 우도(Log-likelihood) 기반 학습 자동화 수준 차이
태스크 규모 차이 규모가 큰 손실에 편향됨 분산을 고려하여 정규화 수행 스케일링 문제 해결
학습 안정성 낮음 (반복적인 재학습 필요) 높음 (자동 수렴 유도) 유지보수 비용 감소
성능 잠재력 서브 태스크 성능 저하 위험 균형 잡힌 파레토 최적점 도달 글로벌 최적화 유리

2. Uncertainty Weighting의 수학적 메커니즘

Kendall 등(2018)이 제안한 이 기법은 각 태스크의 Homoscedastic Uncertainty(동질적 불확실성)를 모델링합니다. 멀티태스크 손실 함수는 다음과 같은 형태로 정의됩니다.

$$L_{total} = \sum_{i} \frac{1}{2\sigma_i^2} L_i + \log \sigma_i$$

여기서 $\sigma_i$는 태스크 $i$의 노이즈 강도를 나타내는 학습 가능한 파라미터입니다. 모델은 손실 $L_i$가 클 때 $\sigma_i$를 키워 첫 번째 항을 줄이려 하지만, 두 번째 항인 정규화 요소($\log \sigma_i$)에 의해 무한정 커지는 것이 억제됩니다. 이 균형점을 찾는 과정이 바로 최적의 가중치를 찾는 과정이 됩니다.


3. 개발자가 실무에 바로 적용 가능한 실전 예제 (7가지 방법)

파이썬의 PyTorch 프레임워크를 사용하여 MTL의 고질적인 문제를 해결하는 구체적인 코드 예시입니다.

Example 1: Multi-Task Loss Wrapper 기본 클래스 구현

import torch
import torch.nn as nn

class UncertaintyWeighting(nn.Module):
    def __init__(self, num_tasks):
        super(UncertaintyWeighting, self).__init__()
        # 로그 분산 파라미터 초기화 (학습 가능하게 설정)
        self.log_vars = nn.Parameter(torch.zeros(num_tasks))

    def forward(self, *losses):
        total_loss = 0
        for i, loss in enumerate(losses):
            precision = torch.exp(-self.log_vars[i])
            total_loss += precision * loss + self.log_vars[i]
        return total_loss
    

Example 2: 분류(Classification)와 회귀(Regression) 복합 태스크 해결

두 태스크의 손실 함수 스케일이 다를 때 적용하는 방법입니다.

# 회귀용 MSE와 분류용 CrossEntropy가 섞인 경우
criterion_mtl = UncertaintyWeighting(num_tasks=2)
loss_reg = nn.MSELoss()(pred_reg, target_reg)
loss_cls = nn.CrossEntropyLoss()(pred_cls, target_cls)

# 동적 가중치 적용
total_loss = criterion_mtl(loss_reg, loss_cls)
total_loss.backward()
    

Example 3: 시계열 데이터와 이미지 데이터의 동시 학습 (Domain Difference)

# 데이터 도메인마다 발생하는 노이즈 차이를 상쇄하는 학습 로직
# log_vars의 초기값을 태스크의 중요도에 따라 다르게 설정하여 수렴 속도 제어 가능
class DomainAwareWeighting(UncertaintyWeighting):
    def __init__(self, num_tasks):
        super().__init__(num_tasks)
        nn.init.constant_(self.log_vars, 0.5) # 초기 불확실성을 높게 설정
    

Example 4: 10개 이상의 대규모 태스크(Large-scale Tasks) 관리

# 태스크가 많을 때 dict 형태로 매핑하여 손실 관리
task_losses = {'segmentation': seg_loss, 'depth': depth_loss, 'edge': edge_loss}
losses_tensor = [task_losses[k] for k in sorted(task_losses.keys())]
final_loss = criterion_mtl(*losses_tensor)
    

Example 5: 특정 태스크 강제 가중치(Priority Task) 부여 방법

# 특정 태스크의 log_var에 상수를 더해 학습의 우선순위를 인위적으로 조정
priority_mask = torch.tensor([1.2, 0.8]) # 태스크 1에 더 높은 가중치 가이드
weighted_loss = (precision * priority_mask[i]) * loss + self.log_vars[i]
    

Example 6: NaN 방지를 위한 안정적인 수치 연산 구현

# log_vars가 너무 작아져 precision이 폭주하는 것을 방지
precision = torch.exp(-self.log_vars[i]).clamp(min=1e-4, max=1e4)
    

Example 7: 학습된 가중치(Sigma) 모니터링 및 시각화

# 학습 중 각 태스크의 시그마(sigma) 값을 추적하여 어떤 태스크가 어려운지 진단
sigmas = torch.exp(criterion_mtl.log_vars)**0.5
for i, s in enumerate(sigmas):
    print(f"Task {i} Uncertainty (Sigma): {s.item():.4f}")
    

4. 결론: 왜 Uncertainty Weighting이 정답인가?

멀티태스크 학습에서 태스크 간의 불균형을 수동으로 잡는 것은 수많은 시행착오와 컴퓨팅 자원을 소모하게 만듭니다. Uncertainty Weighting은 단순한 가중치 조절을 넘어, 각 태스크가 가진 고유한 노이즈 강도를 통계적으로 추정하여 학습 효율을 극대화합니다. 이는 모델이 스스로 중요한 태스크와 노이즈가 많은 태스크를 구분하게 만드는 지능형 학습 환경을 제공합니다.

성능 차이를 해결하고 싶다면, 고정된 상수를 곱하는 방식에서 벗어나 위 7가지 사례를 활용한 동적 가중치 알고리즘을 즉시 도입해 보시길 권장합니다.


내용 출처 및 기술 참조

  • Kendall, A., Gal, Y., & Cipolla, R. (2018). "Multi-task learning using uncertainty to weigh losses for scene geometry and semantics." CVPR.
  • Liebel, L., & Körner, M. (2018). "Auxiliary tasks in multi-task learning." arXiv preprint arXiv:1805.06334.
  • PyTorch Official Documentation: nn.Parameter 및 Autograd 메커니즘 참조.
728x90