【问题标题】:Why DBSCAN clustering returns single cluster on Movie lens data set?为什么 DBSCAN 聚类在电影镜头数据集上返回单个聚类?
【发布时间】:2018-06-11 14:49:48
【问题描述】:

情景:

我正在对电影镜头数据集执行聚类,其中我有两种格式的数据集:

旧格式:

uid iid rat
941 1   5
941 7   4
941 15  4
941 117 5
941 124 5
941 147 4
941 181 5
941 222 2
941 257 4
941 258 4
941 273 3
941 294 4

新格式:

uid 1               2               3               4
1   5               3               4               3
2   4               3.6185548023    3.646073985     3.9238342172
3   2.8978348799    2.6692556753    2.7693015618    2.8973463681
4   4.3320762062    4.3407749532    4.3111995162    4.3411425423
940 3.7996234581    3.4979386925    3.5707888503    2
941 5               NaN             NaN             NaN
942 4.5762594612    4.2752554573    4.2522440019    4.3761477591
943 3.8252406362    5               3.3748860659    3.8487417604

我需要使用 KMeans、DBSCAN 和 HDBSCAN 执行聚类。 使用 KMeans,我可以设置和获取集群。

问题

问题只存在于 DBSCAN 和 HDBSCAN,我无法获得足够数量的集群(我知道我们无法手动设置集群)

尝试的技术:

  • IRIS data-set 试过这个,我发现 Species 不包括在内。显然,这是在 String 中,除此之外还有待预测,所有内容都只是 works fine 与该数据集(片段 1)
  • 尝试使用旧格式的电影镜头 100K dataset(带和不带 UID),因为我尝试了一个类比,即 UID == SPECIES,因此尝试不使用它。 (片段 2)
  • 尝试与 NEW FORMAT 相同(带和不带 UID)但结果以相同的样式结束。

片段 1:

print "\n\n FOR IRIS DATA-SET:"
from sklearn.datasets import load_iris

iris = load_iris()
dbscan = DBSCAN()

d = pd.DataFrame(iris.data)
dbscan.fit(d)
print "Clusters", set(dbscan.labels_)

片段 1(输出):

FOR IRIS DATA-SET:
Clusters set([0, 1, -1])
Out[30]: 
array([ 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
        0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
        0,  0,  0,  0,  0,  0,  0, -1,  0,  0,  0,  0,  0,  0,  0,  0,  1,
        1,  1,  1,  1,  1,  1, -1,  1,  1, -1,  1,  1,  1,  1,  1,  1,  1,
       -1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
        1,  1, -1,  1,  1,  1,  1,  1, -1,  1,  1,  1,  1, -1,  1,  1,  1,
        1,  1,  1, -1, -1,  1, -1, -1,  1,  1,  1,  1,  1,  1,  1, -1, -1,
        1,  1,  1, -1,  1,  1,  1,  1,  1,  1,  1,  1, -1,  1,  1, -1, -1,
        1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1])

片段 2:

import pandas as pd
from sklearn.cluster import DBSCAN

data_set = pd.DataFrame

ch = int(input("Extended Cluster Methods for:\n1. Main Matrix IBCF \n2. Main Matrix UBCF\nCh:"))
if ch is 1:
    data_set = pd.read_csv("MainMatrix_IBCF.csv")
    data_set = data_set.iloc[:, 1:]
    data_set = data_set.dropna()
elif ch is 2:
    data_set = pd.read_csv("MainMatrix_UBCF.csv")
    data_set = data_set.iloc[:, 1:]
    data_set = data_set.dropna()
else:
    print "Enter Proper choice!"

print "Starting with DBSCAN for Clustering on\n", data_set.info()

db_cluster = DBSCAN()
db_cluster.fit(data_set)
print "Clusters assigned are:", set(db_cluster.labels_)

片段 2(输出):

Extended Cluster Methods for:
1. Main Matrix IBCF 
2. Main Matrix UBCF
Ch:>? 1
Starting with DBSCAN for Clustering on
<class 'pandas.core.frame.DataFrame'>
Int64Index: 942 entries, 0 to 942
Columns: 1682 entries, 1 to 1682
dtypes: float64(1682)
memory usage: 12.1 MB
None
Clusters assigned are: set([-1])

