손실함수는 정답(y)와 예측(^y)를 입력으로 받아 실숫값 점수를 만드는데, 이 점수가 높을수록 모델이 안좋은 것
손실함수의 함수값이 최소화 되도록 하는 가중치(weight)와 편향(bias)를 찾는 것이 딥러닝 학습의 목표
예측한 값과 실제 값 사이의 평균 제곱 오차를 정의한다. 공식이 매우 간단하며, 차가 커질수록 제곱 연산으로 인해서 값이 더욱 뚜렷해진다. 그리고 제곱으로 인해서 오차가 양수이든 음수이든 누적 값을 증가시킨다.
MSE에 루트(√)를 씌운 것으로 MSE와 기본적으로 동일하다. MSE 값은 오류의 제곱을 구하기 때문에 실제 오류 평균보다 더 커지는 특성이 있어 MSE에 루트를 씌운 RMSE 은 값의 왜곡을 줄여준다.
MSE와 RMSE와 다르게 Crossentropy는 개념은 추후의 포스트에서 설명하기로 한다.
실제 레이블과 예측 레이블 간의 교차 엔트로피 손실을 계산한다. 2개의 레이블 클래스(0, 1로 가정)가 있을 때 Binary Crossentropy를 사용하면 좋다.
활성화 함수 : sigmoid 사용 (출력값이 0과 1사이의 값)
수식은 아래와 같으며
아래 함수에 예측값(Yi) 과 실제값(ti) 에 1을 대입하면, 수식은 0에 수렴하게 됨
아래 함수에 예측값(Yi =0)과 실제값(ti = 1)을 대입한다면, 수식은 양의 무한대가 됨
import tensorflow as tf
import keras
tf.keras.losses.BinaryCrossentropy(from_logits=False, label_smoothing=0, reduction="auto", name="binary_crossentropy")
import torch
import torch.nn as nn
bce_loss = nn.BCELoss()
sigmoid = nn.Sigmoid()
probabilities = sigmoid(torch.randn(4, 1, requires_grad=True)
targets = torch.tensor([1, 0, 1, 0], dtype = torch.float32).view(4, 1)
loss = bce_loss(probabilities, targets)
print(probabilities)
print(loss)
레이블 클래스가 2개 초과일 경우 binary가 아닌 categorical을 사용한다. 보통 softmax 활성화함수 다음에 연계되어 사용되므로 softmax loss로도 불린다.
출력을 클래스 소속 확률에 대한 예측으로 이해할 수 있는 문제에서 사용
라벨이 (0,0,1,0,0) , (0,1,0,0,0) 과 같이 one-hot encoding 된 형태로 제공될 때 사용 가능
아래 수식에서 C 는 클래스의 개수
실제값과 예측값이 모두 동일하게 될 경우 손실함수의 값은 0이 나옴
실제값과 예측값이 다를 경우 수식에 대입하면 양의 무한대로 발산
tf.keras.losses.CategoricalCrossentropy(from_logits=False, label_smoothing = 0, reduction="auto", name = 'catogorical_crossentropy")
import torch
import torch.nn as nn
ce_loss = nn.CrossEntropyLoss()
outputs = torch.randn(3, 5, requires_grad = True)
targets = torch.tensor([1, 0, 3], dtype = torch.int64)
loss = ce_loss(outputs, targets)
print(loss)
랜덤한 벡터를 출력으로 가정하고, 그 target 벡터를 정수 벡터로 만든다. 파이토치의 CrossEntropyLoss 클래스는 각 입력이 클래스 하나에 속하고 각 클래스에는 고유한 인덱스가 있다고 가정하기 때문이다.
범주형 교차 엔트로피와 동일하게 멀티 클래스 분류에 사용
one-hot encoding 된 상태일 필요 없이 정수 인코딩 된 상태에서 수행 가능
라벨이 (1,2,3,4) 이런식으로 정수형태일때 사용!
tf.keras.losses.sparse_categorical_crossentropy(y_true, y_pred, from_logits=False, axis = 1)
Focal loss는 페이스북의 Lin et al. 이 소개했습니다.
RetinaNet 모델을 학습시키는데 Focal loss가 한단계 객체 탐색기를 향상시킵니다.
Focal loss는 분류 에러에 근거한 loss에 가중치를 부여하는데, 샘플이 CNN에 의해 이미 올바르게 분류되었다면 그것에 대한 가중치는 감소합니다. 즉, 좀 더 문제가 있는 loss에 더 집중하는 방식으로 불균형한 클래스 문제를 해결하였습니다.
Focal loss는 Sigmoid activation을 사용하기 때문에, Binary Cross-Entropy loss라고도 할 수 있습니다.
특별히, r = 0 일때 Focal loss는 Binary Cross Entropy Loss와 동일합니다.
from keras import backend as K
import tensorflow as tf
def focal_loss(gamma=2, alpha=.25):
def focal_loss_fixed(y_ture, y_pred):
pt_1 = tf.where(tf.equal(y_true, 1), y_pred, tf.ones_like(y_pred))
pt_0 = tf.where(tf.equal(y_true, 0), y_pred, tf.zeros_like(y_pred))
return -K.mean(alpha * K.pow(1. - pt_1, gamma) * K.log(pt_1)) - K.mean((1 - alpha) *K.pow(pt_0, gamma) * K.log(1. - pt_0))
return focla_loss_fixed
import torch
import torch.nn as nn
import torch.nn.functional as F
from torch.autograd import Variable
class FocalLoss(nn.Module):
def init(self, gamma=0, alpha=None, size_average=True):
super(FocalLoss, self).init()
self.gamma = gamma
self.alpha = alpha
if isinstance(alpha,(float,int,long)): self.alpha = torch.Tensor([alpha,1-alpha])
if isinstance(alpha,list): self.alpha = torch.Tensor(alpha)
self.size_average = size_average
def forward(self, input, target):
if input.dim()>2:
input = input.view(input.size(0),input.size(1),-1) # N,C,H,W => N,C,H*W
input = input.transpose(1,2) # N,C,H*W => N,H*W,C
input = input.contiguous().view(-1,input.size(2)) # N,H*W,C => N*H*W,C
target = target.view(-1,1)
logpt = F.log_softmax(input)
logpt = logpt.gather(1,target)
logpt = logpt.view(-1)
pt = Variable(logpt.data.exp())
if self.alpha is not None:
if self.alpha.type()!=input.data.type():
self.alpha = self.alpha.type_as(input.data)
at = self.alpha.gather(0,target.data.view(-1))
logpt = logpt * Variable(at)
loss = -1 * (1-pt)**self.gamma * logpt
if self.size_average: return loss.mean()
else: return loss.sum()