Python/Scipy : Find "bounded" min/max of a matrix

标签 python numpy scipy maximization

我认为最容易说明我的问题,一般情况很难解释。

假设我有一个矩阵

a with dimensions NxMxT,

人们可以将 T 视为时间维度(以使问题更容易)。设 (n,m) 为通过 NxM 的索引。我可能会称 (n,m) 为状态空间标识符。然后我需要找到 python/scipy 等价物

for each (n,m):
     find a*(n,m) = min(a(n,m,:) s.t. a*(n,m) > a(n,m,T)

也就是说,为整个状态空间找到仍然高于最后一次(在时间维度中)观察值的最小状态空间值。

我的第一次尝试是先解决内层问题(找到比a[...,-1]高的a):

aHigherThanLast = a[ a > a[...,-1][...,newaxis] ]

然后我想为每个 (n,m) 找到所有这些中最小的一个。不幸的是,aHigherThanLast 现在包含所有这些值的一维数组,所以我不再有 (n,m) 对应关系。对此有什么更好的方法?

还有一个问题:状态空间是可变的,它也可以是 3 维或更多维(NxMxKx...),我无法对其进行硬编码。所以任何一种

for (n,m,t) in nditer(a):

不可行。

非常感谢!

/编辑:

a = array([[[[[[[[ 0.,  2.,  1.],
             [ 0.,  2.,  1.],
             [ 0.,  2.,  1.],
             [ 0.,  2.,  1.],
             [ 0.,  2.,  1.],
             [ 0.,  2.,  1.],
             [ 0.,  2.,  1.],
             [ 0.,  2.,  1.],
             [ 0.,  2.,  1.],
             [ 0.,  2.,  1.]]]],



          [[[[ 0.,  2.,  1.],
             [ 0.,  2.,  1.],
             [ 0.,  2.,  1.],
             [ 0.,  2.,  1.],
             [ 0.,  2.,  1.],
             [ 0.,  2.,  1.],
             [ 0.,  2.,  1.],
             [ 0.,  2.,  1.],
             [ 0.,  2.,  1.],
             [ 0.,  2.,  1.]]]]],




         [[[[[ 0.,  2.,  1.],
             [ 0.,  2.,  1.],
             [ 0.,  2.,  1.],
             [ 0.,  2.,  1.],
             [ 0.,  2.,  1.],
             [ 0.,  2.,  1.],
             [ 0.,  2.,  1.],
             [ 0.,  2.,  1.],
             [ 0.,  2.,  1.],
             [ 0.,  2.,  1.]]]],



          [[[[ 0.,  2.,  1.],
             [ 0.,  2.,  1.],
             [ 0.,  2.,  1.],
             [ 0.,  2.,  1.],
             [ 0.,  2.,  1.],
             [ 0.,  2.,  1.],
             [ 0.,  2.,  1.],
             [ 0.,  2.,  1.],
             [ 0.,  2.,  1.],
             [ 0.,  2.,  1.]]]]]]]])
# a.shape = (1L, 1L, 2L, 2L, 1L, 1L, 10L, 3L). so in this case, T = 3.
# expected output would be the sort of
# b.shape = (1L, 1L, 2L, 2L, 1L, 1L, 10L), which solves
  • b[a,b,c,d,e,f,g] > a[a,b,c,d,e,f,g,-1](b 高于最新观测值)

    • a中i中没有元素同时满足

      -- a[a,b,c,d,e,f,g,t] > a[a,b,c,d,e,f,g,-1]

      -- a[a,b,c,d,e,f,g,t] < b[a,b,c,d,e,f,g] (b 是大于的最小元素最新观察)

因此,假设前一个数组是一个简单的堆栈 if [0,2,1] 沿着最后的观察,我期望

b = ones((1,1,2,2,1,1,10))*2

但是, - 如果在一些 (a,b,c,d,e,f,g) 中,不仅有 {0,1,2} 的值,还有 {3},那么我仍然想要 2 (因为它是满足 i > 1 的 i = {2,3} 中的较小者。 - 如果在某些 (a,b,c,d,e,f,g) 中只有值 {0,1,3},我想要 3,因为 i = 3 将是满足 i 的最小数字> 1.

希望这能稍微澄清一下?

/编辑2:

非常感谢答案,它有效。如果我想要相反的东西,即较小的那些中最大的,我将如何调整它?我没有尝试通过那个复杂的索引逻辑,所以我(弱)尝试只改变前三行没有成功:

        b = sort(a[...,:-1], axis=-1)
        b = b[...,::-1]
        mask = b < a[..., -1:]
        index = argmax(mask, axis=-1)
        indices = tuple([arange(j) for j in a.shape[:-1]])
        indices = meshgrid(*indices, indexing='ij', sparse=True)
        indices.append(index)
        indices = tuple(indices)
        a[indices]

此外,我的第二次尝试 [...,::-1][indices] 也没有成功。

最佳答案

我认为 E 先生的做法是正确的。您一定要先对没有最后时间值的数组进行排序:

b = np.sort(a[..., :-1], axis=-1)

理想情况下,您现在可以使用 `np.searchsorted 来查找大于最终值的第一项的位置,但不幸的是 np.searchsorted 仅适用于展平数组,所以我们必须做更多的工作,比如创建一个 bool 掩码,然后使用 np.argmax 找到第一个 True:

mask = b > a[..., -1:]
index = np.argmax(mask, axis=-1)

你现在有了索引,要提取实际值,你需要做一些索引魔术:

indices = tuple([np.arange(j) for j in b.shape[:-1]])
indices = np.meshgrid(*indices, indexing='ij', sparse=True)
indices.append(index)
indices = tuple(indices)

现在你终于可以做到了:

>>> b[indices]
array([[[[[[[ 2.,  2.,  2.,  2.,  2.,  2.,  2.,  2.,  2.,  2.]]],


          [[[ 2.,  2.,  2.,  2.,  2.,  2.,  2.,  2.,  2.,  2.]]]],



         [[[[ 2.,  2.,  2.,  2.,  2.,  2.,  2.,  2.,  2.,  2.]]],


          [[[ 2.,  2.,  2.,  2.,  2.,  2.,  2.,  2.,  2.,  2.]]]]]]])
>>> b[indices].shape
(1L, 1L, 2L, 2L, 1L, 1L, 10L)

要在较小的那些中获得最大的,您可以这样做:

mask = b >= a[..., -1:]
index = np.argmax(mask, axis=-1) - 1

即较小的项中最大的是相等或更大的项中最小项之前的项。第二种情况更清楚地表明,如果没有满足条件的项目,则此方法会给出垃圾结果。在第二种情况下,当发生这种情况时,您将获得索引的 -1,因此您可以通过 np.any(index == -1)< 检查结果是否有效.

如果第一种情况不能满足条件,你可以将索引设置为-1

mask = b > a[..., -1:]
wrong = np.all(~mask, axis=-1)
index = np.argmax(mask, axis=-1)
index[wrong] = -1

关于Python/Scipy : Find "bounded" min/max of a matrix,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19930749/

相关文章:

python - 重新粉刷开罗 window ?

python - 当我在 Windows Vista 命令提示符下运行 'import pylons' 时,为什么无法识别 Pylons?

python - Beautifulsoup 不显示所有 html 元素

python - NumPy:使用 'np.save()' 和 'allow_pickle=False' 的后果

python - 如何从一组数据点插入单个 ("non-piecewise") 三次样条?

python - 使用 genfromtxt 创建具有空列的 numpy 数组

python - NumPy - 将值环绕任意边界

python - 两个大向量之间的逐元素比较,稀疏度高

python - 使用 scipy truncnorm 拟合数据

python - 使用 scipy.linalg.lstsq 的点集的最佳拟合平面结果错误?