正如所见,它只返回 1 个集群。我想听听我做错了什么。

【问题讨论】:

    标签: python pandas cluster-analysis dbscan


    【解决方案1】:

    需要选择合适的参数。如果 epsilon 太小,一切都会变成噪音。 sklearn 不应该这个参数有默认值,需要为每个数据集选择不同的值。

    您还需要对数据进行预处理。

    用没有意义的kmeans获得“集群”是微不足道的......

    不要只调用随机函数。你需要了解你在做什么,否则你只是在浪费时间。

    【讨论】:

    • 很好的建议,但我不能在这里真正提出我的实际目标和代码。只需了解我需要完成这两种聚类方法即可。如果您能指出所需的预处理和要使用的参数,那对我来说真的很有用。
    • 阅读 DBSCAN 论文。参数记录在那里。如果您使用欧几里德距离,预处理类似于使 kmeans 返回有意义结果所需的(但与 kmeans 相比,您可以使用与您的神秘目标更相关的其他距离)。
    【解决方案2】:

    首先,您需要对数据进行预处理,删除任何无用的属性,例如 id 和不完整的实例(以防您选择的距离度量无法处理)。

    很高兴了解这些算法来自两种不同的范式,即基于质心 (KMeans) 和基于密度 (DBSCAN 和 HDBSCAN*)。虽然基于质心的算法通常将簇的数量作为输入参数,但基于密度的算法需要邻居的数量 (minPts) 和邻域的半径 (eps)。

    通常在文献中将邻居数 (minPts) 设置为 4,并通过分析不同的值找到半径 (eps)。您可能会发现 HDBSCAN* 更易于使用,因为您只需要告知邻居的数量 (minPts)。

    如果在尝试了不同的配置之后,你仍然得到无用的聚类,可能你的数据根本没有聚类,KMeans 输出没有意义。

    【讨论】:

      【解决方案3】:

      正如@faraway 和@Anony-Mousse 所指出的,该解决方案在数据集上的数学性比在编程上更重要。

      终于可以找出集群了。方法如下:

      db_cluster = DBSCAN(eps=9.7, min_samples=2, algorithm='ball_tree', metric='minkowski', leaf_size=90, p=2)
      arr = db_cluster.fit_predict(data_set)
      print "Clusters assigned are:", set(db_cluster.labels_)
      
      uni, counts = np.unique(arr, return_counts=True)
      d = dict(zip(uni, counts))
      print d
      

      SO: How can I choose eps and minPts (two parameters for DBSCAN algorithm) for efficient results? 开始,Epsilon 和 Out-lier 概念变得更加明亮。

      【讨论】:

      • 使用 min_samples=2 时,您实际上并不是在进行 DBSCAN,而是在进行单链接聚类。对于真正的 DBSCAN,选择更大的最小尺寸(否则,一切都是密集的)。
      • 我尝试增加,但它返回更多异常值。有什么解决办法吗? @Erich
      • 我尝试增加,但它返回更多异常值。有什么解决办法吗? @Erich
      • 那么,有没有不将 min_samples 设置为 2 的标准?是否有任何方程可以保留 min_samples w.r.t.数据集?
      • 嗯,如前所述,使用 min_samples单链接聚类。如果你想要基于密度的聚类,你需要使用足够的样本来获得密度。为第二部分定义“保留”。
      【解决方案4】:

      您是否尝试过使用 PCA(例如)查看集群在 2D 空间中的外观。如果整个数据很密集并且实际上可能形成单个组,那么您可能会得到单个集群。

      更改其他参数,例如 min_samples=5、算法、指标。您可以从 sklearn.neighbors.VALID_METRICS 检查算法和指标的可能值。

      【讨论】:

        猜你喜欢
        • 2012-12-24
        • 2019-04-15
        • 2020-02-14
        • 2016-03-27
        • 2017-06-07
        • 2019-01-20
        • 2014-07-24
        • 2016-04-07
        • 2017-05-17
        相关资源
        最近更新 更多