Talip7/scikit-learn-issues-multilabel huggingface dataset:
KNeighborsClassifier: allow p value for Minkowski calculation to be less than 1.0 (and greater than 0)

### Describe the workflow you want to enable

I would like to be able to use the KNeighborsClassifier with something like:

`neigh = KNeighborsClassifier(n_neighbors=2, p=0.1)`

The error you get is:

```
File ~/opt/anaconda3/envs/tensorflow-3/lib/python3.10/site-packages/sklearn/neighbors/_base.py:395, in NeighborsBase._check_algorithm_metric(self)
    392     effective_p = self.p
    394 if self.metric in ["wminkowski", "minkowski"] and effective_p < 1:
--> 395     raise ValueError("p must be greater or equal to one for minkowski metric")

ValueError: p must be greater or equal to one for minkowski metric
```

Change the above line to limit minkowski p value to < 0:

`if self.metric in ["wminkowski", "minkowski"] and effective_p < 0:`

There is nothing wrong with using a p value > 0 and < 1.

### Describe your proposed solution

Don't throw an exception if p is < 1.0.

Calculating Minkowski distance is most definitely valid for p > 0 and p < 1.  I.e.: 0.1, 0.2, 0.3, 0.4, etc

The only requirement is compute for each dimension raised to the p power. In this case **p and after the sum of all dimensions. Take the p-th root of the sum of dimensions:  `distance = distance_sum**p`

There are many cases where it is desirable to compute minkowski > 0 and < 1

### Describe alternatives you've considered, if relevant

Write my own kNN classifier with my own minkowski distance calculator:

```
def minkowski_distance(row1, row2, p=3):
    distance = 0.0
    for i in range(len(row1)-1):
        distance += abs(row1[i] - row2[i])**p
    return distance**(1/p)
```

### Additional context

_No response_

COMMENT:
I am fine with allowing p<1.0 it in KNNClassifier without a warning when using the bruteforce method as it's perfectly fine to compute the datapoints with the lowest pseudo-metric values.

But we should still raise an exception when using ball-tree because then the triangle inequality is required to return correct results.

The `DistanceMetric` subclasses could expose an additional attribute `true_metric` or something (with a boolean value) to make it explicit

Labels: New Feature, module:neighbors, Needs Info
KNeighborsClassifier: allow p value for Minkowski calculation to be less than 1.0 (and greater than 0)

### Describe the workflow you want to enable

I would like to be able to use the KNeighborsClassifier with something like:

`neigh = KNeighborsClassifier(n_neighbors=2, p=0.1)`

The error you get is:

```
File ~/opt/anaconda3/envs/tensorflow-3/lib/python3.10/site-packages/sklearn/neighbors/_base.py:395, in NeighborsBase._check_algorithm_metric(self)
    392     effective_p = self.p
    394 if self.metric in ["wminkowski", "minkowski"] and effective_p < 1:
--> 395     raise ValueError("p must be greater or equal to one for minkowski metric")

ValueError: p must be greater or equal to one for minkowski metric
```

Change the above line to limit minkowski p value to < 0:

`if self.metric in ["wminkowski", "minkowski"] and effective_p < 0:`

There is nothing wrong with using a p value > 0 and < 1.

### Describe your proposed solution

Don't throw an exception if p is < 1.0.

Calculating Minkowski distance is most definitely valid for p > 0 and p < 1.  I.e.: 0.1, 0.2, 0.3, 0.4, etc

The only requirement is compute for each dimension raised to the p power. In this case **p and after the sum of all dimensions. Take the p-th root of the sum of dimensions:  `distance = distance_sum**p`

There are many cases where it is desirable to compute minkowski > 0 and < 1

### Describe alternatives you've considered, if relevant

Write my own kNN classifier with my own minkowski distance calculator:

```
def minkowski_distance(row1, row2, p=3):
    distance = 0.0
    for i in range(len(row1)-1):
        distance += abs(row1[i] - row2[i])**p
    return distance**(1/p)
```

### Additional context

_No response_

COMMENT:
> I am fine with allowing p<1.0 it in KNNClassifier without a warning when using the bruteforce method as it's perfectly fine to compute the datapoints with the lowest pseudo-metric values.

Actually a pseudo metric would still satisfy the triangular inequality. It's just that d(x, y) = 0 does not imply the identity x = y.

But still the `KNNClassifier` results would still be correct if the neighbors are computed with the bruteforce method. I would just document that it's not a metric for p<1.0 in the docstring.

Labels: New Feature, module:neighbors, Needs Info
KNeighborsClassifier: allow p value for Minkowski calculation to be less than 1.0 (and greater than 0)

