torch.nn.CrossEntropyLoss()
2024. 2. 19. 17:17ㆍPytorch
만약 이중분류를 진행중이라면 torch.nn.BECLoss()를 사용하자.
Multi-Class CrossEntropyLoss
1. input tensor에 대해서 각 row 별로 softmax() 진행(=각 class별 확률을 나타냄)
2. 각 row별로 softmax()가 진행된 값에 log를 취해줌
**1-2단계를 한번에 torch.nn.functional.log_softmax(x, dim=1) 로 구현할 수도 있다.
3. predict와 y의 element-wise product 진행.
- 이때 y는 모든 class에 대한 one-hot encoding.
- 즉, 각 row별 y class에 해당하는 probability만 남음.
- 이때 2단계 진행 시 softmax의 결과는 1 이하이기 때문에 log 변환 시 각 값은 음수를 띄게 된다.
- 정답에 가까울수록 softmax값이 크고(1에 가까움). log변환시 0에 가깝다 = loss를 의미한다.
- 음수 * one hot encoding이므로 정답과 가깝게 예측했을 수록 값이 작다.
4. torch.sum()를 통해 각 row를 1차원으로 축소
5. torch.mean()를 통해 모든 row(데이터)에 대한 loss의 평균을 구함. 이때 값이 log변환으로 인해 음수이므로 -1을 곱해준다.
import numpy as np
import torch
import torch.nn as nn
import torch.nn.functional as F
recon_mat = np.load('/content/recon_mat.npy')
mat = np.load('/content/mat.npy')
print(f'recon_mat shape: {recon_mat.shape}, mat shape: {mat.shape}')
recon_mat = torch.tensor(recon_mat[:2, :])
mat = torch.tensor(mat[:2, :])
print(f'recon_mat shape: {recon_mat.shape}, mat shape: {mat.shape}')
print()
multi_class = nn.CrossEntropyLoss()
print(f'Multi-Class Entropy: {multi_class(recon_mat, mat)}')
y_hat = torch.nn.functional.log_softmax(recon_mat, dim=1)
print(f'y hat: {y_hat}')
print(f'y: {mat}')
print(f'result: {y_hat*mat}')
print()
print(torch.sum(y_hat*mat, -1))
print(torch.mean(torch.sum(y_hat*mat, -1)))
loss = -torch.mean(torch.sum(y_hat*mat, -1))
print()
print(f'Multi-Class Entropy: {multi_class(recon_mat, mat)}')
print(f'Custom Entropy: {loss}')