用互相关矩阵检验多个数据集的相似性

2024-09-27 18:10:15 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图比较几个数据集,基本上测试它们是否显示相同的特性,尽管这个特性可能会被移动、反转或减弱。 下面是一个非常简单的例子:

A = np.array([0., 0, 0, 1., 2., 3., 4., 3, 2, 1, 0, 0, 0])
B = np.array([0., 0, 0, 0, 0, 1, 2., 3., 4, 3, 2, 1, 0])
C = np.array([0., 0, 0, 1, 1.5, 2, 1.5, 1, 0, 0, 0, 0, 0])
D = np.array([0., 0, 0, 0, 0, -2, -4, -2, 0, 0, 0, 0, 0])
x = np.arange(0,len(A),1)

That look like this

我认为最好的方法是将这些信号归一化,得到绝对值(在这个阶段,它们的衰减对我来说并不重要,我对位置感兴趣。。。但我可能错了,所以我也欢迎对这个概念的思考)并计算它们重叠的面积。{我看起来很简单,但是我很难理解。在

^{pr2}$

然后看起来像这样: ![Normalized

但是,当我试图从答案中实施解决方案时,我遇到了问题。在

旧的

for c1,w1 in enumerate([a,b,c,d]):
    for c2,w2 in enumerate([a,b,c,d]):
        w1 = np.abs(w1)
        w2 = np.abs(w2)
        M[c1,c2] = integrate.trapz(min(np.abs(w2).any(),np.abs(w1).any()))
print M

产生TypeError: 'numpy.bool_' object is not iterable或{}。但我只包括了.any(),因为没有它们,我得到的是{}。在

编辑-新建 (谢谢@Kody King)

新代码现在是:

M = np.zeros([4,4])
SH = np.zeros([4,4])
for c1,w1 in enumerate([a,b,c,d]):
    for c2,w2 in enumerate([a,b,c,d]):
        crossCorrelation = np.correlate(w1,w2, 'full')
        bestShift = np.argmax(crossCorrelation)

        # This reverses the effect of the padding.
        actualShift = bestShift - len(w2) + 1
        similarity = crossCorrelation[bestShift]

        M[c1,c2] = similarity
        SH[c1,c2] = actualShift
M = M/M.max()
print M, '\n', SH

以及输出:

[[ 1.          1.          0.95454545  0.63636364]
 [ 1.          1.          0.95454545  0.63636364]
 [ 0.95454545  0.95454545  0.95454545  0.63636364]
 [ 0.63636364  0.63636364  0.63636364  0.54545455]] 
[[ 0. -2.  1.  0.]
 [ 2.  0.  3.  2.]
 [-1. -3.  0. -1.]
 [ 0. -2.  1.  0.]]

移位矩阵现在看起来不错,但实际的相关矩阵不好。我真的很困惑,因为最小的相关值是用来与d本身相关的。我现在想要实现的是:


编辑-更新

按照建议,我使用了推荐的标准化公式(将信号除以其和),但问题没有解决,只是颠倒过来了。现在d和d的相关性是1,但是所有其他的信号都与它们本身不相关。在

新输出:

[[ 0.45833333  0.45833333  0.5         0.58333333]
 [ 0.45833333  0.45833333  0.5         0.58333333]
 [ 0.5         0.5         0.57142857  0.66666667]
 [ 0.58333333  0.58333333  0.66666667  1.        ]] 
[[ 0. -2.  1.  0.]
 [ 2.  0.  3.  2.]
 [-1. -3.  0. -1.]
 [ 0. -2.  1.  0.]]

  1. 为了使信号与其自身相关,相关值应为最高值(即在主对角线上具有最高值)。在
  2. 为了得到介于0和1之间的相关值,因此,我将在主对角线上使用1,在其他地方使用其他数字(0.x)。在

我希望M=M/M.max()可以完成这项工作,但前提是条件1得到满足,而目前还没有满足


Tags: infor信号shnpanyabsarray
2条回答

要在向量之间使用互相关:

例如:

>>> np.correlate(A,B)
array([ 31.])

>>> np.correlate(A,C)
array([ 19.])

>>> np.correlate(A,D)
array([-28.])

如果你不在乎符号,你可以简单地取绝对值。。。在

正如ssm所说,numpy的关联函数对于这个问题很有效。你说过你对这个职位感兴趣。关联函数还可以帮助您判断一个序列与另一个序列的偏移量。在

import numpy as np

def compare(a, b):
    # 'full' pads the sequences with 0's so they are correlated
    # with as little as 1 actual element overlapping.
    crossCorrelation = np.correlate(a,b, 'full')
    bestShift = np.argmax(crossCorrelation)

    # This reverses the effect of the padding.
    actualShift = bestShift - len(b) + 1
    similarity = crossCorrelation[bestShift]

    print('Shift: ' + str(actualShift))
    print('Similatiy: ' + str(similarity))
    return {'shift': actualShift, 'similarity': similarity}

print('\nExpected shift: 0')
compare([0,0,1,0,0], [0,0,1,0,0])
print('\nExpected shift: 2')
compare([0,0,1,0,0], [1,0,0,0,0])
print('\nExpected shift: -2')
compare([1,0,0,0,0], [0,0,1,0,0])

编辑:

在关联每个序列之前,您需要将它们规范化,否则较大的序列将和所有其他序列具有非常高的相关性。在

互相关的一个特性是:

latex

所以,如果用每个序列除以它的和来规范化,相似度总是在0和1之间。在

我建议你不要取序列的绝对值。这会改变形状,而不仅仅是比例。例如np.abs([1,-2])==[1,2]。规范化将已经确保序列大部分是正的,加起来等于1。在

第二次编辑:

我意识到了。把信号想象成向量。规范化向量本身总是有一个最大点积。互相关只是在各种位移下计算的点积。如果像向量一样规范化信号(s除以sqrt(s dots s)),那么自相关总是最大和1。在

^{pr2}$

输出:

[[ 1.          1.          0.97700842  0.86164044]
[ 1.          1.          0.97700842  0.86164044]
[ 0.97700842  0.97700842  1.          0.8819171 ]
[ 0.86164044  0.86164044  0.8819171   1.        ]]
[[ 0. -2.  1.  0.]
[ 2.  0.  3.  2.]
[-1. -3.  0. -1.]
[ 0. -2.  1.  0.]]

相关问题 更多 >

    热门问题