繁体   English   中英

更改列表的最后1000个值的最小值和最大值

[英]Minimum and maximum of the last 1000 values of the changing list

我正在创建一个迭代算法(蒙特卡罗方法)。 该算法在每次迭代时返回一个值,从而创建一个值流。

我需要分析这些值并在1000返回值带有一些epsilon时停止算法。

我决定实现它计算最后1000值的maxmin ,然后使用这个公式(max-min)/min计算error并将其与epsilon进行比较: error<=epsilon 如果达到此条件,请停止迭代并返回结果。

  1. 第一个大胆的想法是使用一个list并为其append新值,计算每次追加后最后1000值的maxmin

  2. 然后我决定不再使用1000最后的值。 所以我想起了deque 这是一个非常好的主意,因为在deque对象的两端添加和删除的复杂性是O(1) 但它没有解决需要在每次迭代中经历所有最后1000个值来计算minmax

  3. 然后我记得有heapq模块 它使数据保持在每时每刻高效返回最小数据的方式。 但我需要最小和最大的。 此外,我需要保留元素的顺序,以便我可以保留1000最后返回的算法元素,我不知道如何使用heapq实现它。

考虑到所有这些想法,我决定在这里问:

如何最有效地解决此任务?

如果您有空/愿意更改error定义,您可能需要考虑使用variance而不是(max-min)/min

您可以逐步计算方差 是的,使用此方法,您不会从流中删除任何值 - 方差将取决于所有值。 但那又怎么样? 有了足够的值,前几个对方差无关紧要,当足够的值聚集在某个固定值附近时,平均值variance/n将变小。

因此,您可以选择在variance/n < epsilon时停止。

作为@ unutbu优秀创意的改进,您可以考虑使用指数加权移动方差。 它可以在每次观察O(1)时间内计算,需要O(1)空间,并且具有随着观察变老而自动降低观察重量的优点。

以下论文有相关公式: 链接 参见其中的等式(140) - (143)。

最后,您可能希望使用标准偏差而不是方差。 它只是方差的平方根,并且具有与原始数据具有相同单位的优点。 这应该可以更容易地制定有意义的停止标准。

numpy怎么样?

只是为了比较速度:

import numpy as np
a = range(1000)
b = np.arange(1000)

max(a) # 29.7us
b.max() # 7.29us

你可以无限地写这个数组:

i = 0
b = np.empty([1000]) + np.nan

your loop:
    b[i % 1000] = value
    i += 1

超过1000次迭代的值将被覆盖。 使用np.nanmin(b)np.nanmax(b)得到最小值/最大值。

nan背后的想法是你用1000纳秒初始化这个数组,然后你一个接一个地覆盖它们。 nanminnanmax方法忽略了这些nan。

我担心我现在无法提供一个很好的Python答案,但我会给你一个你需要使用的数据结构的大纲:

将1000个项目保留在FIFO队列中。 保持指向队列中最大和最小项的指针。 如果其中一个离开队列,则在队列中搜索新的最大/最小值(根据您的数据计算的摊销成本)。 如果新的最大/最小值进入队列,只需更新指针(O(1))。 假设您的数据正在收敛,这应该可以正常工作。

创建具有minvalue和maxvalue属性的deque子类。 添加或删除条目时,将它们与当前的最小值和最大值进行比较 - 如果要删除的值是当前最小值或最大值,则只需重新扫描最小值/最大值的双端队列。 添加时,只需将新值与当前最小值和最大值进行比较,然后进行相应更新。 这将优化您的双端队列扫描最小/最大值。

你可以使用两个斐波纳契堆 添加值在O(1)中,删除在O(log(n))中。 在您的问题中,您已经建议使用heapq模块。 我不确定它提供了什么样的堆,但是正常的堆也可以非常顺利地工作。

您只能从一个堆中提取最小值而不是最大值的问题可以通过保留两个堆来解决。 由于我不知道heapq模块,你或者可以提供它自己的比较函数,或者你可以使用-value而不是第二个堆的键的value

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM