sklearn.clustering.DBSCAN的输入是否应该进行预处理?
在示例中 http://scikit-learn.org/stable/auto_examples/cluster/plot_dbscan.html#example-cluster-plot-dbscan-py 计算并归一化了输入样本 X 之间的距离:
D = distance.squareform(distance.pdist(X))
S = 1 - (D / np.max(D))
db = DBSCAN(eps=0.95, min_samples=10).fit(S)
在 v0.14 (http://jaquesgrobler.github.io/online-sklearn-build/auto_examples/cluster/plot_dbscan.html( 的另一个示例中,进行了一些缩放:
X = StandardScaler().fit_transform(X)
db = DBSCAN(eps=0.3, min_samples=10).fit(X)
我的代码基于后一个示例,并且印象是聚类分析在这种扩展中效果更好。但是,这种缩放"通过删除平均值并缩放到单位方差来标准化特征"。我尝试查找 2d 集群。如果我的集群分布在平方区域中 - 假设 100x100,我认为缩放没有问题。但是,如果分布在矩形区域中,例如 800x200,则缩放会"挤压"我的样本并在一个维度上更改它们之间的相对距离。这会恶化集群,不是吗?还是我理解了。错?我是否需要应用一些预处理,或者我可以简单地输入我的"原始"数据?
这取决于您要做什么。
如果对地理数据运行 DBSCAN,并且距离以米为单位,则可能不希望对任何内容进行规范化,但也可以以米为单位设置 epsilon 阈值。
是的,特别是不均匀的缩放确实会扭曲距离。而非失真缩放相当于仅使用不同的 epsilon 值!
请注意,在第一个示例中,显然处理的是相似性而不是距离矩阵。 S = (1 - D / np.max(D))
是一种将相似性矩阵转换为相异性矩阵的启发式方法。Epsilon 0.95实际上最多意味着"观察到的最大相异性的0.05"。应产生相同结果的替代版本是:
D = distance.squareform(distance.pdist(X))
S = np.max(D) - D
db = DBSCAN(eps=0.95 * np.max(D), min_samples=10).fit(S)
而在第二个示例中,fit(X)
实际处理原始输入数据,而不是距离矩阵。恕我直言,这是一个丑陋的黑客,以这种方式重载方法。这很方便,但有时会导致误解,甚至可能不正确的使用。
总的来说,我不会把sklearn的DBSCAN作为参考。整个 API 似乎在很大程度上是由分类驱动的,而不是由聚类驱动的。通常,您不会fit
聚类分析,而只是对监督方法执行此操作。另外,sklearn目前不使用索引进行加速,并且需要O(n^2)
内存(DBSCAN通常不会(。
一般来说,您需要确保您的距离有效。如果距离函数不起作用,则基于距离的算法不会产生所需的结果。在某些数据集上,朴素距离(如欧几里得(在首次规范化数据时效果更好。在其他数据集上,您对距离有很好的了解(例如地理数据。对此进行标准化是没有意义的,欧几里得距离也没有意义!