### Describe the workflow you want to enable

I would like to be able to use the KNeighborsClassifier with something like:

`neigh = KNeighborsClassifier(n_neighbors=2, p=0.1)`

The error you get is:

```
File ~/opt/anaconda3/envs/tensorflow-3/lib/python3.10/site-packages/sklearn/neighbors/_base.py:395, in NeighborsBase._check_algorithm_metric(self)
    392     effective_p = self.p
    394 if self.metric in ["wminkowski", "minkowski"] and effective_p < 1:
--> 395     raise ValueError("p must be greater or equal to one for minkowski metric")

ValueError: p must be greater or equal to one for minkowski metric
```

Change the above line to limit minkowski p value to < 0:

`if self.metric in ["wminkowski", "minkowski"] and effective_p < 0:`

There is nothing wrong with using a p value > 0 and < 1.

### Describe your proposed solution

Don't throw an exception if p is < 1.0.

Calculating Minkowski distance is most definitely valid for p > 0 and p < 1.  I.e.: 0.1, 0.2, 0.3, 0.4, etc

The only requirement is compute for each dimension raised to the p power. In this case **p and after the sum of all dimensions. Take the p-th root of the sum of dimensions:  `distance = distance_sum**p`

There are many cases where it is desirable to compute minkowski > 0 and < 1

### Describe alternatives you've considered, if relevant

Write my own kNN classifier with my own minkowski distance calculator:

```
def minkowski_distance(row1, row2, p=3):
    distance = 0.0
    for i in range(len(row1)-1):
        distance += abs(row1[i] - row2[i])**p
    return distance**(1/p)
```

### Additional context

_No response_

COMMENT:
> Actually a pseudo metric would still satisfy the triangular inequality.

Actually minkowski with p<1 does not satisfy triangle inequality (take points (0,0), (1,1) and (0,1), example from wikipedia)

Labels: New Feature, module:neighbors, Needs Info
KNeighborsClassifier: allow p value for Minkowski calculation to be less than 1.0 (and greater than 0)

### Describe the workflow you want to enable

I would like to be able to use the KNeighborsClassifier with something like:

`neigh = KNeighborsClassifier(n_neighbors=2, p=0.1)`

The error you get is:

```
File ~/opt/anaconda3/envs/tensorflow-3/lib/python3.10/site-packages/sklearn/neighbors/_base.py:395, in NeighborsBase._check_algorithm_metric(self)
    392     effective_p = self.p
    394 if self.metric in ["wminkowski", "minkowski"] and effective_p < 1:
--> 395     raise ValueError("p must be greater or equal to one for minkowski metric")

ValueError: p must be greater or equal to one for minkowski metric
```

Change the above line to limit minkowski p value to < 0:

`if self.metric in ["wminkowski", "minkowski"] and effective_p < 0:`

There is nothing wrong with using a p value > 0 and < 1.

### Describe your proposed solution

Don't throw an exception if p is < 1.0.

Calculating Minkowski distance is most definitely valid for p > 0 and p < 1.  I.e.: 0.1, 0.2, 0.3, 0.4, etc

The only requirement is compute for each dimension raised to the p power. In this case **p and after the sum of all dimensions. Take the p-th root of the sum of dimensions:  `distance = distance_sum**p`

There are many cases where it is desirable to compute minkowski > 0 and < 1

### Describe alternatives you've considered, if relevant

Write my own kNN classifier with my own minkowski distance calculator:

```
def minkowski_distance(row1, row2, p=3):
    distance = 0.0
    for i in range(len(row1)-1):
        distance += abs(row1[i] - row2[i])**p
    return distance**(1/p)
```

### Additional context

_No response_

COMMENT:
What's our conclusion?
1. Do not allow p<1 and raise an error (current behaviour).
   Action: Improve error message and close this issue.
2. Allow it and raise a warning.
   Action: PR to allow p<1 with warnings and tests.

I'll vote for 1. as I don't have seen a convincing use case to allow it, and on top of it, it is available via passing `scipy.spatial.distance.cdist(X, Y, "minkowski", p=0.1)` to `KNeighborsClassifier`.

Labels: New Feature, module:neighbors, Needs Info
KNeighborsClassifier: allow p value for Minkowski calculation to be less than 1.0 (and greater than 0)

### Describe the workflow you want to enable

I would like to be able to use the KNeighborsClassifier with something like:

`neigh = KNeighborsClassifier(n_neighbors=2, p=0.1)`

The error you get is:

