python - 找到三个 'connected' 矩阵的最大最小值的最快方法

标签 python numpy matrix optimization memory

两个矩阵的答案在 question 中给出,但我不确定如何将此逻辑应用于三个成对连接的矩阵,因为没有“自由”索引。我想最大化以下功能:

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

其中 ABC 是矩阵,ij和 k 是范围最大为矩阵各自维度的索引。我想找到 (i, j, k) 使得 f(i, j, k) 最大化。我目前正在这样做:

import numpy as np
import itertools

I = 100
J = 150
K = 200

A = np.random.rand(I, J)
B = np.random.rand(J, K)
C = np.random.rand(I, K)

# All the different i,j,k
combinations = itertools.product(np.arange(I), np.arange(J), np.arange(K))
combinations = np.asarray(list(combinations))

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

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

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

[49 14 136]

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

在其他语言中,您可能可以构造矩阵,以便它们包含指向 ABC 的指针,但我没有看到如何在 Python 中实现这一点。

编辑:查看后续问题以获取更多索引 here

最佳答案

我们可以使用numpy广播来暴力破解它,或者尝试一些智能分支切割:

import numpy as np

def bf(A,B,C):
    I,J = A.shape
    J,K = B.shape
    return np.unravel_index((np.minimum(np.minimum(A[:,:,None],C[:,None,:]),B[None,:,:])).argmax(),(I,J,K))

def cut(A,B,C):
    gmx = min(A.min(),B.min(),C.min())
    I,J = A.shape
    J,K = B.shape
    Y,X = np.unravel_index(A.argsort(axis=None)[::-1],A.shape)
    for y,x in zip(Y,X):
        if A[y,x] <= gmx:
            return gamx
        curr = np.minimum(B[x,:],C[y,:])
        camx = curr.argmax()
        cmx = curr[camx]
        if cmx >= A[y,x]:
            return y,x,camx
        if gmx < cmx:
            gmx = cmx
            gamx = y,x,camx
    return gamx
            
from timeit import timeit

I = 100
J = 150
K = 200

for rep in range(4):
    print("trial",rep+1)
    A = np.random.rand(I, J)
    B = np.random.rand(J, K)
    C = np.random.rand(I, K)

    print("results identical",cut(A,B,C)==bf(A,B,C))
    print("brute force",timeit(lambda:bf(A,B,C),number=2)*500,"ms")
    print("branch cut",timeit(lambda:cut(A,B,C),number=10)*100,"ms")

事实证明,在给定的尺寸下, Twig 切割是非常值得的:

trial 1
results identical True
brute force 169.74265850149095 ms
branch cut 1.951422297861427 ms
trial 2
results identical True
brute force 180.37619898677804 ms
branch cut 2.1000938024371862 ms
trial 3
results identical True
brute force 181.6371419990901 ms
branch cut 1.999850495485589 ms
trial 4
results identical True
brute force 217.75578951928765 ms
branch cut 1.5871295996475965 ms

Twig 切割是如何工作的?

我们选择一个数组(例如 A)并将其从最大到最小排序。然后,我们逐一遍历数组,将每个值与其他数组中的适当值进行比较,并跟踪运行的最大值和最小值。一旦最大值不小于 A 中的剩余值,我们就完成了。由于这通常会很快发生,因此我们可以节省大量资金。

关于python - 找到三个 'connected' 矩阵的最大最小值的最快方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69461798/

相关文章:

python - 类型错误 : unsupported operand type(s) for +=: 'builtin_function_or_method' and 'int'

python - 有没有办法使用预训练的 doc2vec 模型来评估某些文档数据集

python - 如何 cv2.imshow 存储在 Numpy 数组中的图像?

r - 如何在 R 中创建一个大数据框,无论是否先创建矩阵,然后将其转换为 data.frame?

c++ - 编译器提示 "Error: stray '\24 0' in program"

python - 在 Peewee 中执行子字符串查询

python - 打印一行中的字母 + 1

python - 句子[:] mean here?]是什么意思

c++ - 如何初始化未知大小的多维 vector ,C++

python - Numpy polyfit - 协方差矩阵