En lisant, je trouve qu'il est possible de passer une matrice de distance précalculée dans SKLearn DBSCAN . Malheureusement, je ne sais pas comment le transmettre pour le calcul.
Disons que j'ai un tableau 1D avec 100 éléments, avec juste les noms des nœuds. Ensuite, j'ai une matrice 2D, 100x100 avec la distance entre chaque élément (dans le même ordre).
Je sais que je dois l'appeler:
db = DBSCAN (eps = 2, min_samples = 5, metric = "précalculé")
Pour une distance entre les nœuds de 2 et un minimum de 5 clusters de nœuds. Utilisez également «précalculé» pour indiquer d'utiliser la matrice 2D. Mais comment transmettre les informations pour le calcul?
La même question pourrait s'appliquer si vous utilisez RAPIDS CUML DBScan a > fonction (accéléré par GPU).
3 Réponses :
from sklearn.cluster import DBSCAN clustering = DBSCAN(metric='precomputed') clustering.fit(distance_matrix)
from sklearn.cluster import DBSCAN clustering = DBSCAN() DBSCAN.fit(X)
Donc, la façon dont vous appelez cela normalement est:
[...] metricstring, or callable, default=âeuclideanâ The metric to use when calculating distance between instances in a feature array. If metric is a string or callable, it must be one of the options allowed by sklearn.metrics.pairwise_distances for its metric parameter. If metric is âprecomputedâ, X is assumed to be a distance matrix and must be square. X may be a Glossary, in which case only ânonzeroâ elements may be considered neighbors for DBSCAN. [...]
si vous avez une matrice de distance, vous faites:
class sklearn.cluster.DBSCAN(eps=0.5, *, min_samples=5, metric='euclidean', metric_params=None, algorithm='auto', leaf_size=30, p=None, n_jobs=None) [...]
Donc, X sera la matrice carrée avec les distances paires, non? Ne devrait pas être métrique = "précalculé" au lieu de métrique = 'fixe'?
pourriez-vous s'il vous plaît revoir les détails que je donne ci-dessous? Merci
D'accord, j'ai essayé votre suggestion, mais cela ne fonctionne pas. Je suis cet article:
Voici mon état actuel du code. Lors du calcul de la distance dans le cadre de l'appel DBSCAN, cela fonctionne comme un champion. En essayant la même chose avec précalculé, j'obtiens une erreur.
791 794 798 1124 1125 791 0.000000 6.091447 35.342980 42.952046 29.158508 794 6.091447 0.000000 29.394745 39.452365 23.151700 798 35.342980 29.394745 0.000000 41.346497 12.675131 1124 42.952046 39.452365 41.346497 0.000000 29.392357 1125 29.158508 23.151700 12.675131 29.392357 0.000000
Voici l'erreur que j'obtiens:
File "./DBSCAN.py", line 41, in <module> db.fit(matrix) File "/Users/jnebrera/.pyenv/versions/3.8.3/lib/python3.8/site-packages/sklearn/cluster/_dbscan.py", line 330, in fit neighbors_model = NearestNeighbors( File "/Users/jnebrera/.pyenv/versions/3.8.3/lib/python3.8/site-packages/sklearn/utils/validation.py", line 73, in inner_f return f(**kwargs) File "/Users/jnebrera/.pyenv/versions/3.8.3/lib/python3.8/site-packages/sklearn/neighbors/_unsupervised.py", line 113, in __init__ super().__init__( File "/Users/jnebrera/.pyenv/versions/3.8.3/lib/python3.8/site-packages/sklearn/neighbors/_base.py", line 305, in __init__ self._check_algorithm_metric() File "/Users/jnebrera/.pyenv/versions/3.8.3/lib/python3.8/site-packages/sklearn/neighbors/_base.py", line 332, in _check_algorithm_metric raise ValueError("Metric '%s' not valid. Use " ValueError: Metric 'precomputed' not valid. Use sorted(sklearn.neighbors.VALID_METRICS['ball_tree']) to get valid options. Metric can also be a callable function.
Ceci est la matrice de distance que j'ai:
#!/usr/bin/env python3 import pandas as pd, numpy as np from numpy import load from sklearn.neighbors import DistanceMetric from sklearn.cluster import DBSCAN from geopy.distance import great_circle from shapely.geometry import MultiPoint from numpy import save kms_per_radian = 6371.0088 #Loading GPS coordinates array cities_df = pd.read_csv('geo.csv',delimiter=';',header=0) reducida = cities_df.copy() coords = reducida.drop(columns=['ID']) #Transforming to radians cities_df['lat'] = np.radians(cities_df['lat']) cities_df['lon'] = np.radians(cities_df['lon']) #Function to compute distance. This is simulated, in reality we will use a different procedure dist = DistanceMetric.get_metric('haversine') cities_df[['lat','lon']].to_numpy() matrix = pd.DataFrame(dist.pairwise(cities_df[['lat','lon']].to_numpy())*kms_per_radian, columns=cities_df.ID.unique(), index=cities_df.ID.unique()) # Saving distance matrix to disk # save('data.npy',matrix) epsilon = 1 / kms_per_radian # Load matrix #matrix = load('data.npy') # Computing clusters with precomputed matrix, DOESN'T WORK db = DBSCAN(eps=epsilon, min_samples=1, algorithm='ball_tree', metric='precomputed') db.fit(distancias) # Instead if I use the embedded haversine function IT DOES WORK. Should have the same result # db = DBSCAN(eps=epsilon, min_samples=1, algorithm='ball_tree', metric='haversine').fit(np.radians(coords)) cluster_labels = db.labels_ num_clusters = len(set(cluster_labels)) clusters = pd.Series([coords[cluster_labels == n] for n in range(num_clusters)]) print('Number of clusters: {}'.format(num_clusters))
Ceci est juste un sous-ensemble des données, j'ai en réalité une matrice beaucoup plus grande. Les nombres sont les ID des colonnes et des lignes (peut-être que l'erreur est là)
vous ne définissez pas de distancias
dans votre code. Pouvez-vous modifier votre question / réponse s.t. il est défini? Pouvez-vous également vérifier le type (distancias)
?
De plus, quelle version de sklearn avez-vous? Essayez: import sklearn
puis sklearn .__ version__
Désolé, une erreur de copier-coller s'est produite. Il faudrait dire matrice au lieu de distances (en fait, l'erreur qu'elle produit est déjà bien copiée et dit db.fit (matrice)
La version de sklearn est la 0.23.1
Voici ce que j'obtiens en exécutant:
pip install -U scikit-learn Requirement already up-to-date: scikit-learn in /Users/jnebrera/.pyenv/versions/3.8.3/lib/python3.8/site-packages (0.23.1) Requirement already satisfied, skipping upgrade: joblib>=0.11 in /Users/jnebrera/.pyenv/versions/3.8.3/lib/python3.8/site-packages (from scikit-learn) (0.15.1) Requirement already satisfied, skipping upgrade: threadpoolctl>=2.0.0 in /Users/jnebrera/.pyenv/versions/3.8.3/lib/python3.8/site-packages (from scikit-learn) (2.1.0) Requirement already satisfied, skipping upgrade: scipy>=0.19.1 in /Users/jnebrera/.pyenv/versions/3.8.3/lib/python3.8/site-packages (from scikit-learn) (1.5.0) Requirement already satisfied, skipping upgrade: numpy>=1.13.3 in /Users/jnebrera/.pyenv/versions/3.8.3/lib/python3.8/site-packages (from scikit-learn) (1.19.0)