Repository: scikit-learn/scikit-learn
File: sklearn/calibration.py (Python)

Code before:
            logits of the form (-x, x). For shapes of the form (n_samples, 1), the
            same process applies.

        y : array-like of shape (n_samples,)
            Training target.

        sample_weight : array-like of shape (n_samples,), default=None
            Sample weights. If None, then samples are equally weighted.

        Returns
        -------
        self : object
            Returns an instance of self.
        """
        xp, _, xp_device = get_namespace_and_device(X, y)
        X, y = indexable(X, y)
        check_consistent_length(X, y)
        logits = _convert_to_logits(X)  # guarantees xp.float64 or xp.float32

        dtype_ = logits.dtype
        labels = column_or_1d(y, dtype=dtype_)

        if sample_weight is not None:
            sample_weight = _check_sample_weight(sample_weight, labels, dtype=dtype_)

        halfmulti_loss = HalfMultinomialLoss(n_classes=logits.shape[1])

        def log_loss(log_beta=0.0):
            """Compute the log loss as a parameter of the inverse temperature
            (beta).

            Parameters
            ----------
            log_beta : float
                The current logarithm of the inverse temperature value during
                optimisation.

            Returns
            -------
            negative_log_likelihood_loss : float
                The negative log likelihood loss.

            """
            # TODO: numpy 2.0
            # Ensure raw_prediction has the same dtype as labels using .astype().
            # Without this, dtype promotion rules differ across NumPy versions:
            #
            #   beta = np.float64(0)
            #   logits = np.array([1, 2], dtype=np.float32)
            #
            #   result = beta * logits

Review comment (suggestion):
This change is present because `sample_weight` gets ignored in the initialization part of the `HalfMultinomialLoss` class. We need to pass it when calling the loss.

Code after:
        Parameters
        ----------
        X : ndarray of shape (n_samples,) or (n_samples, n_classes)
            Training data.

            This should be the output of `decision_function` or `predict_proba`.
            If the input appears to be probabilities (i.e., values between 0 and 1
            that sum to 1 across classes), it will be converted to logits using
            `np.log(p + eps)`.

            Binary decision function outputs (1D) will be converted to two-class
            logits of the form (-x, x). For shapes of the form (n_samples, 1), the
            same process applies.

        y : array-like of shape (n_samples,)
            Training target.

        sample_weight : array-like of shape (n_samples,), default=None
            Sample weights. If None, then samples are equally weighted.

        Returns
        -------
        self : object
            Returns an instance of self.
        """
        xp, _, xp_device = get_namespace_and_device(X, y)
        X, y = indexable(X, y)
        check_consistent_length(X, y)
        logits = _convert_to_logits(X)  # guarantees xp.float64 or xp.float32

        dtype_ = logits.dtype
        labels = column_or_1d(y, dtype=dtype_)

        if sample_weight is not None:
            sample_weight = _check_sample_weight(sample_weight, labels, dtype=dtype_)

        if _is_numpy_namespace(xp):
            multinomial_loss = HalfMultinomialLoss(n_classes=logits.shape[1])
        else:
            multinomial_loss = partial(_half_multinomial_loss, xp=xp)

        def log_loss(log_beta=0.0):
            """Compute the log loss as a parameter of the inverse temperature
            (beta).

            Parameters
            ----------
            log_beta : float
                The current logarithm of the inverse temperature value during
                optimisation.