```
File ~/opt/anaconda3/envs/tensorflow-3/lib/python3.10/site-packages/sklearn/neighbors/_base.py:395, in NeighborsBase._check_algorithm_metric(self)
    392     effective_p = self.p
    394 if self.metric in ["wminkowski", "minkowski"] and effective_p < 1:
--> 395     raise ValueError("p must be greater or equal to one for minkowski metric")

ValueError: p must be greater or equal to one for minkowski metric
```

Change the above line to limit minkowski p value to < 0:

`if self.metric in ["wminkowski", "minkowski"] and effective_p < 0:`

There is nothing wrong with using a p value > 0 and < 1.

### Describe your proposed solution

Don't throw an exception if p is < 1.0.

Calculating Minkowski distance is most definitely valid for p > 0 and p < 1.  I.e.: 0.1, 0.2, 0.3, 0.4, etc

The only requirement is compute for each dimension raised to the p power. In this case **p and after the sum of all dimensions. Take the p-th root of the sum of dimensions:  `distance = distance_sum**p`

There are many cases where it is desirable to compute minkowski > 0 and < 1

### Describe alternatives you've considered, if relevant

Write my own kNN classifier with my own minkowski distance calculator:

```
def minkowski_distance(row1, row2, p=3):
    distance = 0.0
    for i in range(len(row1)-1):
        distance += abs(row1[i] - row2[i])**p
    return distance**(1/p)
```

### Additional context

_No response_

COMMENT:
> Actually minkowski with p<1 does not satisfy triangle inequality (take points (0,0), (1,1) and (0,1), example from wikipedia)

Yes I agree, I was correcting my previous comment where I made a bad use of the word "pseudometric".

Still, bruteforce knn is well defined for p<1, so I don't see why we should block it. But I agree that we should prevent running the ball-tree (and even more the kd-tree) algorithms that relies on the `metric`/`metric_kwargs` parameters to specify a true metric in order to return correct results.

Labels: New Feature, module:neighbors, Needs Info
KNeighborsClassifier: allow p value for Minkowski calculation to be less than 1.0 (and greater than 0)

### Describe the workflow you want to enable

I would like to be able to use the KNeighborsClassifier with something like:

`neigh = KNeighborsClassifier(n_neighbors=2, p=0.1)`

The error you get is:

```
File ~/opt/anaconda3/envs/tensorflow-3/lib/python3.10/site-packages/sklearn/neighbors/_base.py:395, in NeighborsBase._check_algorithm_metric(self)
    392     effective_p = self.p
    394 if self.metric in ["wminkowski", "minkowski"] and effective_p < 1:
--> 395     raise ValueError("p must be greater or equal to one for minkowski metric")

ValueError: p must be greater or equal to one for minkowski metric
```

Change the above line to limit minkowski p value to < 0:

`if self.metric in ["wminkowski", "minkowski"] and effective_p < 0:`

There is nothing wrong with using a p value > 0 and < 1.

### Describe your proposed solution

Don't throw an exception if p is < 1.0.

Calculating Minkowski distance is most definitely valid for p > 0 and p < 1.  I.e.: 0.1, 0.2, 0.3, 0.4, etc

The only requirement is compute for each dimension raised to the p power. In this case **p and after the sum of all dimensions. Take the p-th root of the sum of dimensions:  `distance = distance_sum**p`

There are many cases where it is desirable to compute minkowski > 0 and < 1

### Describe alternatives you've considered, if relevant

Write my own kNN classifier with my own minkowski distance calculator:

```
def minkowski_distance(row1, row2, p=3):
    distance = 0.0
    for i in range(len(row1)-1):
        distance += abs(row1[i] - row2[i])**p
    return distance**(1/p)
```

### Additional context

_No response_

COMMENT:
> I'll vote for 1. as I don't have seen a convincing use case to allow it, and on top of it, it is available via passing scipy.spatial.distance.cdist(X, Y, "minkowski", p=0.1) to KNeighborsClassifier.

1. is definitely simpler to implement and maintain but is somewhat artificially limiting the potential use cases for this class.

`scipy.spatial.distance.cdist(X, Y, "minkowski", p=0.1)` is a potential workaround be would not benefit from the optimized / chunked / parallel Cython implementation of the  pairwise distance + reduction computation.

Labels: New Feature, module:neighbors, Needs Info
KNeighborsClassifier: allow p value for Minkowski calculation to be less than 1.0 (and greater than 0)

### Describe the workflow you want to enable

I would like to be able to use the KNeighborsClassifier with something like:

`neigh = KNeighborsClassifier(n_neighbors=2, p=0.1)`

