Make complex numbers check optional in `BaseEstimator._validate_and_set_fit_params`

### Describe the workflow you want to enable

I recently extended my library [PySR](https://github.com/MilesCranmer/PySR) to allow for complex `X` and `y` arrays. However, the function `BaseEstimator._validate_and_set_fit_params` has no way of disabling the real number assertion. The function `_ensure_no_complex_data(array)` in `utils/validation.py` cannot be disabled. Thus, the only way for me to get my library working is to monkey patch this function to skip the validation altogether.

### Describe your proposed solution

I would like there to be a parameter for `_validate_and_set_fit_params` that turns off the complex number check, just as there is also a way to turn off the 2D array check, etc.

### Describe alternatives you've considered, if relevant

_No response_

### Additional context

Here is where the call takes place in my `PySRRegressor` object: https://github.com/MilesCranmer/PySR/blob/ab9ae608a74ea35557c2011e1f1218d300f18a2e/pysr/sr.py#L1346. This object inherits `MultiOutputMixin, RegressorMixin, BaseEstimator`.

Here is an example call and the error I see:

```python
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In [9], line 1
----> 1 model.fit(X, y)

File ~/Documents/PySR/pysr/sr.py:1737, in PySRRegressor.fit(self, X, y, Xresampled, weights, variable_names)
   1733 self._setup_equation_file()
   1735 mutated_params = self._validate_and_set_init_params()
-> 1737 X, y, Xresampled, weights, variable_names = self._validate_and_set_fit_params(
   1738     X, y, Xresampled, weights, variable_names
   1739 )
   1741 if X.shape[0] > 10000 and not self.batching:
   1742     warnings.warn(
   1743         "Note: you are running with more than 10,000 datapoints. "
   1744         "You should consider turning on batching (https://astroautomata.com/PySR/options/#batching). "
   (...)
   1749         "More datapoints will lower the search speed."
   1750     )

File ~/Documents/PySR/pysr/sr.py:1346, in PySRRegressor._validate_and_set_fit_params(self, X, y, Xresampled, weights, variable_names)
   1344     weights = check_array(weights, ensure_2d=False)
   1345     check_consistent_length(weights, y)
-> 1346 X, y = self._validate_data(X=X, y=y, reset=True, multi_output=True)
   1347 self.feature_names_in_ = _check_feature_names_in(self, variable_names)
   1348 variable_names = self.feature_names_in_

File ~/venvs/main/lib/python3.10/site-packages/sklearn/base.py:596, in BaseEstimator._validate_data(self, X, y, reset, validate_separately, **check_params)
    594         y = check_array(y, input_name="y", **check_y_params)
    595     else:
--> 596         X, y = check_X_y(X, y, **check_params)
    597     out = X, y
    599 if not no_val_X and check_params.get("ensure_2d", True):

File ~/venvs/main/lib/python3.10/site-packages/sklearn/utils/validation.py:1074, in check_X_y(X, y, accept_sparse, accept_large_sparse, dtype, order, copy, force_all_finite, ensure_2d, allow_nd, multi_output, ensure_min_samples, ensure_min_features, y_numeric, estimator)
   1069         estimator_name = _check_estimator_name(estimator)
   1070     raise ValueError(
   1071         f"{estimator_name} requires y to be passed, but the target y is None"
   1072     )
-> 1074 X = check_array(
   1075     X,
   1076     accept_sparse=accept_sparse,
   1077     accept_large_sparse=accept_large_sparse,
   1078     dtype=dtype,
   1079     order=order,
   1080     copy=copy,
   1081     force_all_finite=force_all_finite,
   1082     ensure_2d=ensure_2d,
   1083     allow_nd=allow_nd,
   1084     ensure_min_samples=ensure_min_samples,
   1085     ensure_min_features=ensure_min_features,
   1086     estimator=estimator,
   1087     input_name="X",
   1088 )
   1090 y = _check_y(y, multi_output=multi_output, y_numeric=y_numeric, estimator=estimator)
   1092 check_consistent_length(X, y)

File ~/venvs/main/lib/python3.10/site-packages/sklearn/utils/validation.py:866, in check_array(array, accept_sparse, accept_large_sparse, dtype, order, copy, force_all_finite, ensure_2d, allow_nd, ensure_min_samples, ensure_min_features, estimator, input_name)
    858         raise ValueError(
    859             "Complex data not supported\n{}\n".format(array)
    860         ) from complex_warning
    862 # It is possible that the np.array(..) gave no warning. This happens
    863 # when no dtype conversion happened, for example dtype = None. The
    864 # result is that np.array(..) produces an array of complex dtype
    865 # and we need to catch and raise exception for such cases.
--> 866 _ensure_no_complex_data(array)
    868 if ensure_2d:
    869     # If input is scalar raise error
    870     if array.ndim == 0:

File ~/venvs/main/lib/python3.10/site-packages/sklearn/utils/validation.py:568, in _ensure_no_complex_data(array)
    561 def _ensure_no_complex_data(array):
    562     if (
    563         hasattr(array, "dtype")
    564         and array.dtype is not None
    565         and hasattr(array.dtype, "kind")
    566         and array.dtype.kind == "c"
    567     ):
--> 568         raise ValueError("Complex data not supported\n{}\n".format(array))

ValueError: Complex data not supported
[[-2.02335203-0.13285217j -1.14560511+0.36383775j -0.0388407 -0.56413576j
   0.22136457-0.65906156j  1.31305444+0.33418455j]
 [-0.8686053 -0.20667045j  1.44976451-0.91981686j -0.54253912-0.28040131j
   2.77618372+1.37670423j  1.24366589+1.23424509j]
 [-1.18890458-0.68708739j  1.08839574+0.3281328j  -0.39634625-0.5159068j
   0.21911703+0.87334088j  0.19518873-0.24635224j]
 ...
 [-0.5148545 +0.7814871j   1.44093924-0.65092289j  2.05879756-0.53332935j
   0.55355862+0.2447758j  -0.59905953-0.41042992j]
 [-0.2645599 +2.00658263j  0.27197639+1.48677505j  0.34973374-0.80205851j
   0.39487604-0.26306846j  0.10859811-0.41198692j]
 [ 0.08583031-0.84073204j -0.84911584-0.46094548j -0.20988759-0.66359283j
   0.0835439 -0.73089652j  1.66839496+1.26268374j]]
```

COMMENT:
This is my temporary workaround in case others have a similar issue:

https://github.com/MilesCranmer/PySR/blob/4dd9621fcc157973c97d2d85f0491d27d237c6a4/pysr/sklearn_monkeypatch.py

```python
from sklearn.utils import validation

def _ensure_no_complex_data(*args, **kwargs):
    ...

try:
    validation._ensure_no_complex_data = _ensure_no_complex_data
except AttributeError:
    ...
```

It's definitely a hack though, so it would be great if there is a built-in mechanism to avoid this check.

Labels: New Feature, Needs Decision - Include Feature