{"record":{"id":"16cdfb4df31c7074","repo":"TheAlgorithms/Python","slug":"y-true-must-be-one-hot-encoded","errorCode":null,"errorMessage":"y_true must be one-hot encoded.","messagePattern":"y_true must be one-hot encoded\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"machine_learning/loss_functions.py","lineNumber":142,"sourceCode":"    ValueError: y_true must be one-hot encoded.\n    >>> true_labels = np.array([[1, 0, 1], [1, 0, 0]])\n    >>> pred_probs = np.array([[0.9, 0.1, 0.0], [0.2, 0.7, 0.1]])\n    >>> categorical_cross_entropy(true_labels, pred_probs)\n    Traceback (most recent call last):\n        ...\n    ValueError: y_true must be one-hot encoded.\n    >>> true_labels = np.array([[1, 0, 0], [0, 1, 0]])\n    >>> pred_probs = np.array([[0.9, 0.1, 0.1], [0.2, 0.7, 0.1]])\n    >>> categorical_cross_entropy(true_labels, pred_probs)\n    Traceback (most recent call last):\n        ...\n    ValueError: Predicted probabilities must sum to approximately 1.\n    \"\"\"\n    if y_true.shape != y_pred.shape:\n        raise ValueError(\"Input arrays must have the same shape.\")\n\n    if np.any((y_true != 0) & (y_true != 1)) or np.any(y_true.sum(axis=1) != 1):\n        raise ValueError(\"y_true must be one-hot encoded.\")\n\n    if not np.all(np.isclose(np.sum(y_pred, axis=1), 1, rtol=epsilon, atol=epsilon)):\n        raise ValueError(\"Predicted probabilities must sum to approximately 1.\")\n\n    y_pred = np.clip(y_pred, epsilon, 1)  # Clip predictions to avoid log(0)\n    return -np.sum(y_true * np.log(y_pred))\n\n\ndef categorical_focal_cross_entropy(\n    y_true: np.ndarray,\n    y_pred: np.ndarray,\n    alpha: np.ndarray = None,\n    gamma: float = 2.0,\n    epsilon: float = 1e-15,\n) -> float:\n    \"\"\"\n    Calculate the mean categorical focal cross-entropy (CFCE) loss between true\n    labels and predicted probabilities for multi-class classification.","sourceCodeStart":124,"sourceCodeEnd":160,"githubUrl":"https://github.com/TheAlgorithms/Python/blob/f5988cc09713315817df6a7e327e258013a94440/machine_learning/loss_functions.py#L124-L160","documentation":"Raised by categorical_cross_entropy when y_true contains values other than 0/1 or any row does not sum to exactly 1 — i.e. it is not one-hot encoded. The loss -sum(y_true * log(y_pred)) only equals cross-entropy when y_true selects exactly one class per row, so soft or integer labels are rejected.","triggerScenarios":"Passing raw integer class labels like np.array([[0], [2]]) or [[0, 1, 2], ...]), or soft label distributions whose rows do not sum to 1 (e.g. [0.5, 0.6]).","commonSituations":"Forgetting the one-hot step after label encoding, using softmax outputs as 'labels', or duplicated 1s in a row from a buggy encoder.","solutions":["One-hot encode labels: y_true = np.eye(n_classes)[class_indices].","If rows should already be one-hot, find and fix the bad rows: bad = np.where(y_true.sum(axis=1) != 1).","If you need soft-label support, use a different loss implementation; this one requires strict one-hot."],"exampleFix":"# before\nlabels = np.array([0, 2, 1])\ncategorical_cross_entropy(labels.reshape(-1, 1), y_pred)\n\n# after\nlabels = np.array([0, 2, 1])\ny_true = np.eye(y_pred.shape[1])[labels]\ncategorical_cross_entropy(y_true, y_pred)","handlingStrategy":"validation","validationCode":"y_true = np.asarray(y_true)\nassert set(np.unique(y_true)) <= {0, 1} and (y_true.sum(axis=1) == 1).all(), \"y_true not one-hot\"\nloss = categorical_cross_entropy(y_true, y_pred)","typeGuard":"def is_one_hot(y_true: np.ndarray) -> bool:\n    return (\n        y_true.ndim == 2\n        and np.isin(y_true, [0, 1]).all()\n        and np.all(y_true.sum(axis=1) == 1)\n    )","tryCatchPattern":"try:\n    categorical_cross_entropy(y_true, y_pred)\nexcept ValueError as e:\n    if \"one-hot\" in str(e):\n        y_true = np.eye(y_pred.shape[1])[y_true.argmax(axis=1)] if y_true.ndim == 2 else np.eye(y_pred.shape[1])[y_true.ravel()]\n        return categorical_cross_entropy(y_true, y_pred)\n    raise","preventionTips":["Always run np.eye(k)[labels] before calling categorical losses.","Validate one-hotness in unit tests for your data pipeline.","Do not reuse softmax outputs as labels."],"tags":["machine-learning","loss-function","one-hot","label-encoding"],"backgroundTag":null,"analyzedSha":"f5988cc09713315817df6a7e327e258013a94440","analyzedAt":"2026-08-14T17:30:07.041Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}