More intuitive check on GaussianMixture initialization

### Describe the workflow you want to enable

Hey!

I am using GaussianMixture and testing different initialization methods (kmeans, random, k-means++ and random_from_data). When I ran the code using `"init_params==kmeans++"` an error was produced in `sklearn/mixture/_base.py` `_initialize_parameters`, saying that responsibilities were referenced before assignment. Of course this is because I initialized the `GaussianMixture` incorrectly and typed `"kmeans++"` instead of `"k-means++"` (without the dash).

### Describe your proposed solution

It would be great if init_params was checked upon initialization of GaussianMixture: something like "if self.init_params not in ['random', 'random_from_data', 'kmeans', 'k-means++']" would produce an error.

Alternatively (and maybe even more robust), one could add the extra else statement in _base.py _initialize_parameters to make sure the initialization technique is spelled correctly.

### Describe alternatives you've considered, if relevant

_No response_

### Additional context

_No response_

COMMENT:
> It would be great if init_params was checked upon initialization of GaussianMixture: something like "if self.init_params not in ['random', 'random_from_data', 'kmeans', 'k-means++']" would produce an error.

Hey, I tried to reproduce this on my machine and it produces the error message as expected. I used `kmeans++` as follows:
```
import numpy as np
import sklearn
from sklearn.mixture import GaussianMixture
print(sklearn.__version__)
X = np.array([[1, 2], [1, 4], [1, 0], [10, 2], [10, 4], [10, 0]])
gm1 = GaussianMixture(n_components=2, init_params="kmeans++", random_state=0).fit(X)
print(gm1.predict([[0, 0], [12, 3]]))
```

The traceback produces an `InvalidParameterError` due to the parameter validation as below:
```
1.5.dev0
Traceback (most recent call last):
  File "c:\Users\rahil\test_gaussian_mixture_params.py", line 6, in <module>
    gm1 = GaussianMixture(n_components=2, init_params="kmeans++", random_state=0).fit(X)
  File "c:\users\rahil\rahil\scikit-learn\sklearn\mixture\_base.py", line 181, in fit
    self.fit_predict(X, y)
  File "c:\users\rahil\rahil\scikit-learn\sklearn\base.py", line 1467, in wrapper
    estimator._validate_params()
  File "c:\users\rahil\rahil\scikit-learn\sklearn\base.py", line 666, in _validate_params
    validate_parameter_constraints(
  File "c:\users\rahil\rahil\scikit-learn\sklearn\utils\_param_validation.py", line 95, in validate_parameter_constraints
    raise InvalidParameterError(
sklearn.utils._param_validation.InvalidParameterError: The 'init_params' parameter of GaussianMixture must be a str among {'random_from_data', 'k-means++', 'kmeans', 'random'}. Got 'kmeans++' instead.
```

<details>
<summary>System Details</summary>

```
System:
    python: 3.9.13 | packaged by conda-forge | (main, May 27 2022, 16:51:29) [MSC v.1929 64 bit (AMD64)]
executable: C:\Users\rahil\anaconda3\envs\sklearn-env\python.exe
   machine: Windows-10-10.0.22621-SP0

Python dependencies:
      sklearn: 1.5.dev0
          pip: 22.1.2
   setuptools: 62.3.2
        numpy: 1.22.4
        scipy: 1.8.1
       Cython: 0.29.30
       pandas: 2.0.0
   matplotlib: 3.7.1
       joblib: 1.2.0
threadpoolctl: 3.1.0

Built with OpenMP: True

threadpoolctl info:
       user_api: blas
   internal_api: mkl
         prefix: libblas
       filepath: C:\Users\rahil\anaconda3\envs\sklearn-env\Library\bin\libblas.dll
        version: 2022.0-Product
threading_layer: intel
    num_threads: 4

       user_api: openmp
   internal_api: openmp
         prefix: vcomp
       filepath: C:\Users\rahil\anaconda3\envs\sklearn-env\vcomp140.dll
        version: None
    num_threads: 8
```
</details>
<hr>

<br>

> Alternatively (and maybe even more robust), one could add the extra else statement in _base.py _initialize_parameters to make sure the initialization technique is spelled correctly.

