AttributeError: This 'LabelEncoder' has no attribute 'set_output'

### Describe the bug

I tried to call **'set_output'** from LabelEncoder object and got the AttributeError.

[The document](https://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.LabelEncoder.html) says sklearn.preprocessing.LabelEncoder has **'set_output'** method, but it was not working.

Soon I found most of other **'set_output'** available estimators inherits both of sklearn.base.OneToOneFeatureMixin and sklearn.base.TransformerMinxin

Howerver, [LabelEncoder](https://github.com/scikit-learn/scikit-learn/blob/main/sklearn/preprocessing/_label.py) only inherits the TransformerMinxin.

```python
class LabelEncoder(TransformerMixin, BaseEstimator):
```

</br>

Function **'set_output'** seems available when **'_auto_wrap_is_configured'** is True. [(utils._set_output.py)](https://github.com/scikit-learn/scikit-learn/blob/main/sklearn/utils/_set_output.py)

```python
    @available_if(_auto_wrap_is_configured)
    def set_output(self, *, transform=None):
        """Set output container.

        See :ref:`sphx_glr_auto_examples_miscellaneous_plot_set_output.py`
        for an example on how to use the API.

        Parameters
        ----------
        transform : {"default", "pandas"}, default=None
            Configure output of `transform` and `fit_transform`.

            - `"default"`: Default output format of a transformer
            - `"pandas"`: DataFrame output
            - `None`: Transform configuration is unchanged

        Returns
        -------
        self : estimator instance
            Estimator instance.
        """
        if transform is None:
            return self

        if not hasattr(self, "_sklearn_output_config"):
            self._sklearn_output_config = {}

        self._sklearn_output_config["transform"] = transform
        return self
```

</br>

Then estimator should have **'get_feature_names_out'** to make **'_auto_wrap_is_configured'** returns True. [(utils._set_output.py)](https://github.com/scikit-learn/scikit-learn/blob/main/sklearn/utils/_set_output.py)

```python
def _auto_wrap_is_configured(estimator):
    """Return True if estimator is configured for auto-wrapping the transform method.

    `_SetOutputMixin` sets `_sklearn_auto_wrap_output_keys` to `set()` if auto wrapping
    is manually disabled.
    """
    auto_wrap_output_keys = getattr(estimator, "_sklearn_auto_wrap_output_keys", set())
    return (
        hasattr(estimator, "get_feature_names_out")
        and "transform" in auto_wrap_output_keys
    )
```

</br>

 To have **'get_feature_names_out'** attr, estimator should inherit OneToOneFeatureMixin as I think. [(base.py)](https://github.com/scikit-learn/scikit-learn/blob/main/sklearn/base.py)

```python
class OneToOneFeatureMixin:
    """Provides `get_feature_names_out` for simple transformers.

    This mixin assumes there's a 1-to-1 correspondence between input features
    and output features, such as :class:`~preprocessing.StandardScaler`.
    """

    def get_feature_names_out(self, input_features=None):
        """Get output feature names for transformation.

        Parameters
        ----------
        input_features : array-like of str or None, default=None
            Input features.

            - If `input_features` is `None`, then `feature_names_in_` is
              used as feature names in. If `feature_names_in_` is not defined,
              then the following input feature names are generated:
              `["x0", "x1", ..., "x(n_features_in_ - 1)"]`.
            - If `input_features` is an array-like, then `input_features` must
              match `feature_names_in_` if `feature_names_in_` is defined.

        Returns
        -------
        feature_names_out : ndarray of str objects
            Same as input features.
        """
        check_is_fitted(self, "n_features_in_")
        return _check_feature_names_in(self, input_features)
```

</br>

I want to know that it is kind of a bug, or the document says wrong information.

### Steps/Code to Reproduce

```python
from sklearn.preprocessing import LabelEncoder

LabelEncoder().set_output()
```

### Expected Results

No error is thrown

### Actual Results

```python
--------------------------------------------------------------------------------
AttributeError                                 Traceback (most recent call last)                        
/tmp/ipykernel_16765/3091610596.py in <module>
---> 1 LabelEncoder().set_output()

~/.local/lib/python3.8/site-packages/sklearn/utils/_available_if.py in __get__(self, obj, owner)
      31        # this is to allow access to the docstrings.
      32        if not self.check(obj):
--->  33            raise attr_err
      34        out = MethodType(self.fn, obj)
      35
AttributeError: This 'LabelEncoder' has no attribute 'set_output'
```
            
             
            

### Versions

```shell
1.2.2
```

COMMENT:
I’ve looked into this, and indeed the root of the problem is how the [@available_if](https://github.com/scikit-learn/scikit-learn/blob/543092020dc1bfa42b7722c9245b53cf277fe1b4/sklearn/utils/_available_if.py#L57) decorator works, as even though it makes `LabelEncoder().set_output` raise AttributeError, `set_output` is still in `dir(LabelEncoder)`, and `LabelEncoder.set_output` does give back the `_SetOutputMixin.set_output` method. So sphinx will find it as a member of the class to be documented ([see here](https://github.com/sphinx-doc/sphinx/blob/ca043c3ccdc88ae5d30e4527382fe0c8bd5e2a88/sphinx/ext/autodoc/__init__.py#L1968)).

I see a few possible ways to remove the documentation:

- I think the best solution would be to separate [`TransformerMixin`](https://github.com/scikit-learn/scikit-learn/blob/543092020dc1bfa42b7722c9245b53cf277fe1b4/sklearn/base.py#L801) and [`_SetOutputMixin`](https://github.com/scikit-learn/scikit-learn/blob/543092020dc1bfa42b7722c9245b53cf277fe1b4/sklearn/utils/_set_output.py#L347) (and expose the latter too), so have the `set_output` method opt-in instead of opt-out, but that would be a breaking change.

- Adding `:exclude-members: set_output` to the [doc template](scikit-learn/doc/templates/base.rst) as @Remi-Gau suggested, but then it's never documented (maybe would be good as a temporary solution?).

- For classes that don’t want to implement `set_output`, we could override it by one raising NotImplementedError (and having a docstring that makes sphinx skip it, by adding `:meta private:`), although that kind of goes against the magic using the `available_if` decorator and the `auto_wrap_output_keys` param. (Other such classes are LabelBinarizer, MultiLabelBinarizer, HashingVectorizer and TfidfTransformer.)

Ways that don’t work (currently):

- In sphinx, one can connect a method to call back when autodoc is deciding wether a member should be documented or skipped [like here](https://github.com/scikit-learn/scikit-learn/blob/bde701db13cebd5d5ed0bc049fb0bc9693c6c5dc/doc/conf.py#L848), but unfortunately (as of 8.1.3), is only gets the member method and not the parent class, so it’s not really possible to distinguish the `set_output` method of a class that has it or not, because it still exists in the cases when it’s not callable, and it’s the same function object (except maybe using inspect…).

- Trying to remove the method with `delattr(LabelEncoder, "set_output")` raises AttributeError.

Are there any preferences?

Labels: Bug, Documentation, good first issue, help wanted