我试图了解如何使用互相关来确定两个信号的相似性。 This tutorial对基本原理提供了非常清晰的解释,但是我仍然不了解如何有效使用归一化来防止强信号在能量级别不同的情况下主导互相关度量。同一位老师David Dorran讨论了归一化here的问题,并解释了如何使用点积来归一化相关性,但是我仍然有一些疑问。
我编写了这个python例程,以在一组信号中的每对信号之间进行互相关:
import numpy as np
import pandas as pd
def mycorrelate2d(df, normalized=False):
# initialize cross correlation matrix with zeros
ccm = np.zeros(shape=df.shape, dtype=list)
for i, row_dict1 in enumerate(
df.to_dict(orient='records')):
outer_row = list(row_dict1.values())
for j, row_dict2 in enumerate(
df.to_dict(orient='records')):
inner_row = list(row_dict2.values())
x = np.correlate(inner_row, outer_row)
if normalized:
n = np.dot(inner_row, outer_row)
x = x / n
ccm[i][j] = x
return ccm
假设我有3个幅度逐渐增大的信号: [1、2、3],[4、5、6]和[7、8、9]
我想对这三个信号进行互相关以查看哪些对相似,但是当我将这三个信号传递到我编写的例程中时,我似乎并没有获得相似性的度量。互相关值的大小只是能量信号的函数。期。甚至信号 与其自身的互相关 所产生的值也比该信号与另一个能量较高的信号的互相关要低。
df_x3 = pd.DataFrame(
np.array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]]).reshape(3, -1))
mycorrelate2d(df_x3)
这将产生:
array([[array([ 3, 8, 14, 8, 3]),
array([12, 23, 32, 17, 6]),
array([21, 38, 50, 26, 9])],
[array([ 6, 17, 32, 23, 12]),
array([24, 50, 77, 50, 24]),
array([ 42, 83, 122, 77, 36])],
[array([ 9, 26, 50, 38, 21]),
array([ 36, 77, 122, 83, 42]),
array([ 63, 128, 194, 128, 63])]], dtype=object)
现在,我传递相同的3个信号,但是这次我表示我想要归一化的结果:
mycorrelate2d(df_x3, normalized=True)
这将产生:
array([[array([ 0.2142, 0.5714, 1., 0.5714, 0.2142]),
array([ 0.375, 0.71875, 1., 0.5312, 0.1875]),
array([ 0.42, 0.76, 1., 0.52, 0.18])],
[array([ 0.1875, 0.5312, 1., 0.7187, 0.375]),
array([ 0.3116, 0.6493, 1., 0.6493, 0.3116]),
array([ 0.3442, 0.6803, 1., 0.6311, 0.2950])],
[array([ 0.18, 0.52, 1., 0.76, 0.42]),
array([ 0.2950, 0.6311, 1., 0.6803, 0.3442]),
array([ 0.3247, 0.6597, 1., 0.6597, 0.3247])]],
dtype=object)
所有最大值现在都是1!因此,我们从具有基于虚假差异的最大值变为完全没有最大值之间的差异!我很容易承认,我不了解如何使用互相关来检测信号之间的相似性。有人将信号与互相关进行比较的分析工作流程是什么?
答案 0 :(得分:1)
看看Compute Normalized Cross-Correlation in Python
因此,用于规范化的公式不太正确。归一化发生在我们与NCC相关之前,然后将答案除以向量长度,如本维基百科公式https://en.wikipedia.org/wiki/Cross-correlation#Zero-normalized_cross-correlation_(ZNCC)
所示所以你需要类似的东西
import numpy as np
def mycorrelate2d(df, normalized=False):
# initialize cross correlation matrix with zeros
ccm = np.zeros((3,3))
for i in range(3):
outer_row = df[i][:]
for j in range(3):
inner_row = df[j][:]
if(not normalized):
x = np.correlate(inner_row, outer_row)
else:
a = (inner_row-np.mean(inner_row))/(np.std(inner_row)*len(inner_row))
#print(a)
b = (outer_row-np.mean(outer_row))/(np.std(outer_row))
#print(b)
x = np.correlate(a,b)
ccm[i][j] = x
return ccm
df_x3 =np.array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]]).reshape(3, -1)
print(mycorrelate2d(df_x3,True))
df_x3 =np.array([[1, 2, 3],
[9, 5, 6],
[74, 8, 9]]).reshape(3, -1)
print(mycorrelate2d(df_x3,True))
输出为
[[1. 1. 1.]
[1. 1. 1.]
[1. 1. 1.]]
[[ 1. -0.72057669 -0.85933941]
[-0.72057669 1. 0.97381599]
[-0.85933941 0.97381599 1. ]]