【发布时间】:2015-12-14 18:43:21
【问题描述】:
我正在尝试自定义 DBSCAN 算法,以便如果仅在 x 方向 上的两点之间的距离大于某个数字,或者仅在 y 方向 上的两点之间的距离大于某个数字。但是,我在执行此操作时遇到了一些麻烦。
到目前为止,这是我的代码:
public void ComputeClusterDbscan(DatasetItem[] allPoints, double epsilon, int minPts, double[] currentpt, double[] nextpt, out HashSet<DatasetItem[]> clusters)
{
var allPointsDbscan = allPoints.Select(x => new DbscanPoint(x)).ToArray();
int clusterId = 0;
for (int i = 0; i < allPointsDbscan.Length - 1 ; i++)
{
int j = i + 1;
DbscanPoint p = allPointsDbscan[i];
if (p.IsVisited)
continue;
p.IsVisited = true;
DbscanPoint[] neighborPts = null;
RegionQuery(allPointsDbscan, p.ClusterPoint, epsilon, out neighborPts);
//calculate distance between points in x and y directions
double xDirection = Math.Abs(allPointsDbscan[j].ClusterPoint.X - allPointsDbscan[i].ClusterPoint.X);
double yDirection = Math.Abs(allPointsDbscan[j].ClusterPoint.Y - allPointsDbscan[i].ClusterPoint.Y);
if (xDirection > 0.299 | yDirection > 0.199)
{
//begin new cluster
}
if (neighborPts.Length < minPts)
p.ClusterId = (int)ClusterIds.Noise;
else
{
clusterId++;
ExpandCluster(allPointsDbscan, p, neighborPts, clusterId, epsilon, minPts);
}
}
clusters = new HashSet<DatasetItem[]>(
allPointsDbscan
.Where(x => x.ClusterId > 0)
.GroupBy(x => x.ClusterId)
.Select(x => x.Select(y => y.ClusterPoint).ToArray())
);
}
【问题讨论】:
-
这个问题很老,所以你希望能解决这个问题。但是您需要在 RegionQuery 函数中添加 dx 和 dy 比较,而不是在 ComputeClusterDbScan 函数中。 RegionQuery 确定任何给定点是否可以属于传入点的集群。它通过在满足所有被视为邻居的标准时将每个点添加到邻居列表中来做到这一点。在您的情况下,除了需要在指定的 epsilon 距离内之外,您还将进一步检查每个点是否在投影 x/y 距离内。如果没有,请不要添加到邻居列表中。