Repository: automl/auto-sklearn

Issue:
[Question] restriction of y_max
# Short Question Description
A clear single sentence question we can try to help with?


In the [predict](https://github.com/automl/auto-sklearn/blob/63bfbebbd288c8669d6bce7f44f8c9a3a82facd5/autosklearn/pipeline/regression.py#L108)() of Class SimpleRegressionPipeline, there are restrictions on the min/max values of y. 
```
def predict(self, X, batch_size=None):
    y = super().predict(X, batch_size=batch_size)
    y[y > (2 * self.y_max_)] = 2 * self.y_max_
    if self.y_min_ < 0:
        y[y < (2 * self.y_min_)] = 2 * self.y_min_
    elif self.y_min_ > 0:
        y[y < (0.5 * self.y_min_)] = 0.5 * self.y_min_
    return y
```

My question is should we also consider y_max < 0 like y_min?

```
def predict(self, X, batch_size=None):
    y = super().predict(X, batch_size=batch_size)
    if self.y_max > 0:
        y[y > (2 * self.y_max_)] = 2 * self.y_max_
    elif self.y_max < 0:
        y[y > (0.5 * self.y_max_)] = 0.5 * self.y_max_
    if self.y_min_ < 0:
        y[y < (2 * self.y_min_)] = 2 * self.y_min_
    elif self.y_min_ > 0:
        y[y < (0.5 * self.y_min_)] = 0.5 * self.y_min_
    return y
```

If I have missed anything, please let me know. 
Many thanks!




Discussion:
Hi,
thank you for pointing this out. It's a fair question. And I do agree with you on the fact that max should be capped in the way you suggested. However, this part of the code is very old, and I did not write it so I will rather ask before changing it. Maybe there has been a good empirical reason for this.

I'm really sceptical, though, so I will mark it as a bug until all doubts are cleared.

Will let you know once I found out.
According to the author, this is indeed a bug.

Great catch! Again, thank you very much for pointing it out.

I will quickly get onto fixing it. For now, I will just use your code snippet as it's a reasonable solution and definitely the quickest one.
Later, we will likely use something more robust, like a `TransformedTargetRegressor`, instead of manually capping like above.

Resolving patch:
diff --git a/autosklearn/pipeline/regression.py b/autosklearn/pipeline/regression.py
--- a/autosklearn/pipeline/regression.py
+++ b/autosklearn/pipeline/regression.py
@@ -106,12 +106,35 @@ def iterative_fit(self, X, y, n_iter=1, **fit_params):
         )
 
     def predict(self, X, batch_size=None):
+        """Predict the classes using the selected model.
+
+        Predicted values are capped to approximately the maximum and minimum labels
+        seen during training.
+
+        Parameters
+        ----------
+        X : array-like, shape = (n_samples, n_features)
+
+        batch_size: int or None, defaults to None
+            batch_size controls whether the pipeline will be
+            called on small chunks of the data. Useful when calling the
+            predict method on the whole array X results in a MemoryError.
+
+        Returns
+        -------
+        array, shape=(n_samples,) if n_classes == 2 else (n_samples, n_classes)
+            Returns the predicted values"""
         y = super().predict(X, batch_size=batch_size)
-        y[y > (2 * self.y_max_)] = 2 * self.y_max_
+
+        if self.y_max_ > 0:
+            y[y > (2 * self.y_max_)] = 2 * self.y_max_
+        elif self.y_max_ < 0:
+            y[y > (0.5 * self.y_max_)] = 0.5 * self.y_max_
         if self.y_min_ < 0:
             y[y < (2 * self.y_min_)] = 2 * self.y_min_
         elif self.y_min_ > 0:
             y[y < (0.5 * self.y_min_)] = 0.5 * self.y_min_
+
         return y
 
     def _get_hyperparameter_search_space(


Test patch: