Math 我如何计算「;差异“;在两个点序列之间?

Math 我如何计算「;差异“;在两个点序列之间?,math,numerical-methods,edit-distance,Math,Numerical Methods,Edit Distance,我有两个长度为n和m的序列。每一个都是一系列点的形式(x,y)和代表曲线的图像。我需要找出这些序列有多不同(或相似),这一事实 一个序列可能比另一个序列长(即,一个序列可能比另一个序列长一半或四分之一,但如果它们追踪的曲线大致相同,则它们是相同的) 这些序列的方向可能相反(即序列1从左向右,而序列2从右向左) 我研究了一些差异估计,比如Levenshtein,以及蛋白质折叠结构相似性匹配中的编辑距离,但它们似乎都不起作用。我可以写我自己的暴力方法,但我想知道是否有更好的方法 谢谢。为什么不做一些

我有两个长度为n和m的序列。每一个都是一系列点的形式(x,y)和代表曲线的图像。我需要找出这些序列有多不同(或相似),这一事实

  • 一个序列可能比另一个序列长(即,一个序列可能比另一个序列长一半或四分之一,但如果它们追踪的曲线大致相同,则它们是相同的)
  • 这些序列的方向可能相反(即序列1从左向右,而序列2从右向左)

    我研究了一些差异估计,比如Levenshtein,以及蛋白质折叠结构相似性匹配中的编辑距离,但它们似乎都不起作用。我可以写我自己的暴力方法,但我想知道是否有更好的方法


  • 谢谢。

    为什么不做一些曲线拟合程序(最小二乘法,无论是普通的还是非线性的),看看形状参数上的系数是否相同。如果将其作为面板数据类型的模型运行,则会有明确的统计测试,以确定参数集之间是否存在显著差异。这将解决相同曲线但以不同分辨率采样的问题

    您的意思是您正在尝试匹配已在x,y坐标中转换的曲线吗?图像处理的一种技术是使用链码[我正在寻找一个合适的参考,但我现在能找到的就是]对每个序列进行编码,然后比较这些链码。可以求差的和(模8),如果结果为0,则曲线相同。由于序列具有不同的长度,并且不一定从同一相对位置开始,因此您必须移动一个序列并反复执行此操作,但您只需创建一次链码。检测其中一个序列是否反转的唯一方法是尝试其中一个序列的正向和反向。如果曲线不完全相同,那么和将大于零,但很难简单地判断曲线与和的不同程度


    此方法不会具有旋转不变性。如果您需要一种旋转不变的方法,那么应该查看以边界为中心的极轴编码。我找不到这方面的免费参考资料,但如果您需要我描述它,请让我知道。

    以下方法可能有效:

    对于两个序列:

    通过序列拟合曲线。确保从[0,1]到该曲线上的点之间有一个连续的一对一函数。也就是说,对于0和1之间的每个(实数)数字,此函数返回曲线上属于它的点。通过跟踪从0到1的所有数字的函数,可以得到整个曲线

    拟合曲线的一种方法是在每对连续点之间绘制一条直线(这不是一条好曲线,因为它有急弯,但可能适合您的目的)。在这种情况下,可以通过计算所有线段(毕达哥拉斯)的总长度来获得该函数。曲线上对应于数字Y(0和1之间)的点对应于曲线上距离序列上第一个点Y*(所有线段的总长度)的点,通过在线段上移动来测量(!!)

    现在,在我们获得了第一个序列的函数F(double)和第二个序列的函数G(double)之后,我们可以如下计算相似性:

    double epsilon = 0.01;
    double curveDistanceSquared = 0.0;
    for(double d=0.0;d<1.0;d=d+epsilon)
    {
       Point pointOnCurve1 = F(d);    
       Point pointOnCurve2 = G(d); 
       //alternatively, use G(1.0-d) to check whether the second sequence is reversed       
       double distanceOfPoints = pointOnCurve1.EuclideanDistance(pointOnCurve2);
       curveDistanceSquared = curveDistanceSquared + distanceOfPoints * distanceOfPoints;
    }
    similarity = 1.0/ curveDistanceSquared;
    
    def resample(path, numPoints)
        pathLength = pathLength(path)  #write this function
    
        segments = generateSegments(path)
        currentSegment = next(segments)
        segmentsSoFar = [currentSegment]
    
        for i in range(numPoints):
            samplePosition = i/(numPoints-1)*pathLength
            while samplePosition > pathLength(segmentsSoFar)+currentSegment.length:
                currentSegment = next(segments)
                segmentsSoFar.insert(currentSegment)
            difference = samplePosition - pathLength(segmentsSoFar)
            howFar = difference/currentSegment.length
            yield Point((1-howFar)*currentSegment.start + (howFar)*currentSegment.end)
    

    随后,您尝试以最小化距离的方式选择R。(要查看发生了什么,请注意G(R(d))也跟踪曲线)

    我会使用曲线拟合程序,但也会加入一个常数项,即0=B0+B1*X+B2*Y+B3*X*Y+B4*X^2等。这将捕获平移方差,然后您可以对两组点形成的曲线的估计系数进行统计比较,作为对它们进行分类的一种方式。我假设如果数据在x-y平面上形成任意曲线,就必须进行双变量插值

    步骤1:规范化方向。例如,假设所有曲线都从字典顺序最低的端点开始

    def inCanonicalOrientation(path):
        return path if path[0]<path[-1] else reversed(path)
    
    这可以从线性重采样修改为更好的方式

    def error(pathA, pathB):
        pathA = inCanonicalOrientation(pathA)
        pathB = inCanonicalOrientation(pathB)
    
        higherResolution = max([len(pathA), len(pathB)])
        resampledA = resample(pathA, higherResolution)
        resampledB = resample(pathA, higherResolution)
    
        error = sum(
            abs(pointInA-pointInB)
            for pointInA,pointInB in zip(pathA,pathB)
        )
        averageError = error / len(pathAorB)
        normalizedError = error / Z(AorB)
        return normalizedError
    

    其中Z类似于路径的“直径”,可能是路径中任意两点之间的最大欧几里德距离。

    能否更具体地说明编辑距离中的内容?你想在序列上找到某种度量空间吗?你只是想给比赛排名吗?或者你只是在寻找一个主观的相似性度量?@templatetypedef-我真正想做的是将序列(路线)分类为组。我希望通过计算相似性或差异值并使用预定义的阈值将该序列分配给一个组来实现这一点。当你说一个序列比另一个短时,你是说它只遵循另一条曲线的一部分吗,或者它遵循相同的曲线,但点数较少?@Beta-可能两者都是。这些序列是穿过空间的对象的位置,输入的数据容易出错-它可能从中间开始(仅部分曲线),或者可能缺少信息(较少的点)。是否有关于曲线的更多信息?例如,它们是否可以自相交?Catmull Rom能很好地逼近曲线吗?等等…知道一条曲线与另一条曲线有多大的不同是很重要的,因为这就是我对曲线进行分类的方式,尽管看起来,如果曲线类有足够的不同,求和会给我一个粗略的概念。此外,曲线的绝对坐标也很重要,不仅是它们的空间性(两条看起来相同但位于图像不同部分的曲线是不同的),而且它也很重要
    def error(pathA, pathB):
        pathA = inCanonicalOrientation(pathA)
        pathB = inCanonicalOrientation(pathB)
    
        higherResolution = max([len(pathA), len(pathB)])
        resampledA = resample(pathA, higherResolution)
        resampledB = resample(pathA, higherResolution)
    
        error = sum(
            abs(pointInA-pointInB)
            for pointInA,pointInB in zip(pathA,pathB)
        )
        averageError = error / len(pathAorB)
        normalizedError = error / Z(AorB)
        return normalizedError