Repository: ivy-llc/ivy

Issue:
softmax_with_cross_entropy



Discussion:

Resolving patch:
diff --git a/ivy/functional/frontends/paddle/nn/functional/loss.py b/ivy/functional/frontends/paddle/nn/functional/loss.py
--- a/ivy/functional/frontends/paddle/nn/functional/loss.py
+++ b/ivy/functional/frontends/paddle/nn/functional/loss.py
@@ -324,6 +324,67 @@ def smooth_l1_loss(
     return out.astype(label.dtype)
 
 
+@with_supported_dtypes(
+    {"2.5.1 and below": ("float32", "float64")},
+    "paddle",
+)
+@inputs_to_ivy_arrays
+def softmax_with_cross_entropy(
+    logits,
+    label,
+    soft_label=False,
+    ignore_index=-100,
+    numeric_stable_mode=True,
+    return_softmax=False,
+    axis=-1,
+):
+    input_dims = len(list(logits.shape))
+    if input_dims == 0:
+        raise ValueError("The dimention of input should be larger than zero!")
+    label_dims = len(list(label.shape))
+    if input_dims - 1 != label_dims and input_dims != label_dims:
+        raise ValueError(
+            "Expected nput_dims - 1 = label_dims or input_dims == label_dims           "
+            "  (got nput_dims{}, label_dims{})".format(input_dims, label_dims)
+        )
+    logits = ivy.array(logits)
+    label = ivy.array(label)
+    if input_dims - 1 == label_dims:
+        label = ivy.expand_dims(label, axis=axis)
+    if numeric_stable_mode:
+        max_logits = ivy.max(logits, axis=axis, keepdims=True)
+        log_max_sum_logits = ivy.log(
+            ivy.sum(ivy.exp(ivy.subtract(logits, max_logits)), axis=axis, keepdims=True)
+        )
+        softmax = ivy.exp(
+            ivy.subtract(ivy.subtract(logits, max_logits), log_max_sum_logits)
+        )
+    else:
+        softmax = ivy.softmax(logits, axis=axis)
+
+    if soft_label:
+        loss = -ivy.sum(
+            ivy.multiply(
+                label,
+                ivy.subtract(
+                    logits, ivy.log(ivy.sum(ivy.exp(logits), axis=axis, keepdims=True))
+                ),
+            ),
+            axis=axis,
+            keepdims=True,
+        )
+    else:
+        mask = ivy.not_equal(label.astype("float64"), float(ignore_index))
+        loss = ivy.add(
+            -ivy.take_along_axis(logits, label, axis),
+            ivy.log(ivy.sum(ivy.exp(logits), axis=axis, keepdims=True)),
+        )
+        loss = ivy.multiply(loss, mask)
+    if return_softmax:
+        return paddle.to_tensor(loss), paddle.to_tensor(softmax)
+    return paddle.to_tensor(loss)
+
+
 @with_supported_dtypes({"2.5.1 and below": ("float32",)}, "paddle")
 @to_ivy_arrays_and_back
 def square_error_cost(input, label):


Test patch:
diff --git a/ivy_tests/test_ivy/test_frontends/test_paddle/test_nn/test_functional/test_loss.py b/ivy_tests/test_ivy/test_frontends/test_paddle/test_nn/test_functional/test_loss.py
--- a/ivy_tests/test_ivy/test_frontends/test_paddle/test_nn/test_functional/test_loss.py
+++ b/ivy_tests/test_ivy/test_frontends/test_paddle/test_nn/test_functional/test_loss.py
@@ -511,6 +511,66 @@ def test_paddle_smooth_l1_loss(
     )
 
 
+@handle_frontend_test(
+    fn_tree="paddle.nn.functional.softmax_with_cross_entropy",
+    dtype_and_x_and_axis=helpers.dtype_values_axis(
+        available_dtypes=helpers.get_dtypes("float"),
+        num_arrays=2,
+        min_value=1e-04,
+        max_value=1,
+        min_num_dims=2,
+        allow_inf=False,
+        shared_dtype=True,
+        force_int_axis=True,
+        valid_axis=True,
+    ),
+    soft_label=st.booleans(),
+    numeric_stable_mode=st.booleans(),
+    return_softmax=st.booleans(),
+)
+def test_paddle_softmax_with_cross_entropy(
+    dtype_and_x_and_axis,
+    soft_label,
+    numeric_stable_mode,
+    return_softmax,
+    on_device,
+    fn_tree,
+    backend_fw,
+    frontend,
+    test_flags,
+):
+    x_dtype, x, axis = dtype_and_x_and_axis
+    logits = x[0]
+    labels = x[1]
+    label_dtype = x_dtype
+    ignore_index = 0
+    if soft_label:
+        labels = labels / ivy.sum(labels).to_native()
+    else:
+        labels = ivy.argmax(labels, axis=axis).to_native()
+        flattened_labels = labels.flatten()
+        ignore_index = ivy.randint(0, flattened_labels.size)
+        ignore_index = flattened_labels[ignore_index]
+        label_dtype = [str(labels.dtype)]
+    if on_device == "cpu" or soft_label:
+        numeric_stable_mode = True
+    helpers.test_frontend_function(
+        input_dtypes=[x_dtype[0], label_dtype[0]],
+        frontend=frontend,
+        backend_to_test=backend_fw,
+        test_flags=test_flags,
+        fn_tree=fn_tree,
+        on_device=on_device,
+        logits=logits,
+        label=labels,
+        soft_label=soft_label,
+        ignore_index=ignore_index,
+        numeric_stable_mode=numeric_stable_mode,
+        return_softmax=return_softmax,
+        axis=axis,
+    )
+
+
 @handle_frontend_test(
     fn_tree="paddle.nn.functional.loss.square_error_cost",
     dtype_and_input_and_label=helpers.dtype_and_values(