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

Code before:
        X : {ndarray, sparse matrix} of shape (n_samples, n_features)
            Training data. Will be cast to float64 if necessary.

        y : ndarray of shape (n_samples,) or (n_samples, n_targets)
            Target values. Will be cast to float64 if necessary.

        sample_weight : float or ndarray of shape (n_samples,), default=None
            Individual weights for each sample. If given a float, every sample
            will have the same weight. Note that the scale of `sample_weight`
            has an impact on the loss; i.e. multiplying all weights by `k`
            is equivalent to setting `alpha / k`.

        score_params : dict, default=None
            Parameters to be passed to the underlying scorer.

            .. versionadded:: 1.5
                See :ref:`Metadata Routing User Guide <metadata_routing>` for
                more details.

        Returns
        -------
        self : object
        """
        xp, is_array_api, device_ = get_namespace_and_device(X)
        follow_X = make_converter(X)
        y, sample_weight = follow_X(y), follow_X(sample_weight)
        if is_array_api or hasattr(getattr(X, "dtype", None), "kind"):
            original_dtype = X.dtype
        else:
            # for X that does not have a simple dtype (eg pandas dataframe) the
            # attributes will be stored in the dtype chosen by validate_data, ie
            # np.float64
            original_dtype = None
        dtype = max_precision_float_dtype(xp, device=device_)
        X, y = validate_data(
            self,
            X,
            y,
            accept_sparse=["csr", "csc", "coo"],
            dtype=dtype,
            multi_output=True,
            y_numeric=True,
        )

        # alpha_per_target cannot be used in classifier mode. All subclasses
        # of _RidgeGCV that are classifiers keep alpha_per_target at its
        # default value: False, so the condition below should never happen.
        assert not (self.is_clf and self.alpha_per_target)

        if sample_weight is not None:
            sample_weight = _check_sample_weight(sample_weight, X, dtype=X.dtype)

Review comment (suggestion):
I don't think I am a big fan of a factory function with a generic name such as `make_converter` that returns a callable for this pattern.

I think I would prefer a simple function such as:

```suggestion
        y, sample_weight = move_to_namespace_and_device(y, sample_weight, ref=X)
```




Code after:
            # by centering, the other columns are orthogonal to that one
            intercept_column = sqrt_sw[:, None]
            X = xp.concat((X, intercept_column), axis=1)
        U, singvals, _ = xp.linalg.svd(X, full_matrices=False)
        singvals_sq = singvals**2
        UT_y = U.T @ y
        return X_mean, singvals_sq, U, UT_y

    def _solve_svd_design_matrix(self, alpha, y, sqrt_sw, X_mean, singvals_sq, U, UT_y):
        """Compute dual coefficients and diagonal of G^-1.

        Used when we have an SVD decomposition of X
        (n_samples > n_features and X is dense).
        """
        xp, is_array_api = get_namespace(U)
        w = ((singvals_sq + alpha) ** -1) - (alpha**-1)
        if self.fit_intercept:
            # detect intercept column
            normalized_sw = sqrt_sw / xp.linalg.vector_norm(sqrt_sw)
            intercept_dim = int(_find_smallest_angle(normalized_sw, U))
            # cancel the regularization for the intercept
            w[intercept_dim] = -(alpha**-1)
        c = U @ self._diag_dot(w, UT_y) + (alpha**-1) * y
        G_inverse_diag = self._decomp_diag(w, U) + (alpha**-1)
        if len(y.shape) != 1:
            # handle case where y is 2-d
            G_inverse_diag = G_inverse_diag[:, None]
        return G_inverse_diag, c

    def fit(self, X, y, sample_weight=None, score_params=None):
        """Fit Ridge regression model with gcv.

        Parameters
        ----------
        X : {ndarray, sparse matrix} of shape (n_samples, n_features)
            Training data. Will be cast to float64 if necessary.

        y : ndarray of shape (n_samples,) or (n_samples, n_targets)
            Target values. Will be cast to float64 if necessary.

        sample_weight : float or ndarray of shape (n_samples,), default=None
            Individual weights for each sample. If given a float, every sample
            will have the same weight. Note that the scale of `sample_weight`
            has an impact on the loss; i.e. multiplying all weights by `k`
            is equivalent to setting `alpha / k`.

        score_params : dict, default=None
            Parameters to be passed to the underlying scorer.

            .. versionadded:: 1.5
                See :ref:`Metadata Routing User Guide <metadata_routing>` for