Failure to insert instantiated class of estimator in Pipeline produces an unclear error message

### Describe the bug

While building a pipeline I forgot the parenthesis during a step creation in the pipeline. I'm really not proud to admit that it took me a while to realize the mistake that I've made. I thought that maybe the error message in this instance could be improved if you guys agree. 

I feel like it's a pretty easy non-breaking fix this one.

Cheers!

### Steps/Code to Reproduce

```python
# Made a silly error while building a pipeline and
# thought that the error message could be improved.

from sklearn.decomposition import PCA
from sklearn.pipeline import Pipeline
import numpy as np

# Dummy data to showcase issue
X = np.ndarray(
    shape=(10, 5),
    buffer=np.random.rand(50),
    dtype=float,
)

pipeline = Pipeline(steps=[
    # ('step1', step1),
    # ('step2', step2),
    # ...
    ('pca', PCA), # <-- Error: PCA is not instantiated, currently it's an instance of abc.ABCMeta
])

# This will raise an error but the error message will be a bit unclear
X_transformed = pipeline.fit_transform(X) 
```

### Expected Results

I would expect an error that told me that a step was not instantiated correctly, or is of type `abc.ABCMeta`, should be instance of `sklearn.decomposition.PCA`.

### Actual Results

```
Traceback (most recent call last):
  File "test.py", line 23, in <module>
    X_trainsformed = pipeline.fit_transform(X)
  File "/opt/homebrew/Caskroom/miniconda/base/envs/dsml25/lib/python3.8/site-packages/sklearn/base.py", line 1152, in wrapper
    return fit_method(estimator, *args, **kwargs)
  File "/opt/homebrew/Caskroom/miniconda/base/envs/dsml25/lib/python3.8/site-packages/sklearn/pipeline.py", line 479, in fit_transform
    return last_step.fit_transform(Xt, y, **fit_params_last_step)
  File "/opt/homebrew/Caskroom/miniconda/base/envs/dsml25/lib/python3.8/site-packages/sklearn/utils/_set_output.py", line 157, in wrapped
    data_to_wrap = f(self, X, *args, **kwargs)
  File "/opt/homebrew/Caskroom/miniconda/base/envs/dsml25/lib/python3.8/site-packages/sklearn/base.py", line 1145, in wrapper
    estimator._validate_params()
AttributeError: 'numpy.ndarray' object has no attribute '_validate_params'
```

### Versions

```shell
System:
    python: 3.8.20 | packaged by conda-forge | (default, Sep 30 2024, 17:48:42)  [Clang 17.0.6 ]
executable: /opt/homebrew/Caskroom/miniconda/base/envs/dsml25/bin/python3
   machine: macOS-26.1-arm64-arm-64bit

Python dependencies:
      sklearn: 1.3.2
          pip: 24.3.1
   setuptools: 75.3.0
        numpy: 1.24.4
        scipy: 1.10.1
       Cython: None
       pandas: 2.0.3
   matplotlib: 3.7.3
       joblib: 1.4.2
threadpoolctl: 3.5.0

Built with OpenMP: True

threadpoolctl info:
       user_api: blas
   internal_api: openblas
    num_threads: 10
         prefix: libopenblas
       filepath: /opt/homebrew/Caskroom/miniconda/base/envs/dsml25/lib/libopenblas.0.dylib
        version: 0.3.25
threading_layer: openmp
   architecture: VORTEX

       user_api: openmp
   internal_api: openmp
    num_threads: 10
         prefix: libomp
       filepath: /opt/homebrew/Caskroom/miniconda/base/envs/dsml25/lib/libomp.dylib
        version: None
```

COMMENT:
Thank you for pointing this out @peter-avg!

This is somewhat related to #32565 (which originated from [this issue](https://github.com/scikit-learn/scikit-learn/issues/32394#issuecomment-3375647854)).
While the underlying problem is the same (user passed class instead of instance), this specific error here is not covered by the proposed fix in #32565, because different ways of checking estimators are used:
* in the proposed fix, a specific error is raised whenever `get_tags()` is called on an estimator 
* for pipelines, the components are checked on whether they implement `fit/transform/fit_transform`, so `get_tags()` is not called here.

Since the underlying problem is the same, I think it would be nice to also implement a unified solution. 
I'll look into it more closely. Any thoughts @adrinjalali?

Labels: Bug