Class: GRX::Loss::CrossEntropyLoss

Inherits:
Object
  • Object
show all
Defined in:
lib/grx/loss.rb

Overview

================================================================

CrossEntropyLoss — Softmax + NLL (multi-class) L = -sum(target * log(softmax(logits))) / batch_size

Constant Summary collapse

EPS =
1e-7

Instance Method Summary collapse

Instance Method Details

#call(logits, target) ⇒ Object

Raises:



52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/grx/loss.rb', line 52

def call(logits, target)
  raise ShapeError, "Incompatible shapes: #{logits.shape} vs #{target.shape}" if logits.shape != target.shape
  probs = logits.softmax
  p_data = probs.to_a
  t_data = target.to_a
  batch_size = logits.shape[0].to_f

  loss_val = t_data.each_with_index.sum do |t, i|
    next 0.0 if t == 0.0
    p = [p_data[i], EPS].max
    -t * Math.log(p)
  end / batch_size

  out = Tensor.create([loss_val], [1], requires_grad: logits.requires_grad || target.requires_grad)
  if logits.requires_grad || target.requires_grad
    out._grafo_hijos.push(logits, target)
    out.backward_fn = ->(g) {
      scale = g.item / batch_size
      grad_logits = p_data.zip(t_data).map { |p, t| (p - t) * scale }
      logits.agregar_gradiente(Tensor.create(grad_logits, logits.shape)) if logits.requires_grad
    }
  end
  out
end