【问题标题】:DBSCAN eps and min_samplesDBSCAN eps 和 min_samples
【发布时间】:2020-03-03 02:44:28
【问题描述】:

我一直在尝试使用 DBSCAN 来检测异常值,据我了解,DBSCAN 输出 -1 作为异常值,1 作为内联值,但是在我运行代码之后,我得到的数字不是 -1 或 1,有人可以解释为什么吗?通过反复试验找到最佳 eps 值也是正常的,因为我无法找到找到最佳 eps 值的方法。

import numpy as np

import pandas as pd

import matplotlib.pyplot as plt

%matplotlib inline

from sklearn.cluster import DBSCAN



df = pd.read_csv('Final After Simple Filtering.csv',index_col=None,low_memory=True)


# Dropping columns with low feature importance
del df['AmbTemp_DegC']
del df['NacelleOrientation_Deg']
del df['MeasuredYawError']



#applying DBSCAN


DBSCAN = DBSCAN(eps = 1.8, min_samples =10,n_jobs=-1)

df['anomaly'] = DBSCAN.fit_predict(df)


np.unique(df['anomaly'],return_counts=True)

(array([  -1,    0,    1, ..., 8462, 8463, 8464]),
array([1737565, 3539278, 4455734, ...,      13,       8,       8]))

谢谢。

