【问题标题】:Fastest way to find the maximum minimum value of two 'connected' matrices找到两个“连接”矩阵的最大最小值的最快方法
【发布时间】:2021-11-25 19:42:12
【问题描述】:

我想最大化以下功能:

f(i, j, k) = min(A(i, j), B(j, k))

其中AB 是矩阵,ijk 是范围高达矩阵各自维度的索引。我想找到(i, j, k) 以使f(i, j, k)最大化。我目前这样做如下:

import numpy as np
import itertools

shape_a = (100       , 150)
shape_b = (shape_a[1], 200)

A = np.random.rand(shape_a[0], shape_a[1])
B = np.random.rand(shape_b[0], shape_b[1])

# All the different i,j,k
combinations = itertools.product(np.arange(shape_a[0]), np.arange(shape_a[1]), np.arange(shape_b[1]))
combinations = np.asarray(list(combinations))

A_vals = A[combinations[:, 0], combinations[:, 1]]
B_vals = B[combinations[:, 1], combinations[:, 2]]

f = np.min([A_vals, B_vals], axis=0)

best_indices = combinations[np.argmax(f)]
print(best_indices)
[ 49  14 136]

这比遍历所有(i, j, k) 更快,但是很多(并且大部分)时间都花在了构建A_valsB_vals 矩阵上。这是不幸的,因为它们包含许多重复值,因为相同的 ijk 多次出现。有没有办法做到这一点,(1) numpy 的矩阵计算速度可以保持,(2) 我不必构造内存密集型 A_valsB_vals 数组。

在其他语言中,您也许可以构造矩阵,以便它们包含指向 AB 的指针,但我不知道如何在 Python 中实现这一点。

【问题讨论】:

  • 请考虑选择这个问题的答案,这样它就不会永远在未回答的队列中。这个和你的许多其他问题都有很好的答案。
  • @MadPhysicist 我会的,可能明天等我看清楚了!

标签: python numpy matrix optimization memory


【解决方案1】:

您的值i,j,k 由集合{A,B} 中的最大值的索引确定。您可以简单地使用np.argmax()

if np.max(A) < np.max(B):
    ind = np.unravel_index(np.argmax(A),A.shape)
else:
    ind = np.unravel_index(np.argmax(B),B.shape)

它只会返回两个值,i,j 如果max({A,B}) = max({A})j,k 如果max({A,B}) = max({B})。但是,如果你得到i,j,那么k 可以是任何符合B 数组形状的值,所以随机选择其中一个值。

如果您还需要最大化其他值,那么:

if np.max(A) < np.max(B):
    ind = np.unravel_index(np.argmax(A),A.shape)
    ind = ind + (np.argmax(B[ind[1],:]),)
    
else:
    ind = np.unravel_index(np.argmax(B),B.shape)
    ind = (np.argmax(A[:,ind[0]]),) + ind

【讨论】:

  • 您的方法给出的A[ind] 对于我生成的示例绝对没有最大化。你能弄清楚你提议的细节吗?我想我错过了什么。
  • 这似乎没有考虑到列/行索引必须对两者通用的事实
  • @MadPhysicist 确实如此,但只有在集合 {A,B} 中只有一个最大值时才会起作用,如 OP 的示例中所示
  • 对于我的第一个例子,OP 说他想最大化 min(A(i, j), B(j, k)) 所以一个值要么在 A 要么在 B 但不是两者都在至少有 A.shape[0] 或 @ 987654336@可能的结果。
  • 我的理解是,对于给定的j,他想从每个矩阵中找到最大值,这保证了该对的最大最小值。所以重要的不是给定矩阵中的最大值,而是对应行/列中另一个矩阵中的最大值
【解决方案2】:

也许您可以根据 min 和 max 的实际作用重新评估您如何看待问题。假设您有以下具体示例:

>>> np.random.seed(1)
>>> print(A := np.random.randint(10, size=(4, 5)))
[[5 8 9 5 0]
 [0 1 7 6 9]
 [2 4 5 2 4]
 [2 4 7 7 9]]
>>> print(B := np.random.randint(10, size=(5, 3)))
[[1 7 0]
 [6 9 9]
 [7 6 9]
 [1 0 1]
 [8 8 3]]

您正在寻找AB 中的一对数字,使得A 中的列与B 中的行相同,并且您将获得最大的较小数字。

对于任何一组数字,当您取两个最大的数字时,会出现最大的成对最小值。因此,您正在寻找A 的每一列、B 的行中的最大值,这些对中的最小值,然后是最大值。下面是一个相对简单的解决方案:

candidate_i = A.argmax(axis=0)
candidate_k = B.argmax(axis=1)
j = np.minimum(A[candidate_i, np.arange(A.shape[1])], B[np.arange(B.shape[0]), candidate_k]).argmax()

i = candidate_i[j]
k = candidate_k[j]

确实,你看到了

>>> i, j, k
(0, 2, 2)
>>> A[i, j]
9
>>> B[j, k]
9

如果发生冲突,argmax 将始终选择第一个选项。

【讨论】:

  • 谢谢!一个问题:如果有三个连通矩阵,即f(i,j,k) = min(A(i,j),B(j,k),C(i,k)),类似的逻辑是否仍然适用?
  • 当您查看三个最大的数字时,仍然会出现最大的三个最小值。你的 3-case 有点不同,所以如果这个答案不能帮助你建立所需的直觉,请随时问另一个问题。您似乎很好地掌握了清晰准确地描述您的问题所需的详细程度
  • 完成,stackoverflow.com/questions/69461798/…。因为ik 不再是“免费的”,所以我很难应用相同的方法。
猜你喜欢
  • 2021-11-27
  • 2021-11-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-17
  • 2019-04-17
  • 2018-10-21
  • 1970-01-01
相关资源
最近更新 更多