I'm not sure if this would be added as a feature or not. I think its best to wait for the maintainers' comments on this, in which case I would be happy to open a PR for this issue, if required. I made a few modifications to the `_base.py` file to ensure the string passed to `init_params` is spelled correctly. It also passes the correct string to `self.init_params` and raises a `UserWarning`, if there is a mistake in the spelling. The modifications I made are as follows:
<details>
<summary>Modifications</summary>

```
(sklearn-env) C:\Users\rahil\rahil\scikit-learn\sklearn\mixture>fc _base.py _base_modified_copy.py
Comparing files _base.py and _BASE_MODIFIED_COPY.PY
***** _base.py
        "n_init": [Interval(Integral, 1, None, closed="left")],
        "init_params": [
            StrOptions({"kmeans", "random", "random_from_data", "k-means++"})
        ],
        "random_state": ["random_state"],
***** _BASE_MODIFIED_COPY.PY
        "n_init": [Interval(Integral, 1, None, closed="left")],
        "random_state": ["random_state"],
*****

***** _base.py

        if self.init_params == "kmeans":
***** _BASE_MODIFIED_COPY.PY

        if self.init_params is None:
            warnings.warn("Using 'kmeans' as the default.", UserWarning)
            self.init_params = "kmeans"

        if self.init_params not in ["kmeans", "k-means++", "random", "random_from_data"]:
            message = f"Got '{self.init_params}'. "
            if self.init_params.startswith("k") and not self.init_params.endswith("++"):
                self.init_params = "kmeans"
                warnings.warn(message + "Initializing with 'kmeans' instead.", UserWarning)
            elif self.init_params.startswith("k") and self.init_params.endswith("++"):
                self.init_params = "k-means++"
                warnings.warn(message + "Initializing with 'k-means++' instead.", UserWarning)
            elif self.init_params.startswith("r") and not self.init_params.endswith("data"):
                self.init_params = "random"
                warnings.warn(message + "Initializing with 'random' instead.", UserWarning)
            elif self.init_params.startswith("r") and self.init_params.endswith("data"):
                self.init_params = "random_from_data"
                warnings.warn(message + "Initializing with 'random_from_data' instead.", UserWarning)
            else:
                self.init_params = "kmeans"
                warnings.warn(message + "Provided init_params do not match any known string patterns. Defaulting to 'kmeans' in
stead.", UserWarning)

        if self.init_params == "kmeans":
*****
```
</details>

After making these changes, I ran the following code:
```
import numpy as np
import sklearn
from sklearn.mixture import GaussianMixture

print(sklearn.__version__)
X = np.array([[1, 2], [1, 4], [1, 0], [10, 2], [10, 4], [10, 0]])
gm1 = GaussianMixture(n_components=2, init_params="kmeans++", random_state=0).fit(X)
gm2 = GaussianMixture(n_components=2, init_params="k-means++", random_state=0).fit(X)
gm3 = GaussianMixture(
    n_components=2, init_params="random_from_data", random_state=0
).fit(X)
gm4 = GaussianMixture(n_components=2, init_params="random data", random_state=0).fit(X)


def assert_equal(array1, array2):
    assert np.array_equal(array1, array2)


try:
    assert_equal(gm1.means_, gm2.means_)
    assert_equal(gm1.predict([[0, 0], [12, 3]]), gm2.predict([[0, 0], [12, 3]]))
    assert_equal(gm3.means_, gm4.means_)
    assert_equal(gm3.predict([[0, 0], [12, 3]]), gm4.predict([[0, 0], [12, 3]]))
    print("Arrays are equal")
except AssertionError:
    print("Arrays are not equal")
```

As expected it raises the required warning and uses the correct string for `init_params`. The output is as follows:
```
1.5.dev0
c:\users\rahil\rahil\scikit-learn\sklearn\mixture\_base.py:120: UserWarning: Got 'kmeans++'. Initializing with 'k-means++' instead.
  warnings.warn(message + "Initializing with 'k-means++' instead.", UserWarning)
c:\users\rahil\rahil\scikit-learn\sklearn\mixture\_base.py:126: UserWarning: Got 'random data'. Initializing with 'random_from_data' instead.
  warnings.warn(message + "Initializing with 'random_from_data' instead.", UserWarning)
Arrays are equal
```

PS: I do realize that all code comes at a maintenance cost and it might not be feasible to implement in some cases. A much simpler solution would be to pass the correct string to `init_params` directly. In this case, the above solution might serve as a simple workaround on the local setup.

Labels: New Feature