水平密集数据点

时间:2016-09-20 21:13:31

标签: python scipy scikit-learn cluster-analysis dbscan

我有一组大约34,000个数据标签及其各自的特征(状态概率)在2D numpy数组中,可视化为散点图,看起来like this

很容易看出大多数b数据点位于底部且非常密集。我想使用聚类算法来提取底部区域。我并不努力寻求完美的结果。这只是提取大多数b点。

到目前为止,我已尝试过DBSCAN算法:

import sklearn.cluster as sklc

data1, data2 = zip(*dist_list[1])
data = np.array([data1, data2]).T

core_samples, labels_db = sklc.dbscan(
    data,  # array has to be (n_samples, n_features)
    eps=2.0,
    min_samples=5,
    metric='euclidean',
    algorithm='auto'
)
core_samples_mask = np.zeros_like(labels_db, dtype=bool)
core_samples_mask[core_samples] = True

unique_labels = set(labels_db)

n_clusters_ = len(unique_labels) - (1 if -1 in labels_db else 0)

colors = plt.cm.Spectral(np.linspace(0, 1, len(unique_labels)))
for k, col in zip(unique_labels, colors):
    if k == -1:
        # Black used for noise.
        col = 'k'

    class_member_mask = (labels_db == k)

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

    xy = data[class_member_mask & ~core_samples_mask]
    plt.plot(xy[:, 0], xy[:, 1], 'x', markerfacecolor=col, markeredgecolor='k', markersize=4)

plt.rcParams["figure.figsize"] = (15, 15)
plt.title('Estimated number of clusters: %d' % n_clusters_)
plt.show()

产生this plot

增加最小量的样本只会导致较小的垂直线被归类为噪声,而较长(和较密)的垂直线则会停留。

我还尝试使用scipy.cluster.hierarchy进行群集:

thresh = 2
clusters = hcluster.fclusterdata(data, thresh, criterion="distance")

plt.scatter(*data.T, c=clusters)
title = "t=%f, n=%d" % (thresh, len(set(clusters)))
plt.title(title)
plt.show()

导致类似的垂直分类。请查看该情节的评论。凭借我的声誉,我不允许发布超过两个链接。

现在我的问题是,我在校准算法时犯了错误吗?或者我首先选择的算法是错误的?如何提取b数据点的密集区域?

1 个答案:

答案 0 :(得分:0)

  1. 不要包含ID属性。据推测,你的“节点索引”不应该用于相似性计算吗?

  2. 属性具有不同的单位和比例时,您需要非常小心。流行的启发式算法是StandardScaler,即将每个属性标准化以具有单位方差。但是考虑到你的数据的分布(在x上统一,在y上倾斜),我认为理论很好地支持标准化的使用 - 它假设高斯分布。

  3. 这两者的结合就是你得到这个结果的原因:你的x轴完全支配着结果。它实际上比你的y轴有超过10000倍的影响你实际上只是根据节点ID ...

    进行聚类

    永远不要假设群集“只是工作”。所有这些方法都非常对预处理敏感,因此需要谨慎应用。