The error you get is:

```
File ~/opt/anaconda3/envs/tensorflow-3/lib/python3.10/site-packages/sklearn/neighbors/_base.py:395, in NeighborsBase._check_algorithm_metric(self)
    392     effective_p = self.p
    394 if self.metric in ["wminkowski", "minkowski"] and effective_p < 1:
--> 395     raise ValueError("p must be greater or equal to one for minkowski metric")

ValueError: p must be greater or equal to one for minkowski metric
```

Change the above line to limit minkowski p value to < 0:

`if self.metric in ["wminkowski", "minkowski"] and effective_p < 0:`

There is nothing wrong with using a p value > 0 and < 1.

### Describe your proposed solution

Don't throw an exception if p is < 1.0.

Calculating Minkowski distance is most definitely valid for p > 0 and p < 1.  I.e.: 0.1, 0.2, 0.3, 0.4, etc

The only requirement is compute for each dimension raised to the p power. In this case **p and after the sum of all dimensions. Take the p-th root of the sum of dimensions:  `distance = distance_sum**p`

There are many cases where it is desirable to compute minkowski > 0 and < 1

### Describe alternatives you've considered, if relevant

Write my own kNN classifier with my own minkowski distance calculator:

```
def minkowski_distance(row1, row2, p=3):
    distance = 0.0
    for i in range(len(row1)-1):
        distance += abs(row1[i] - row2[i])**p
    return distance**(1/p)
```

### Additional context

_No response_

COMMENT:
I would allow it for brute force and raise for KD/ball-tree, but no strong opinion.

Labels: New Feature, module:neighbors, Needs Info
KNeighborsClassifier: allow p value for Minkowski calculation to be less than 1.0 (and greater than 0)

### Describe the workflow you want to enable

I would like to be able to use the KNeighborsClassifier with something like:

`neigh = KNeighborsClassifier(n_neighbors=2, p=0.1)`

The error you get is:

```
File ~/opt/anaconda3/envs/tensorflow-3/lib/python3.10/site-packages/sklearn/neighbors/_base.py:395, in NeighborsBase._check_algorithm_metric(self)
    392     effective_p = self.p
    394 if self.metric in ["wminkowski", "minkowski"] and effective_p < 1:
--> 395     raise ValueError("p must be greater or equal to one for minkowski metric")

ValueError: p must be greater or equal to one for minkowski metric
```

Change the above line to limit minkowski p value to < 0:

`if self.metric in ["wminkowski", "minkowski"] and effective_p < 0:`

There is nothing wrong with using a p value > 0 and < 1.

### Describe your proposed solution

Don't throw an exception if p is < 1.0.

Calculating Minkowski distance is most definitely valid for p > 0 and p < 1.  I.e.: 0.1, 0.2, 0.3, 0.4, etc

The only requirement is compute for each dimension raised to the p power. In this case **p and after the sum of all dimensions. Take the p-th root of the sum of dimensions:  `distance = distance_sum**p`

There are many cases where it is desirable to compute minkowski > 0 and < 1

### Describe alternatives you've considered, if relevant

Write my own kNN classifier with my own minkowski distance calculator:

```
def minkowski_distance(row1, row2, p=3):
    distance = 0.0
    for i in range(len(row1)-1):
        distance += abs(row1[i] - row2[i])**p
    return distance**(1/p)
```

### Additional context

_No response_

COMMENT:
@ogrisel What is your favorite option for which you would vote?

Labels: New Feature, module:neighbors, Needs Info
KNeighborsClassifier: allow p value for Minkowski calculation to be less than 1.0 (and greater than 0)

### Describe the workflow you want to enable

I would like to be able to use the KNeighborsClassifier with something like:

`neigh = KNeighborsClassifier(n_neighbors=2, p=0.1)`

The error you get is:

```
File ~/opt/anaconda3/envs/tensorflow-3/lib/python3.10/site-packages/sklearn/neighbors/_base.py:395, in NeighborsBase._check_algorithm_metric(self)
    392     effective_p = self.p
    394 if self.metric in ["wminkowski", "minkowski"] and effective_p < 1:
--> 395     raise ValueError("p must be greater or equal to one for minkowski metric")

ValueError: p must be greater or equal to one for minkowski metric
```

Change the above line to limit minkowski p value to < 0:

`if self.metric in ["wminkowski", "minkowski"] and effective_p < 0:`

There is nothing wrong with using a p value > 0 and < 1.

### Describe your proposed solution

Don't throw an exception if p is < 1.0.

Calculating Minkowski distance is most definitely valid for p > 0 and p < 1.  I.e.: 0.1, 0.2, 0.3, 0.4, etc

