我有两个巨大的数字np.array
(让我们称它们为S1
和S2
,这样len(S1)>>len(S2)>>N
,其中N
是一个非常大的数字)。我希望找到S1
最有可能的候选部分等于S2
。
简单的方法是计算S2
和S1
的部分之间的运行差异,这将花费太长的时间(一次比较大约需要170个小时)。
我想到的另一种方法是手动创建一个窗口矩阵M
,其中M
的每一行i
是S1[i:(i+len(S2)]
。然后,在这种方法下,我们可以广播一个差值运算。这也是不可行的,因为它需要很长时间(比最简单的方法要少,但仍然),而且它使用了我所有的RAM。
我们可以使用卷积来并行化它吗?我们可以使用torch
/keras
来做类似的事情吗?请记住,我正在寻找最佳候选者,因此某些卷积的值只需保持顺序,因此最可能的候选者将具有最小的值。
2条答案
按热度按时间4smxwvx51#
由于您正在处理一个大型数据集,因此算法的效率远比使用更多的计算资源(例如核心)来更快地计算结果更重要。
看起来你想在更大的1D阵列中检测1D图案,同时可能具有良好的抗噪性。该操作通常可以使用相关来完成,更具体地说是cross-correlation。(FFT)。其思想是计算
FFT^-1(FFT(a) * FFT(b))
。这种方法也经常用于高效地计算卷积。对于高效地检测模式非常有用。事实上,傅立叶变换是冷战时期为探测核武器试验而发展起来的地震仪,自从它被应用于包括引力波探测在内的许多科学项目以来(更具体地说,检测两个黑洞的合并,这在非常巨大的数据集中留下特定的事件信号形状)。(与O(n²)
中的朴素相关性相反)。手动执行此处理相当麻烦。希望Scipy提供可以使用FFT的相关函数:
scipy.signal.correlate
。信号需要进行归一化以获得相关性,以提供有趣的结果。在实践中,减去平均值通常就足够了。下面是一个例子:以下是结果输出:
在这里,我们可以看到,尽管有噪声,相关性成功地在5个最佳候选中找到了模式。它的位置是3016。它实际上是这里的最佳候选,但不能保证相关性直接找到最佳候选。您需要先取K并检查每个候选以找到正确的位置。数据集越大,K越大。如果数据集很大,并且搜索的模式与数据集中的值相比可以清楚地识别,则可以将K设置为数据集的1%。可以对K优先值进行排序,以首先检查最佳候选检查可以使用L2范数
np.sum((haystack_block - needle)**2)**0.5
来完成。具有最佳L2范数的候选者是最佳候选者。相关性是避免计算所有可能候选者的L2范数的提示(5与上述示例中的数千相比)。mjqavswn2#
我假设你这样做是为了找到完美的匹配
我假设这一点的理由是你说:
我希望找到S1的最有可能的候选部分等于S2。
indices
,它的值可能是[2,123,457,513,...]indices+1
,并测试与第二个值的匹配。这可能更快,因为需要进行的比较相对较少。将成功的匹配写入新的较小的indices
数组。indices
数组将缩小到大小1。如果每个数组中的单个数值是0-255,你可能想把它们“聚集”成,比如说,一次4个值,以加快速度。但是如果它们是浮点数,你就不能这样做。
通常,这种方法的前几步会很慢,因为它要检查很多位置。但是(假设数字是相当随机的),每一个连续的步骤都会变得快得多。因此,决定它需要多长时间的因素是通过小数组的前几步。
这将需要与
indices
的最大合理尺子一样大的内存大小(您可以用下一个版本覆盖每个indices
列表,因此您只需要一个副本)。你可以并行化:
你可以给予每个并行进程一个大数组(s1)的块。你可以让块重叠
len(s2)-1
,但你只需要在第一次迭代中搜索每个块的前len(s1)
个元素:最后几个元素只是用来检测在那里结束(但不是在那里开始)的序列。但书
正如@Kelly Bundy在下面指出的那样,如果你没有在最终找到完美匹配的旅程中结束,这对你没有帮助。