Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 修改DBSCAN算法_C#_Algorithm_Dbscan - Fatal编程技术网

C# 修改DBSCAN算法

C# 修改DBSCAN算法,c#,algorithm,dbscan,C#,Algorithm,Dbscan,我正在尝试自定义DBSCAN算法,这样,如果仅在x方向上的两点之间的距离大于某个数字,或者仅在y方向上的两点之间的距离大于某个数字,DBSCAN算法也将启动一个新簇。然而,我在做这件事时遇到了一些麻烦 以下是我目前的代码: public void ComputeClusterDbscan(DatasetItem[] allPoints, double epsilon, int minPts, double[] currentpt, double[] nextpt, out HashSe

我正在尝试自定义DBSCAN算法,这样,如果仅在x方向上的两点之间的距离大于某个数字,或者仅在y方向上的两点之间的距离大于某个数字,DBSCAN算法也将启动一个新簇。然而,我在做这件事时遇到了一些麻烦

以下是我目前的代码:

     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())
            );
    }
public void ComputeClusterDbscan(DatasetItem[]allPoints,double epsilon,int minPts,double[]currentpt,double[]nextpt,out HashSet clusters)
{
var allPointsDbscan=allPoints.Select(x=>newdbscanpoint(x)).ToArray();
int-clusterId=0;
对于(int i=0;i0.299 | Y方向>0.199)
{
//开始新集群
}
if(邻接长度x.ClusterId>0)
.GroupBy(x=>x.ClusterId)
.Select(x=>x.Select(y=>y.ClusterPoint).ToArray()
);
}

您无需修改DBSCAN即可完成此操作

三种解决方案:

  • 缩放数据集,使x和y阈值彼此可比,然后使用最大范数。也就是说,如果有eps_x和eps_y,则将x坐标乘以1/eps_x,将y坐标乘以1/eps_y,然后使用eps=1和最大范数
  • 使用加权最大范数
  • 使用通用DBSCAN。例如,在ELKI实现中,添加具有两个epsilon参数的新邻居谓词很容易。以交叉点(邻居x,邻居y)为邻域

  • 所有这些方法都有效地改变了“regionQuery”的结果。

    这两种解决方案都不能解决我的问题。缩放肯定不起作用,因为我正在检查距离;而缩小数据的比例只会给我带来“假”肯定。你必须精确地调整数据以匹配你想要的阈值。我不是说将它们规范化为[0;1]。相信我,如果做得好,这三种方法都会奏效。对不起,我不明白你的意思;请给我看一下。要在x轴上放置重量w,将x乘以w。要在y轴上放置权重u,请将y乘以u!哈哈,我完全理解如何使用标量乘数,但这对我的数据集没有帮助。请记住,我想知道距离(仅在x方向上)是否大于我选择的某个数字…例如0.5)或距离(仅在y方向上大于1.5)。如果它更大,在任何一个方向,然后开始一个新的集群。在这种情况下,缩放不会有任何帮助…当我试图计算距离时,它只会使我的数据变得不成比例。这个问题已经很老了,所以希望你已经解决了这个问题。但是您需要在RegionQuery函数中添加dx和dy比较,而不是ComputeClusterDbScan函数。RegionQuery确定任何给定点是否可以属于传入点的集群。它通过在满足被视为邻居的所有条件时将每个点添加到邻居列表来实现这一点。在您的例子中,除了需要在指定的ε距离内之外,还需要进一步检查每个点是否在投影x/y距离内。如果没有,不要添加到邻居列表中。