【问题标题】:Find the position of a lowest difference between numpy arrays查找 numpy 数组之间差异最小的位置
【发布时间】:2015-10-08 14:39:28
【问题描述】:

我有两个音乐文件:一个是无损的,声音间隙很小(此时它只是静音,但可以是任何东西:正弦曲线或只是一些噪音)和一个 mp3:

In [1]: plt.plot(y[:100000])
Out[1]: 

In [2]: plt.plot(y2[:100000])
Out[2]: 

这个列表相似但不完全相同,所以我需要缩小这个差距,以找到一个列表在另一个列表中的第一次出现,并且具有最低的 delta 错误。

这是我的解决方案(5.7065 秒):

error = []
for i in range(25000):
    y_n = y[i:100000]
    y2_n = y2[:100000-i]
    error.append(abs(y_n - y2_n).mean())
start = np.array(error).argmin()

print(start, error[start]) #23057 0.0100046

有什么pythonic方法可以解决这个问题吗?

编辑: 在计算特殊点之间的平均距离后(例如数据 == 0.5),我将搜索区域从 25000 减少到 2000。这给了我 0.3871 秒的合理时间:

a = np.where(y[:100000].round(1) == 0.5)[0]
b = np.where(y2[:100000].round(1) == 0.5)[0]

mean = int((a - b[:len(a)]).mean())
delta = 1000

error = []
for i in range(mean - delta, mean + delta):
...

【问题讨论】:

  • 如果我们不比较整个数组而只比较其中最独特的部分会怎样?

标签: python numpy


【解决方案1】:

您正在尝试做的是两个信号的cross-correlation

这可以使用scipy 库中的signal.correlate 轻松完成:

import scipy.signal
import numpy as np

# limit your signal length to speed things up
lim = 25000

# do the actual correlation
corr = scipy.signal.correlate(y[:lim], y2[:lim], mode='full')

# The offset is the maximum of your correlation array,
# itself being offset by (lim - 1):
offset = np.argmax(corr) - (lim - 1)

您可能想看看this 对类似问题的回答。

【讨论】:

  • 它比我的解决方案慢三倍:18.4793s 对 5.7065s :)
【解决方案2】:

我们先生成一些数据

N = 1000
y1 = np.random.randn(N)
y2 = y1 + np.random.randn(N) * 0.05
y2[0:int(N / 10)] = 0

在这些数据中,y1y2几乎相同(注意添加的小噪音),但前 10% 的 y2 是空的(类似于您的示例)

我们现在可以计算两个向量之间的绝对差,并找到绝对差低于灵敏度阈值的第一个元素:

abs_delta = np.abs(y1 - y2)
THRESHOLD = 1e-2
sel = abs_delta < THRESHOLD
ix_start = np.where(sel)[0][0]


fig, axes = plt.subplots(3, 1)
ax = axes[0]
ax.plot(y1, '-')
ax.set_title('y1')
ax.axvline(ix_start, color='red')
ax = axes[1]
ax.plot(y2, '-')
ax.axvline(ix_start, color='red')
ax.set_title('y2')

ax = axes[2]
ax.plot(abs_delta)
ax.axvline(ix_start, color='red')
ax.set_title('abs diff')

如果重叠部分确实“几乎相同”,则此方法有效。如果相似度较低,您将不得不考虑更智能的对齐方式。

【讨论】:

  • 感谢您的回答,但这不是我的问题,您应该将您的 y2[0:int(N / 10)] = 0 更改为 y2 = np.hstack([np.zeros(int(N / 10)),y2])[:N]
  • 如果你知道y2本质上是y1,除了它的初始分数是“安静的”,那你为什么不能简单地搜索y2的点绝对值大于某个阈值?
  • 因为对我来说减少轨道之间的增量误差非常重要,而不仅仅是减少垃圾(例如,我不介意两个文件中是否有 5 秒的静音)。
  • 1.找到静音停止的点 (ix = np.where(np.abs(y2)&gt;THRESHOLD)[0][0]) 2. 修剪数组 (y2=y2[ix:]; y1=y1[ix:]) 3. 计算差异 (d=y1 - y2) 我错过了什么吗?
【解决方案3】:

我认为您正在寻找的是相关性。这是一个小例子。

import numpy as np

equal_part = [0, 1, 2, 3, -2, -4, 5, 0]
y1 = equal_part + [0, 1, 2, 3, -2, -4, 5, 0]
y2 = [1, 2, 4, -3, -2, -1, 3, 2]+y1

np.argmax(np.correlate(y1, y2, 'same'))

输出:

7

所以这会返回时间差,其中两个信号之间的相关性最大。如您所见,在示例中,时间差应为 8,但这取决于您的数据... 另请注意,两个信号的长度相同。

【讨论】:

  • 是的,我不知何故忘记了相关性,但不幸的是,您的示例也不起作用:In [109]: np.correlate([0, 1, 2, 3, 4], [1, 2, 3, 4, 5], "same") Out[109]: array([14, 26, 40, 30, 20]) 但它应该是第二个元素而不是第三个元素。
猜你喜欢
  • 2020-01-11
  • 2021-06-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-13
  • 1970-01-01
  • 2021-03-22
相关资源
最近更新 更多