【问题讨论】:

    标签: python machine-learning cluster-analysis


    【解决方案1】:

    好吧,您实际上并没有真正了解 DBSCAN。

    这是来自维基百科的副本:

    如果至少 minPts 个点在其中,则点 p 是核心点 它的距离ε(包括p)。

    如果点 q 在距离 ε 内,则点 q 可以从 p 直接到达 从核心点 p。点只能直接从 核心点。

    如果存在路径 p1, ..., pn 且 p1 = ,则点 q 可以从 p 到达 p 和 pn = q,其中每个 pi+1 都可以从 pi 直接到达。注意 这意味着路径上的所有点都必须是核心点,其中 q 的可能例外。

    从任何其他点无法到达的所有点都是异常值或噪声 点。

    所以用更简单的话来说,这个想法是:

    • 任何在 epsilon 距离上有 min_samples 个邻居的样本都是核心样本。

    • 任何不是核心但至少有一个核心邻居(距离小于 eps)的数据样本都是可直接到达的样本,可以添加到集群中。

    • 任何不是直接可达也不是核心,但至少有一个直接可达邻居(距离小于 eps)的数据样本是可达样本,将被添加到集群中。

    • 任何其他示例都被认为是噪声、异常值或任何您想要命名的示例。(这些示例将被标记为 -1)

    根据聚类的参数(eps 和 min_samples),您很可能拥有两个以上的聚类。您看,这就是您在聚类结果中看到 0 和 -1 以外的其他值的原因。

    回答你的第二个问题

    通过反复试验找到最佳 eps 值也是正常的,

    如果你的意思是做交叉验证(在你知道集群标签的集合上,或者你可以近似正确的集群),是的,我认为这是做它的正常方法

    PS:paper 很好很全面。我强烈建议你看看。祝你好运。

    【讨论】:

    • 这非常有帮助,非常感谢!关于第二个问题,我的主要目标只是去除异常值,而不是一般的聚类标签或聚类。所以我只是在尝试不同的 eps 和 min_samples 值,看看哪些是正确去除异常值的最佳值。
    • @AliYoussef 不客气。是的,你做得很好。只是一条建议,如果您可以将数据分成两部分(保持分布),一个用于火车,一个用于开发,并在火车上尝试不同的参数值并检查开发的质量。这样,你的参数调优就不会偏向于你当前拥有的数据样本,而且会是一个更通用的聚类模型。祝你好运
    【解决方案2】:

    sklearn.cluster.DBSCAN 给出-1 表示噪声,这是一个outlier,除-1 之外的所有其他值都是簇号或簇组。要查看集群总数,您可以使用命令DBSCAN.labels_

    什么是 DBScan 中使用的 eps 或 Epsilon 值?

    Epsilon 是扩展集群的局部半径。将其视为步长 - DBSCAN 永远不会比这更大,但通过执行多个步骤,DBSCAN 集群可以变得比 eps 大得多。

    如何找到最佳的 eps 值?

    使用任何超参数调整方法/包,如GridSearchCVHyperopt。您可以使用here 提到的以下任何索引。

    【讨论】:

      【解决方案3】:

      我发现这是了解 DBSCAN 工作原理的一个很好的例子。

      import numpy as np
      
      from sklearn.cluster import DBSCAN
      from sklearn import metrics
      from sklearn.datasets import make_blobs
      from sklearn.preprocessing import StandardScaler
      
      
      # #############################################################################
      # Generate sample data
      centers = [[1, 1], [-1, -1], [1, -1]]
      X, labels_true = make_blobs(n_samples=750, centers=centers, cluster_std=0.4,
                                  random_state=0)
      
      X = StandardScaler().fit_transform(X)
      
      # #############################################################################
      # Compute DBSCAN
      db = DBSCAN(eps=0.3, min_samples=10).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)
      n_noise_ = list(labels).count(-1)
      
      print('Estimated number of clusters: %d' % n_clusters_)
      print('Estimated number of noise points: %d' % n_noise_)
      print("Homogeneity: %0.3f" % metrics.homogeneity_score(labels_true, labels))
      print("Completeness: %0.3f" % metrics.completeness_score(labels_true, labels))
      print("V-measure: %0.3f" % metrics.v_measure_score(labels_true, labels))
      print("Adjusted Rand Index: %0.3f"
            % metrics.adjusted_rand_score(labels_true, labels))
      print("Adjusted Mutual Information: %0.3f"
            % metrics.adjusted_mutual_info_score(labels_true, labels))
      print("Silhouette Coefficient: %0.3f"
            % metrics.silhouette_score(X, labels))
      
      # #############################################################################
      # 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()
      

      a = np.array(labels)
      a
      

      结果:

      array([ 0,  1,  0,  2,  0,  1,  1,  2,  0,  0,  1,  1,  1,  2,  1,  0, -1,
              1,  1,  2,  2,  2,  2,  2,  1,  1,  2,  0,  0,  2,  0,  1,  1,  0,
              1,  0,  2,  0,  0,  2,  2,  1,  1,  1,  1,  1,  0,  2,  0,  1,  2,
              2,  1,  1,  2,  2,  1,  0,  2,  1,  2,  2,  2,  2,  2,  0,  2,  2,
              0,  0,  0,  2,  0,  0,  2,  1, -1,  1,  0,  2,  1,  1,  0,  0,  0,
              0,  1,  2,  1,  2,  2,  0,  1,  0,  1, -1,  1,  1,  0,  0,  2,  1,
              2,  0,  2,  2,  2,  2, -1,  0, -1,  1,  1,  1,  1,  0,  0,  1,  0,
              1,  2,  1,  0,  0,  1,  2,  1,  0,  0,  2,  0,  2,  2,  2,  0, -1,
              2,  2,  0,  1,  0,  2,  0,  0,  2,  2, -1,  2,  1, -1,  2,  1,  1,
              2,  2,  2,  0,  1,  0,  1,  0,  1,  0,  2,  2, -1,  1,  2,  2,  1,
              0,  1,  2,  2,  2,  1,  1,  2,  2,  0,  1,  2,  0,  0,  2,  0,  0,
              1,  0,  1,  0,  1,  1,  2,  2,  0,  0,  1,  1,  2,  1,  2,  2,  2,
              2,  0,  2,  0,  2,  2,  0,  2,  2,  2,  0,  0,  1,  1,  1,  2,  2,
              2,  2,  1,  2,  2,  0,  0,  2,  0,  0,  0,  1,  0,  1,  1,  1,  2,
              1,  1,  0,  1,  2,  2,  1,  2,  2,  1,  0,  0,  1,  1,  1,  0,  1,
              0,  2,  0,  2,  2,  2,  2,  2,  1,  1,  0,  0,  1,  1,  0,  0,  2,
              1, -1,  2,  1,  1,  2,  1,  2,  0,  2,  2,  0,  1,  2,  2,  0,  2,
              2,  0,  0,  2,  0,  2,  0,  2,  1,  0,  0,  0,  1,  2,  1,  2,  2,
              0,  2,  2,  0,  0,  2,  1,  1,  1,  1,  1,  0,  1,  1,  1,  1,  0,
              0,  1,  1,  1,  0,  2,  0,  1,  2,  2,  0,  0,  2,  0,  2,  1,  0,
              2,  0,  2,  0,  2,  2,  0,  1,  0,  1,  0,  2,  2,  1,  1,  1,  2,
              0,  2,  0,  2,  1,  2,  2,  0,  1,  0,  1,  0,  0,  0,  0,  2,  0,
              2,  0,  1,  0,  1,  2,  1,  1,  1,  0,  1,  1,  0,  2,  1,  0,  2,
              2,  1,  1,  2,  2,  2,  1,  2,  1,  2,  0,  2,  1,  2,  1,  0,  1,
              0,  1,  1,  0,  1,  2, -1,  1,  0,  0,  2,  1,  2,  2,  2,  2,  1,
              0,  0,  0,  0,  1,  0,  2,  1,  0,  1,  2,  0,  0,  1,  0,  1,  1,
              0, -1,  0,  2,  2,  2,  1,  1,  2,  0,  1,  0,  0,  1,  0,  1,  1,
              2,  2, -1,  0,  1,  2,  2,  1,  1,  1,  1,  0,  0,  0,  2,  2,  1,
              2,  1,  0,  0,  1,  2,  1,  0,  0,  2,  0,  1,  0,  2,  1,  0,  2,
              2,  1,  0,  0,  0,  2,  1,  1,  0,  2,  0,  0,  1,  1,  1,  1,  0,
              1,  0,  1,  0,  0,  2,  0,  1,  1,  2,  1,  1,  0,  1,  0,  2,  1,
              0,  0,  1,  0,  1,  1,  2,  2,  1,  2,  2,  1,  2,  1,  1,  1,  1,
              2,  0,  0,  0,  1,  2,  2,  0,  2,  0,  2,  1,  0,  1,  1,  0,  0,
              1,  2,  1,  2,  2,  0,  2,  1,  1,  1,  2,  0,  0,  2,  0,  2,  2,
              0,  2,  0,  1,  1,  1,  1,  0,  0,  0,  2,  1,  1,  1,  1,  2,  2,
              2,  0,  2,  1,  1,  0,  0,  1,  0,  2,  1,  2,  1,  0,  2,  2,  0,
              0,  1,  0,  0,  2,  0,  0,  0,  2,  0,  2,  0,  0,  1,  1,  0,  0,
              1,  2,  2,  0,  0,  0,  0,  2, -1,  1,  1,  2,  1,  0,  0,  2,  2,
              0,  1,  2,  0,  1,  2,  2,  1,  0,  0, -1, -1,  2,  0,  0,  0,  2,
             -1,  2,  0,  1,  1,  1,  1,  1,  0,  0,  2,  1,  2,  0,  1,  1,  1,
              0,  2,  1,  1, -1,  2,  1,  2,  0,  2,  2,  1,  0,  0,  0,  1,  1,
              2,  0,  0,  2,  2,  1,  2,  2,  2,  0,  2,  1,  2,  1,  1,  1,  2,
              0,  2,  0,  2,  2,  0,  0,  2,  1,  2,  0,  2,  0,  0,  0,  1,  0,
              2,  1,  2,  0,  1,  0,  0,  2,  0,  2,  1,  1,  2,  1,  0,  1,  2,
              1,  2], dtype=int64)
      

      那些 -1 数据点是异常值。让我们计算异常值的数量,看看它是否与我们在上图中看到的相符。

      list(a)
      b = a.tolist()
      count = b.count(-1)
      count
      

      结果:

      18
      

      我们有 18 个!完美的!!

      相关链接:

      https://scikit-learn.org/stable/auto_examples/cluster/plot_dbscan.html#sphx-glr-auto-examples-cluster-plot-dbscan-py

      【讨论】:

        猜你喜欢
        • 2014-12-27
        • 2012-10-05
        • 2023-03-15
        • 1970-01-01
        • 2020-09-10
        • 2018-01-08
        • 2020-12-08
        • 2014-06-29
        • 2021-08-18
        相关资源
        最近更新 更多