Repository: sktime/sktime

Issue:
[BUG] sktime breaks with new scikit-learn 1.1.X due to private import
Someone has been importing private methods again 😠 

This time it's `sklearn` 1.1.0 with `_check_param_grid from sklearn.model_selection._search` being imported in `forecasting/model_selection/_tune`

... breaking much of `sktime`


Discussion:

Resolving patch:
diff --git a/sktime/forecasting/model_selection/_tune.py b/sktime/forecasting/model_selection/_tune.py
--- a/sktime/forecasting/model_selection/_tune.py
+++ b/sktime/forecasting/model_selection/_tune.py
@@ -6,11 +6,13 @@
 __author__ = ["mloning"]
 __all__ = ["ForecastingGridSearchCV", "ForecastingRandomizedSearchCV"]
 
+from collections.abc import Sequence
+
+import numpy as np
 import pandas as pd
 from joblib import Parallel, delayed
 from sklearn.base import clone
 from sklearn.model_selection import ParameterGrid, ParameterSampler, check_cv
-from sklearn.model_selection._search import _check_param_grid
 from sklearn.utils.metaestimators import if_delegate_has_method
 
 from sktime.exceptions import NotFittedError
@@ -483,9 +485,33 @@ def __init__(
         )
         self.param_grid = param_grid
 
+    def _check_param_grid(self, param_grid):
+        """_check_param_grid from sklearn 1.0.2, before it was removed."""
+        if hasattr(param_grid, "items"):
+            param_grid = [param_grid]
+
+        for p in param_grid:
+            for name, v in p.items():
+                if isinstance(v, np.ndarray) and v.ndim > 1:
+                    raise ValueError("Parameter array should be one-dimensional.")
+
+                if isinstance(v, str) or not isinstance(v, (np.ndarray, Sequence)):
+                    raise ValueError(
+                        "Parameter grid for parameter ({0}) needs to"
+                        " be a list or numpy array, but got ({1})."
+                        " Single values need to be wrapped in a list"
+                        " with one element.".format(name, type(v))
+                    )
+
+                if len(v) == 0:
+                    raise ValueError(
+                        "Parameter values for parameter ({0}) need "
+                        "to be a non-empty sequence.".format(name)
+                    )
+
     def _run_search(self, evaluate_candidates):
         """Search all candidates in param_grid."""
-        _check_param_grid(self.param_grid)
+        self._check_param_grid(self.param_grid)
         return evaluate_candidates(ParameterGrid(self.param_grid))
 
     @classmethod
diff --git a/sktime/transformations/panel/dictionary_based/_sfa.py b/sktime/transformations/panel/dictionary_based/_sfa.py
--- a/sktime/transformations/panel/dictionary_based/_sfa.py
+++ b/sktime/transformations/panel/dictionary_based/_sfa.py
@@ -475,7 +475,7 @@ def _igb(self, dft, y):
         breakpoints = np.zeros((self.word_length, self.alphabet_size))
         clf = DecisionTreeClassifier(
             criterion="entropy",
-            max_depth=np.log2(self.alphabet_size),
+            max_depth=int(np.floor(np.log2(self.alphabet_size))),
             max_leaf_nodes=self.alphabet_size,
             random_state=1,
         )


Test patch: