Pytorch – loss function Negative log likelihood loss nn.NLLLoss

By | November 27, 2022
1,105 Views

loss function Negative log likelihood loss nn.NLLLoss – Fungsi Negatif Log-Likelihood Loss (NLL) untuk target multiclass dengan menerapkan fungsi softmax sebagai lapisan aktivasi keluaran. Softmax mengacu pada fungsi aktivasi yang menghitung fungsi eksponensial yang dinormalisasi dari setiap unit di lapisan.

Fungsi Softmax dinyatakan sebagai:

    \[ S(y_i) = \frac{exp(y_i)}{\sum_{j=1}^{n}(y_i)} \]

NLL menggunakan konotasi negatif karena probabilitas (atau kemungkinan) bervariasi antara nol dan satu, dan nilai logaritma dalam rentang ini negatif. Pada akhirnya, nilai kerugian menjadi positif.

Di NLL, meminimalkan fungsi kerugian membantu kita mendapatkan output yang lebih baik. Kemungkinan log negatif diperoleh dari perkiraan perkiraan kemungkinan maksimum (MLE). Ini berarti bahwa kita mencoba untuk memaksimalkan kemungkinan log model, dan sebagai hasilnya, meminimalkan NLL.

Dalam NLL, model akan diberikan penalti / hukuman karena membuat prediksi yang benar dengan probabilitas yang lebih kecil dan didorong untuk membuat prediksi dengan probabilitas yang lebih tinggi. NLL tidak hanya peduli tentang prediksi yang benar tetapi juga tentang model yang yakin tentang prediksi dengan skor tinggi.

Misalkan kita punyai 3 record dengan 5 ciri fitur/paramater yaitu

m = nn.LogSoftmax(dim=1)
nll_loss = nn.NLLLoss()
# size of input (N x C) is = 3 x 5
input = torch.randn(5, 4, requires_grad=True)
# every element in target should have 0 <= value < C
target = torch.tensor([0,1,2,3,3])

output = nll_loss(m(input), target)
output.backward()

print(‘input: ‘, input)
print(‘target: ‘, target)
print(‘output: ‘, output)

arti dari

  • m = nn.LogSoftmax(dim=1) artinya akan di kalkulasi berdasarkan perbaris yaitu dim=1 kalau diubah perkolom menjadi dim=0. Pytorch menganut jumlah sample sebagai baris/record dengan jumlah ciri fitur sebagai kolom. Misalkan kita mempunyai 100 record dengan 3 ciri fitur maka torch.randn(100, 3, requires_grad=True)
  • # size of input (N x C) is = 3 x 5 yaitu kita mempunyai 3 record dengan 5 fitur
  • # every element in target should have 0 <= value < C artinya kita harus mempunyai target dengan rentang tersebut

Kapan itu bisa digunakan?

Masalah klasifikasi multi-kelas, jadi misalkan ada 4 kelas kalian bisa menggunakan target nilai 0,1,2,3

Contoh kasus

Lebih jelasnya Cara menggunakan loss function Negative log likelihood loss nn.NLLLoss yaitu untuk klasifikasi multiclass seperti dataset MNIST yang terdiri dari 10 kelas sehingga target isinya [0,1,2,3,4,5,6,7,8,9].  Mengingat target berupa angka tersebut maka kalian wajib menggunakan fungsi aktifasi ReLU.  Langsung saja kita buat model arsitekturnya (sederhana saja hanya MLP bukan CNN sehingga tidak perlu ada Conv2D)

import os
import torch
from torch import nn
from torchvision.datasets import MNIST
from torch.utils.data import DataLoader
from torchvision import transforms

class MLP(nn.Module):
  '''
    Multilayer Perceptron.
  '''
  def __init__(self):
    super().__init__()
    self.layers = nn.Sequential(
      nn.Flatten(),
      nn.Linear(28 * 28 * 1, 64),
      nn.ReLU(),
      nn.Linear(64, 32),
      nn.ReLU(),
      nn.Linear(32, 10),
      nn.LogSoftmax(dim = 1)
    )


  def forward(self, x):
    '''Forward pass'''
    return self.layers(x)

Perhatikan kode  nn.Linear(32, 10)  yang mengindikasikan keluaranya terdiri dari 10 kolom, kemudian langsung di  nn.LogSoftmax(dim = 1) . Berikut kode pelatihannya

if __name__ == '__main__':
  
  # Set fixed random number seed
  torch.manual_seed(42)
  if os.path.exists('data')==False:
      os.mkdir('data')
  # Prepare MNIST dataset
  dataset = MNIST('data', download=True, transform=transforms.ToTensor())
  trainloader = torch.utils.data.DataLoader(dataset, batch_size=10, shuffle=True, num_workers=1)
  
  # Initialize the MLP
  mlp = MLP()
  
  # Define the loss function and optimizer
  loss_function = nn.NLLLoss()
  optimizer = torch.optim.Adam(mlp.parameters(), lr=1e-4)
  
  # Run the training loop
  for epoch in range(0, 5): # 5 epochs at maximum
    
    # Print epoch
    print(f'Starting epoch {epoch+1}')
    
    # Set current loss value
    current_loss = 0.0
    
    # Iterate over the DataLoader for training data
    for i, data in enumerate(trainloader, 0):
      
      # Get inputs
      inputs, targets = data
      
      # Zero the gradients
      optimizer.zero_grad()
      
      # Perform forward pass
      outputs = mlp(inputs)
      
      # Compute loss
      loss = loss_function(outputs, targets)
      
      # Perform backward pass
      loss.backward()
      
      # Perform optimization
      optimizer.step()
      
      # Print statistics
      current_loss += loss.item()
      if i % 500 == 499:
          print('Loss after mini-batch %5d: %.3f' %
                (i + 1, current_loss / 500))
          current_loss = 0.0

  # Process is complete.
  print('Training process has finished.')

Setelah selesai training sebanyak 5 epoch, kita akan uji menggunakan kode berikut, perhatikan kode  prediksi = torch.argmax(prediksi,dim=1) untuk menentukan index/lokasi value terbesar

a,b = next(iter(trainloader))
prediksi = mlp(a)
prediksi = torch.argmax(prediksi,dim=1)
print('target ',b)
print('prediksi ',prediksi)

hasilnya

print('target ',b)
target  tensor([9, 5, 5, 2, 8, 9, 9, 6, 8, 4])

print('prediksi ',prediksi)
prediksi  tensor([9, 5, 5, 8, 8, 9, 9, 6, 2, 4])
See also  Pengenalan Angka Tulisan Tangan