https://pytorch.org/docs/stable/generated/torch.nn.CrossEntropyLoss.html#torch.nn.CrossEntropyLoss
기본적으로 nllloss + log_softmax
예를들어
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으로 들어가줘야 한다.