CrossEntropyLoss

TEMP·2021년 10월 12일
0

Torch_LOSS

목록 보기
4/5

torch.nn.CrossEntropyLoss(reduction='sum')

https://pytorch.org/docs/stable/generated/torch.nn.CrossEntropyLoss.html#torch.nn.CrossEntropyLoss

torch.nn.functional.cross_entropy

https://pytorch.org/docs/stable/generated/torch.nn.functional.cross_entropy.html#torch.nn.functional.cross_entropy

기본적으로 nllloss + log_softmax

  • Output shape : tensor( Batch × Class × k-dimension ) )
    일반적으로 output은 model(input)이고 따라서 score이다.
    보통 CEE전에 softmax를 거쳐야 하는데 code안에 softmax를 거치도록 포함되어 있다.
    아래 예시는 custom한 것인데 위 공식문서를 참고하여 식을 그대로 coding 한 것이다.
  • Target shape : tensor( Batch × k-dimension ) )
    label이 들어와야 한다.

예를들어

outputs = torch.rand(10, 5, requires_grad=True)
targets = torch.tensor([0,2,1,3,4,3,2,1,3,1])

같은 함수이지만 Custom 하면 다음과 같다.

import torch.nn.functional as F
    
def myCEE(outputs,targets):
    exp=torch.exp(outputs)
    A=torch.log(torch.sum(exp,dim=1))
    
    hadamard=F.one_hot(targets, num_classes=5).float()*outputs
    B=torch.sum(hadamard, dim=1)
    return torch.sum(A-B)
  • reduction으로는 'sum''mean'

추가적으로

torch.nn.functional.cross_entropy(outputs, targets,reduction='sum')

라고해도 같은 값이 나온다. 진짜 class와 function의 차이일 뿐이다.
심지어 공식문서 가서 source code보면 class안에서 foraward 함수로 funtion이 되어있는것을 볼 수 있다.



위의 예시는 mninst 같은 classification model에서 사용 하는 방법이다.

이제 Segmentation model에서 cross entropy를 사용해 보자.

기본적으로 FCN에서의 cross entropy는 pixel-wise라고 생각하면 된다.

그런데 pytorch는 왜 내장 2D가 없을까? -> 아니 있다 위에보면 된다.

해보자

아 근데 공식문서의 A-B 이 방법이 당연히 빠를텐데 4차원은 못하겠다.
그래서 느리지만 정석대로 해보자ㅠ.

class가 5개인 예시이다.

loss = nn.CrossEntropyLoss(reduction='sum')
outputs = torch.rand(2, 5, 10, 10, requires_grad=True)
targets = torch.tensor([[
                       [4,0,1,2,4,4,2,1,3,4],
                       [0,2,1,3,4,2,0,2,3,1],
                       [2,1,1,2,4,2,2,1,3,0],
                       [0,0,1,3,2,3,3,4,3,1],
                       [4,2,1,3,4,3,2,4,2,1],
                       [4,0,1,2,4,4,2,1,3,4],
                       [0,2,1,3,4,2,0,2,3,1],
                       [2,1,1,2,4,2,2,1,3,0],
                       [0,0,1,3,2,3,3,4,3,1],
                       [4,2,1,3,4,3,2,4,2,1]],
                       
                      [[4,0,1,2,4,4,2,1,3,4],
                       [0,2,1,3,4,2,0,2,3,1],
                       [2,1,1,2,4,2,2,1,3,0],
                       [0,0,1,3,2,3,3,4,3,1],
                       [4,2,1,3,4,3,2,4,2,1],
                       [4,0,1,2,4,4,2,1,3,4],
                       [0,2,1,3,4,2,0,2,3,1],
                       [2,1,1,2,4,2,2,1,3,0],
                       [0,0,1,3,2,3,3,4,3,1],
                       [4,2,1,3,4,3,2,4,2,1]]])


loss(outputs, targets)



def myloss(outputs, targets):
    onehot = torch.nn.functional.one_hot(targets).float()
    reshape = np.transpose(onehot, (0,3,1,2))
    logsoft_out = nn.LogSoftmax(dim=1)
    logsoft_out_value = logsoft_out(outputs)
    hadamrd = logsoft_out_value*reshape
    sum = torch.sum(hadamrd, dim=1)
    return -torch.sum(sum)
myloss(outputs, targets)

Clear !!!!!!!!!!

이제 드디어 segmentation 할 수 있게 되었다. !!!!!!!!!!!!!!

참고로 이 code가 nllloss와 cee를 연결이 된다는 것을 알 수 있다.

https://subinium.github.io/pytorch-Tensor-Variable/

정리해보자면 다음과 같다.

아래는 torch 공식문서의 예시이다.

loss = nn.CrossEntropyLoss()
input = torch.randn(3, 5, requires_grad=True)
target = torch.empty(3, dtype=torch.long).random_(5)
output = loss(input, target)
output.backward()

이때 target data는 torch.long type으로 들어가줘야 한다.

0개의 댓글