Task마다 다양한 Loss function들이 있다.
구현은 Pytorch를 이용해서 쉽게 가능하다.
Task에 맞는 loss할당하고 y와 y_hat사이의 에러값 구해서 학습시키는 방식
import torch.nn as nn
loss = nn.CrossEntropyLoss()
loss_out = loss(y,y_hat)
optm.zero_grad() # reset gradient
loss_out.backward() # backpropagate
optm.step()
유클라디안 거리를 이용해 회귀문제, 분류문제, 이미지 복구(이미지 간의 차)나 이미지 세그멘테이션(mask간의 차)에서도 사용된다.
MAE방식으로 평균절댓값에러 -L1 norm사용
loss = nn.L1Loss()
input = torch.randn(3, 5, requires_grad=True)
target = torch.randn(3, 5)
output = loss(input, target)
output.backward()
MSE방식으로 평균제곱에러 -L2 norm사용
loss = nn.MSELoss()
input = torch.randn(3, 5, requires_grad=True)
target = torch.randn(3, 5)
output = loss(input, target)
output.backward()
L1loss와 MSEloss의 장점을 합친 손실함수이다. L1에서 아웃라이어들에 대해 MSE에 비해 덜 민감하게 하고, MSE에서 0근처에서 L1에 비해 더 매끄럽게 표현한다.
L1loss를 약간 매끄럽게 만든 손실함수이다. exploding gradient문제를 막기위해 Fast-CNN에서도 사용되었다.
매끄러움의 정도를 결정하는 beta값을 조정함에 따라 MSELoss, L1Loss, HuberLoss와 같아지기도 한다.
분류문제에서 많이 사용된다.
다중 분류문제에 사용되는 loss function
softmax와 cross-entropy를 합쳐놓은걸로 제공하기 때문에 마지막 layer에 softmax사용하지 않는다.
input = torch.randn(3, 5, requires_grad=True)
target = torch.randn(3, 5).softmax(dim=1)
output = loss(input, target)
output.backward()
다중 분류문제에 사용되며 crossentropyloss와 다른점은 활성화 함수가 포함되어 있지 않다. 또한 불균형 데이터 세트에 대해서 weight를 추가할 수 있다. 활성화 함수로는 LogSoftMax를 사용한다.
m = nn.LogSoftmax(dim=1)
loss = nn.NLLLoss()
input = torch.randn(3, 5, requires_grad=True)
target = torch.tensor([1, 0, 4])
output = loss(m(input), target)
output.backward()
CrossEntropyLoss = LogSoftmax + NLLLoss
타켓이 푸아송분포를 따르는 경우일때의 NLLloss버전이다.
loss = nn.PoissonNLLLoss()
log_input = torch.randn(5, 2, requires_grad=True)
target = torch.randn(5, 2)
output = loss(log_input, target)
output.backward()
타켓이 가우시안분포를 따르는 경우일때의 NLLloss버전이다.
loss = nn.GaussianNLLLoss()
log_input = torch.randn(5, 2, requires_grad=True)
target = torch.randn(5, 2)
output = loss(log_input, target)
output.backward()
이진 분류문제에 주로 사용되고 안에 활성화함수가 없어서 마지막 레이어에 추가해야함.
m = nn.Sigmoid()
loss = nn.BCELoss()
input = torch.randn(3, requires_grad=True)
target = torch.empty(3).random_(2)
output = loss(m(input), target)
output.backward()
nn.BCELoss 에 Sigmoid 함수가 포함된 형태여서 따로 활성화함수를 사용하지 않아도 된다. sigmoid와 nn.BCELoss를 사용하는것보다 nn.BCEWithLogitsLoss를 사용하는게 더 안정적이다.
loss = nn.BCEWithLogitsLoss()
input = torch.randn(3, requires_grad=True)
target = torch.empty(3).random_(2)
output = loss(input, target)
output.backward()
분류문제에서 BCE나 CE를 쓰는 것과 동일한 효과이다. 둘 사이의 분포가 얼마나 다른지를 나타내기 때문에 둘 사이의 정보 손실을 이용한 손실함수이다.
kl_loss = nn.KLDivLoss(reduction="batchmean")
# input should be a distribution in the log space
input = F.log_softmax(torch.randn(3, 5, requires_grad=True))
# Sample a batch of distributions. Usually this would come from the dataset
target = F.softmax(torch.rand(3, 5))
output = kl_loss(input, target)
kl_loss = nn.KLDivLoss(reduction="batchmean", log_target=True)
log_target = F.log_softmax(torch.rand(3, 5))
output = kl_loss(input, log_target)
여러개의 입력이 주어질때 입력간의 상대적인 순위를 구하는 방식이다. input들끼리의 상대적인 거리를 예측하는데 분류문제에서 CE대신 사용하기도한다.
예측에 실패해도 순위에 따라 학습했기 때문에 다른 오답레이블보다 순위가 높은게 좋기 때문이다.
입력값은 시계열이고 타깃값이 시퀀스일때 그 사이의 손실함수를 계산한다.
인풋에서 타깃의 가능한 alignment의 확률을 더한다.
타임시리즈의 인풋과 시퀀스인 타깃값 형태이고, CTCLoss는 인풋에서 타깃으로의 가능한 alignment의 확률을 더한다. 각각의 인풋노드에서 미분을 진행하고, 여기서는 인풋의 alignment에서 타깃이 다대일 형태임을 가정하기 때문에 인풋의 길이가 더 길다.
CTC는 입력 음성 프레임 시퀀스와 타겟 단어/음소 시퀀스 간에 명시적인 얼라인먼트(alignment) 정보 없이도 음성 인식 모델을 학습할 수 있는 기법이다.
음성 피처 시퀀스와 타킷 시퀀스에서, 둘의 길이가 다르기 때문에 크로스 엔트로피를 적용할 수 없기때문에 사용된다.
# Target are to be padded
T = 50 # Input sequence length
C = 20 # Number of classes (including blank)
N = 16 # Batch size
S = 30 # Target sequence length of longest target in batch (padding length)
S_min = 10 # Minimum target length, for demonstration purposes
# Initialize random batch of input vectors, for *size = (T,N,C)
input = torch.randn(T, N, C).log_softmax(2).detach().requires_grad_()
# Initialize random batch of targets (0 = blank, 1:C = classes)
target = torch.randint(low=1, high=C, size=(N, S), dtype=torch.long)
input_lengths = torch.full(size=(N,), fill_value=T, dtype=torch.long)
target_lengths = torch.randint(low=S_min, high=S, size=(N,), dtype=torch.long)
ctc_loss = nn.CTCLoss()
loss = ctc_loss(input, target, input_lengths, target_lengths)
loss.backward()
# Target are to be un-padded
T = 50 # Input sequence length
C = 20 # Number of classes (including blank)
N = 16 # Batch size
# Initialize random batch of input vectors, for *size = (T,N,C)
input = torch.randn(T, N, C).log_softmax(2).detach().requires_grad_()
input_lengths = torch.full(size=(N,), fill_value=T, dtype=torch.long)
# Initialize random batch of targets (0 = blank, 1:C = classes)
target_lengths = torch.randint(low=1, high=T, size=(N,), dtype=torch.long)
target = torch.randint(low=1, high=C, size=(sum(target_lengths),), dtype=torch.long)
ctc_loss = nn.CTCLoss()
loss = ctc_loss(input, target, input_lengths, target_lengths)
loss.backward()
# Target are to be un-padded and unbatched (effectively N=1)
T = 50 # Input sequence length
C = 20 # Number of classes (including blank)
# Initialize random batch of input vectors, for *size = (T,C)
input = torch.randn(T, C).log_softmax(2).detach().requires_grad_()
input_lengths = torch.tensor(T, dtype=torch.long)
# Initialize random batch of targets (0 = blank, 1:C = classes)
target_lengths = torch.randint(low=1, high=T, size=(), dtype=torch.long)
target = torch.randint(low=1, high=C, size=(target_lengths,), dtype=torch.long)
ctc_loss = nn.CTCLoss()
loss = ctc_loss(input, target, input_lengths, target_lengths)
loss.backward()
두 인풋들이 비슷한지 아닌지에 대해 측정하기 위해 사용되는 손실함수이다. 코사인 유사도를 사용하고 nonlinear임베딩이나 semi-supervised learning에 사용된다.
https://pytorch.org/docs/stable/nn.html#loss-functions (Pytorch documentation)
https://ratsgo.github.io/speechbook/docs/neuralam/ctc (CTC상세)