Call to estimator.score() in RANSAC even if the produced input data set is too small - fix proposed

### Describe the bug

By sampling radomly from a distribution of x,y values, the RANSAC algorithm tries to find the line which describes best most of the data (while ignoring outliers). For deciding, how well a certain line describes the data, estimator.score() is called in line 526 of _ransac.py.

    525 # score of inlier data set
--> 526 score_subset = estimator.score(
    527     X_inlier_subset,
    528     y_inlier_subset,
    529     **score_params_inlier_subset,
    530 )

However, estimator.score() is called even if the inlier data set contains only a single data point, which then triggers a warning down the road:

...\Lib\site-packages\sklearn\metrics\_regression.py:1283, in r2_score(y_true, y_pred, sample_weight, multioutput, force_finite)
   1281 if _num_samples(y_pred) < 2:
   1282     msg = "R^2 score is not well-defined with less than two samples."
-> 1283     warnings.warn(msg, UndefinedMetricWarning)
   1284     return float("nan")

From my point of view, the code should not call this function if the input data set is not valid.

Unfortunately, I cannot provide a minimum example code as due to the random sampling the warning does only rarely occur. As far as I understand, the situation occurs if in previous iterations there was already a data set with more than 1 inlier data point drawn. Otherwise, line 526 is not reached due to:

510  # less inliers -> skip current random sample
511  if n_inliers_subset < n_inliers_best:
512     self.n_skips_no_inliers_ += 1
513     continue

If propose to modify this line to:

511 if ((n_inliers_subset < n_inliers_best) or (n_inliers_subset < 2)):

At least for me, this does fix the situation that generates the warnings.


### Steps/Code to Reproduce

            # less inliers -> skip current random sample
            if n_inliers_subset < n_inliers_best: # proposed fix: if ((n_inliers_subset < n_inliers_best) or (n_inliers_subset < 2)):
                self.n_skips_no_inliers_ += 1
                continue

            # extract inlier data set
            inlier_idxs_subset = sample_idxs[inlier_mask_subset]
            X_inlier_subset = X[inlier_idxs_subset]
            y_inlier_subset = y[inlier_idxs_subset]

            # cut `fit_params` down to `inlier_idxs_subset`
            score_params_inlier_subset = _check_method_params(
                X, params=routed_params.estimator.score, indices=inlier_idxs_subset
            )

            # score of inlier data set
            score_subset = estimator.score(
                X_inlier_subset,
                y_inlier_subset,
                **score_params_inlier_subset,
            )

### Expected Results

Expected result: RANSAC algorithm should not make call to functions with invalid data that cause warnings.

### Actual Results

...\Lib\site-packages\sklearn\metrics\_regression.py:1283, in r2_score(y_true, y_pred, sample_weight, multioutput, force_finite)
   1281 if _num_samples(y_pred) < 2:
   1282     msg = "R^2 score is not well-defined with less than two samples."
-> 1283     warnings.warn(msg, UndefinedMetricWarning)
   1284     return float("nan")

### Versions

```shell
import sklearn; sklearn.show_versions()

System:
    python: 3.13.5 | packaged by Anaconda, Inc. | (main, Jun 12 2025, 16:37:03) [MSC v.1929 64 bit (AMD64)]
executable: C:\ProgramData\anaconda3\envs\E134\python.exe
   machine: Windows-11-10.0.26200-SP0

Python dependencies:
      sklearn: 1.7.2
          pip: 25.2
   setuptools: 78.1.1
        numpy: 2.3.2
        scipy: 1.16.1
       Cython: None
       pandas: 2.3.2
   matplotlib: 3.10.6
       joblib: 1.5.2
threadpoolctl: 3.6.0

Built with OpenMP: True

threadpoolctl info:
       user_api: blas
   internal_api: openblas
    num_threads: 12
         prefix: libscipy_openblas
       filepath: C:\ProgramData\anaconda3\envs\E134\Lib\site-packages\numpy.libs\libscipy_openblas64_-860d95b1c38e637ce4509f5fa24fbf2a.dll
        version: 0.3.30
threading_layer: pthreads
   architecture: SkylakeX

       user_api: blas
   internal_api: openblas
    num_threads: 12
         prefix: libscipy_openblas
       filepath: C:\ProgramData\anaconda3\envs\E134\Lib\site-packages\scipy.libs\libscipy_openblas-6b2103f2ae4d8547998b5d188e9801fb.dll
        version: 0.3.28
threading_layer: pthreads
   architecture: SkylakeX

       user_api: openmp
   internal_api: openmp
    num_threads: 12
         prefix: vcomp
       filepath: C:\ProgramData\anaconda3\envs\E134\Lib\site-packages\sklearn\.libs\vcomp140.dll
        version: None
```

COMMENT:
> Unfortunately, I cannot provide a minimum example code as due to the random sampling the warning does only rarely occur.

> As RANSAC is based on drawing random (sub-)samples from a given data set, I will need to have a look how to fix the seed for the random number generator.

You can use the `random_state` parameter to control randomness e.g. `RANSACRegressor(random_state=0)`. Hopefully you can generate some synthetic data that recreates the problem.

Still curious, what kind of data are you looking at in case you can tell publicly? Also what makes `RANSACRegressor` useful compared to more "standard" (for lack of  a better term) algorithms?

Basically as a maintainer, to me `RANSACRegressor` feels like the kind of niche algorithm that scikit-learn has but that not many people actually use. Since you seem to have a use case for it, I am quite curious to know more 😉.

Labels: Bug, Needs Reproducible Code, Needs Triage