from sklearn.cluster import DBSCAN
import numpy as np
data = np.random.rand(500,3)
db = DBSCAN(eps=0.12, min_samples=1).fit(data)
labels = db.labels_
from collections import Counter
Counter(labels)
class DBSCAN(object):
def __init__(self, eps=0, min_points=2):
self.eps = eps
self.min_points = min_points
self.visited = []
self.noise = []
self.clusters = []
self.dp = []
def cluster(self, data_points):
self.visited = []
self.dp = data_points
c = 0
for point in data_points:
if point not in self.visited:
self.visited.append(point)
neighbours = self.region_query(point)
if len(neighbours) < self.min_points:
self.noise.append(point)
else:
c += 1
self.expand_cluster(c, neighbours)
def expand_cluster(self, cluster_number, p_neighbours):
cluster = ("Cluster: %d" % cluster_number, [])
self.clusters.append(cluster)
new_points = p_neighbours
while new_points:
new_points = self.pool(cluster, new_points)
def region_query(self, p):
result = []
for d in self.dp:
distance = (((d[0] - p[0])**2 + (d[1] - p[1])**2 + (d[2] - p[2])**2)**0.5)
if distance <= self.eps:
result.append(d)
return result
def pool(self, cluster, p_neighbours):
new_neighbours = []
for n in p_neighbours:
if n not in self.visited:
self.visited.append(n)
n_neighbours = self.region_query(n)
if len(n_neighbours) >= self.min_points:
new_neighbours = self.unexplored(p_neighbours, n_neighbours)
for c in self.clusters:
if n not in c[1] and n not in cluster[1]:
cluster[1].append(n)
return new_neighbours
@staticmethod
def unexplored(x, y):
z = []
for p in y:
if p not in x:
z.append(p)
return z
在对第一个答案中提供的代码进行了一段时间的研究之后,我得出结论,它存在重大问题: 1) 噪波点可以出现在以后的簇中。 2) 它抛出额外的簇,这些簇是先前构建的簇的子集,因为存在对已访问和未探索的点进行计数的问题,导致簇的最小值小于,并且 3) 有些点可以在两个集群中结束-它们可以从两个集群中访问,在这段代码中,它们甚至可能是其中一个集群的核心点。官方的DBSCAN算法将任何作为核心点的点放置在它是核心的一部分的集群中,但是将那些只能从第一个集群中的两个集群中访问到的点放置在发现它们可以从中访问的集群中。这使得这些点的聚类依赖于数据中点的顺序,但所有点在输出数据中只出现一次-在单个聚类中或作为噪声出现。某些应用程序将希望这些可从两个群集访问的共享点放置在两个群集中,但核心点应仅出现在一个群集中。
所以这就是我想到的。它计算两个点之间的间隔距离两次,不使用任何树,但它立即消除没有近邻的点,并创建一次核心点列表,因此在构建核心时只需要考虑这些点。它使用集合进行包含测试注意,此实现确实将共享点放在所有可从其访问的集群中
您可以使用sklearn for DBSCAN。这里有一些代码对我有用-
我得到的结果是-
因此,聚类用每个聚类中的点数来识别55个聚类,如上图所示。
所以这就是我想出来的,我知道这不是最有效的实现,但它是有效的;例如区域查询,它是算法的主要时间消耗者,它不止一次地计算两点之间的距离,而不是仅仅存储它供以后使用。
相关问题 更多 >
编程相关推荐