The only requirement is compute for each dimension raised to the p power. In this case **p and after the sum of all dimensions. Take the p-th root of the sum of dimensions:  `distance = distance_sum**p`

There are many cases where it is desirable to compute minkowski > 0 and < 1

### Describe alternatives you've considered, if relevant

Write my own kNN classifier with my own minkowski distance calculator:

```
def minkowski_distance(row1, row2, p=3):
    distance = 0.0
    for i in range(len(row1)-1):
        distance += abs(row1[i] - row2[i])**p
    return distance**(1/p)
```

### Additional context

_No response_

COMMENT:
> I would allow it for brute force and raise for KD/ball-tree, but no strong opinion.

+1.

Labels: New Feature, module:neighbors, Needs Info
KNeighborsClassifier: allow p value for Minkowski calculation to be less than 1.0 (and greater than 0)

### Describe the workflow you want to enable

I would like to be able to use the KNeighborsClassifier with something like:

`neigh = KNeighborsClassifier(n_neighbors=2, p=0.1)`

The error you get is:

```
File ~/opt/anaconda3/envs/tensorflow-3/lib/python3.10/site-packages/sklearn/neighbors/_base.py:395, in NeighborsBase._check_algorithm_metric(self)
    392     effective_p = self.p
    394 if self.metric in ["wminkowski", "minkowski"] and effective_p < 1:
--> 395     raise ValueError("p must be greater or equal to one for minkowski metric")

ValueError: p must be greater or equal to one for minkowski metric
```

Change the above line to limit minkowski p value to < 0:

`if self.metric in ["wminkowski", "minkowski"] and effective_p < 0:`

There is nothing wrong with using a p value > 0 and < 1.

### Describe your proposed solution

Don't throw an exception if p is < 1.0.

Calculating Minkowski distance is most definitely valid for p > 0 and p < 1.  I.e.: 0.1, 0.2, 0.3, 0.4, etc

The only requirement is compute for each dimension raised to the p power. In this case **p and after the sum of all dimensions. Take the p-th root of the sum of dimensions:  `distance = distance_sum**p`

There are many cases where it is desirable to compute minkowski > 0 and < 1

### Describe alternatives you've considered, if relevant

Write my own kNN classifier with my own minkowski distance calculator:

```
def minkowski_distance(row1, row2, p=3):
    distance = 0.0
    for i in range(len(row1)-1):
        distance += abs(row1[i] - row2[i])**p
    return distance**(1/p)
```

### Additional context

_No response_

COMMENT:
I could live with that. What do the others think? @raymondj-pace, @jjerphan, @adrinjalali @eschibli?

Labels: New Feature, module:neighbors, Needs Info
KNeighborsClassifier: allow p value for Minkowski calculation to be less than 1.0 (and greater than 0)

### Describe the workflow you want to enable

I would like to be able to use the KNeighborsClassifier with something like:

`neigh = KNeighborsClassifier(n_neighbors=2, p=0.1)`

The error you get is:

```
File ~/opt/anaconda3/envs/tensorflow-3/lib/python3.10/site-packages/sklearn/neighbors/_base.py:395, in NeighborsBase._check_algorithm_metric(self)
    392     effective_p = self.p
    394 if self.metric in ["wminkowski", "minkowski"] and effective_p < 1:
--> 395     raise ValueError("p must be greater or equal to one for minkowski metric")

ValueError: p must be greater or equal to one for minkowski metric
```

Change the above line to limit minkowski p value to < 0:

`if self.metric in ["wminkowski", "minkowski"] and effective_p < 0:`

There is nothing wrong with using a p value > 0 and < 1.

### Describe your proposed solution

Don't throw an exception if p is < 1.0.

Calculating Minkowski distance is most definitely valid for p > 0 and p < 1.  I.e.: 0.1, 0.2, 0.3, 0.4, etc

The only requirement is compute for each dimension raised to the p power. In this case **p and after the sum of all dimensions. Take the p-th root of the sum of dimensions:  `distance = distance_sum**p`

There are many cases where it is desirable to compute minkowski > 0 and < 1

### Describe alternatives you've considered, if relevant

Write my own kNN classifier with my own minkowski distance calculator:

```
def minkowski_distance(row1, row2, p=3):
    distance = 0.0
    for i in range(len(row1)-1):
        distance += abs(row1[i] - row2[i])**p
    return distance**(1/p)
```

### Additional context

_No response_

COMMENT:
Works for me. :+1:

Labels: New Feature, module:neighbors, Needs Info