MAINT Improve scikit-learn reliability by replacing `cnp.ndarray`s with typed memoryviews

### Context

Using `cnp.ndarray` is not encouragged and using [typed memoryviews](https://cython.readthedocs.io/en/latest/src/userguide/memoryviews.html#typed-memoryviews) must be preferred. More precisely [`const`-qualified memoryview](https://cython.readthedocs.io/en/latest/src/userguide/memoryviews.html#read-only-views) must be used when the buffer of the NumPy array is readonly (some Cython interfaces previously have had support for readonly data using `cnp.ndarray` as a workaround).

On a side-note, better uniform canonical support of readonly buffers has notable value: some frameworks like Ray or libraries like joblib make use of memory mapping which change the writability of buffers. Yet it might crash in some context if scikit-learn's implementations have no clear support for readonly data and this is fatal to users' workflows.

In overall, we have a poor overview for such support but we must. Efforts in this meta-issue will improve the overview for this support.

---

As an example, the following pattern:

```python
cdef cnp.ndarray[T, ndim=1, mode="c"] readonly_data 
```

must be changed to:

```python
cdef const T[::1] readonly_data
```

where `T` is a concrete type or a fused type.

See [occurences of `cnp.ndarray` in the codebase](https://github.com/search?q=repo%3Ascikit-learn%2Fscikit-learn%20cnp.ndarray&type=code).

:bulb: Do note, as mentioned by @thomasjpfan in https://github.com/scikit-learn/scikit-learn/issues/25484#issuecomment-1422970514, that not all occurences of `cnp.ndarray` must be removed.

:bulb: People interested starting working with Cython might be interested in reading [Cython Best Practices, Conventions and Knowledge section of scikit-learn documentation](https://scikit-learn.org/dev/developers/cython.html#cython).

### Proposed solution: treat one file per PR

- Only perform changes necessary change to use memoryviews
- If the file is big, you can have several PR to treat it
- Create PRs for each warning with the following title:
  ```
  MAINT Use memoryviews in `source_file.ext`
  ```
  where:
  - `source_file.ext` is the file being treated

The following command allows to see which files needs to be treated:
```
ag "cnp.ndarray" -c
```
As of b69abf51, the following files need to be treated:
 - [x] sklearn/metrics/cluster/_expected_mutual_info_fast.pyx:4
 - [x] sklearn/metrics/_dist_metrics.pyx.tp:6
 - [x] sklearn/neighbors/_quad_tree.pyx:1
 - [x] sklearn/preprocessing/_csr_polynomial_expansion.pyx:9
 - [x] sklearn/utils/_seq_dataset.pyx.tp:14
 - [x] sklearn/utils/_fast_dict.pyx:4
 - [x] sklearn/utils/_seq_dataset.pxd.tp:10
 - [x] sklearn/utils/arrayfuncs.pyx:2
 - [x] sklearn/utils/sparsefuncs_fast.pyx:50
 - [x] sklearn/linear_model/_cd_fast.pyx:15
 - [x] sklearn/tree/_tree.pxd:10
 - [x] sklearn/tree/_tree.pyx:38
 - [x] sklearn/neighbors/_binary_tree.pxi:1
 - [x] sklearn/tree/_utils.pyx:1
 - [x] sklearn/tree/_utils.pxd:1
 - [x] sklearn/tree/_criterion.pyx:3
 - [x] sklearn/utils/_random.pyx:4
 - [x] sklearn/_isotonic.pyx:6

### Miscellaneous

#24875 is also linked to this PR regarding using the newest NumPy C API.

COMMENT:
Hi @jpangas, the PR you mentioned is almost five years old (2018). It has indeed been reverted lastly [here](https://github.com/scikit-learn/scikit-learn/pull/25172/files#r1073867117) because up to recently, Cython didn't allow fusetyped memoryviews to be const-qualified. We need input memoryviews to be const-qualified so that read-only arrays won't raise an error at runtime.

Long story short, you can now safely convert those back to memoryviews 😉

Labels: Build / CI, help wanted, cython, Meta-issue