sklearn DBSCAN для кластеризации позиций GPS с большим эпсилоном

Я хочу использовать DBSCAN из sklearn для поиска кластеров по моим позициям GPS. Я не понимаю, почему координата [ 18.28, 57.63] (нижний правый угол на рисунке) сгруппирована вместе с другими координатами слева. Может ли быть какая-то проблема с большим эпсилоном? sklearn версия 0.19.0. Test cluster Чтобы воспроизвести это: я скопировал демонстрационный код отсюда: http://scikit-learn.org/stable/auto_examples/cluster/plot_dbscan.html, но я заменил образцы данных несколькими координатами (см. переменную X в коде ниже). Я черпал вдохновение отсюда: http://geoffboeing.com/2014/08/clustering-to-reduce-spatial-data-set-size/

import numpy as np

from sklearn.cluster import DBSCAN
from sklearn import metrics
from sklearn.datasets.samples_generator import make_blobs
from sklearn.preprocessing import StandardScaler


# #############################################################################
# Generate sample data

X = np.array([[ 11.95,  57.70],
       [ 16.28,  57.63],
       [ 16.27,  57.63],
       [ 16.28,  57.66],
       [ 11.95,  57.63],
       [ 12.95,  57.63],
       [ 18.28,  57.63],
       [ 11.97,  57.70]])

# #############################################################################
# Compute DBSCAN
kms_per_radian = 6371.0088
epsilon = 400 / kms_per_radian
db = DBSCAN(eps=epsilon, min_samples=2, algorithm='ball_tree', metric='haversine').fit(X)
core_samples_mask = np.zeros_like(db.labels_, dtype=bool)
core_samples_mask[db.core_sample_indices_] = True
labels = db.labels_

# Number of clusters in labels, ignoring noise if present.
n_clusters_ = len(set(labels)) - (1 if -1 in labels else 0)

print('Estimated number of clusters: %d' % n_clusters_)

# #############################################################################
# Plot result
import matplotlib.pyplot as plt

# Black removed and is used for noise instead.
unique_labels = set(labels)
colors = [plt.cm.Spectral(each)
          for each in np.linspace(0, 1, len(unique_labels))]
for k, col in zip(unique_labels, colors):
    if k == -1:
        # Black used for noise.
        col = [0, 0, 0, 1]

    class_member_mask = (labels == k)

    xy = X[class_member_mask & core_samples_mask]
    plt.plot(xy[:, 0], xy[:, 1], 'o', markerfacecolor=tuple(col),
             markeredgecolor='k', markersize=14)

    xy = X[class_member_mask & ~core_samples_mask]
    plt.plot(xy[:, 0], xy[:, 1], 'o', markerfacecolor=tuple(col),
             markeredgecolor='k', markersize=6)

plt.title('Estimated number of clusters: %d' % n_clusters_)
plt.show()

person Olppah    schedule 09.11.2017    source источник


Ответы (2)


Недавно я совершил ту же ошибку (используя hdbscan), и это было причиной некоторых ' странные результаты. Например, одна и та же точка иногда включалась в кластер, а иногда помечалась как точка шума. «Как такое может быть быть?», — недоумевал я. Это оказалось из-за того, что я передавал широту/долготу напрямую и не преобразовывал сначала в радианы.

Самостоятельный ответ ОП верен, но не содержит подробностей. Можно, конечно, просто умножить значения широты/долготы на /180, но — если вы уже используете numpy — самое простое решение — изменить эту строку в исходном коде:

db = DBSCAN(eps=epsilon, ... metric='haversine').fit(X)

to:

db = DBSCAN(eps=epsilon, ... metric='haversine').fit(np.radians(X))
person evadeflow    schedule 17.09.2018

Метрика гаверсинуса требует данных в радианах

person Olppah    schedule 10.11.2017