numpy矢量化而不是循环

numpy矢量化而不是循环,numpy,vectorization,Numpy,Vectorization,我有以下等式: 其中v,mu为| R^3,其中σ为| R^(3x3),其中结果为标量值。在numpy实现这一点没有问题: result = np.transpose(v - mu) @ Sigma_inv @ (v - mu) 现在我有一堆v向量(我们称它们为v\in | R^3xn),我会 喜欢以矢量化的方式执行上述等式,以便 结果我在| R^1xn中得到一个新的向量结果 # pseudocode Result = np.zeros((n, 1)) for i,v in V: Re

我有以下等式:

其中v,mu为| R^3,其中σ为| R^(3x3),其中结果为标量值。在numpy实现这一点没有问题:

result = np.transpose(v - mu) @ Sigma_inv @ (v - mu)
现在我有一堆v向量(我们称它们为v\in | R^3xn),我会 喜欢以矢量化的方式执行上述等式,以便 结果我在| R^1xn中得到一个新的向量结果

# pseudocode
Result = np.zeros((n, 1))
for i,v in V:
    Result[i,:] = np.transpose(v - mu) @ Sigma_inv @ (v - mu)
我查看了np.vectorize,但文档表明它与循环所有条目一样,我不希望这样做。什么是优雅的矢量化解决方案

作为旁侧节点:n可能相当大,| R^nxn矩阵肯定不适合我的内存

编辑:工作代码示例

import numpy as np

S = np.array([[1, 2], [3,4]])
V = np.array([[10, 11, 12, 13, 14, 15],[20, 21, 22, 23, 24, 25]])

Res = np.zeros((V.shape[1], 1))
for i in range(V.shape[1]):
    v = np.transpose(np.atleast_2d(V[:,i]))
    Res[i,:] = (np.transpose(v) @ S @ v)[0][0]

print(Res)

这对你有用吗

res = np.diag(V.T @ S @ V).reshape(-1, 1)
它似乎提供了与您想要的相同的结果

import numpy as np

S = np.array([[1, 2], [3,4]])
V = np.array([[10, 11, 12, 13, 14, 15],[20, 21, 22, 23, 24, 25]])

Res = np.zeros((V.shape[1], 1))
for i in range(V.shape[1]):
    v = np.transpose(np.atleast_2d(V[:,i]))
    Res[i,:] = (np.transpose(v) @ S @ v)[0][0]

res = np.diag(V.T @ S @ V).reshape(-1, 1)

print(np.all(np.isclose(Res, res)))
# output: True

虽然使用
np.einsum可能有一个更高效的内存解决方案,但这里有一个简单的解决方案:

import numpy as np

S = np.array([[1, 2], [3,4]])
V = np.array([[10, 11, 12, 13, 14, 15],[20, 21, 22, 23, 24, 25]])

Res = np.sum((V.T @ S) * V.T, axis=1)
使用和的组合-


这是矩阵/向量堆栈的乘法。将S和V设置为正确形状后可以执行此操作:

S = S[np.newaxis, :, :]
VT = V.T[:, np.newaxis, :]
V = VT.transpose(0, 2, 1)    

tmp = np.matmul(S, V)
Res = np.matmul(VT, tmp)

print(Res)
#[[[2700]]
# [[3040]]
# [[3400]]
# [[3780]]
# [[4180]]
# [[4600]]]

即使使用循环(例如,包括
import
语句和您使用的所有符号的定义),如果您能提供一个您想要实现的最低限度的工作示例,这将更容易。正确:我添加了一个最低限度的示例,我将研究
np.einsum
,虽然我相信它是
numpy
中最神秘的函数之一,但它可能正是您想要的。谢谢您的提示!您的解决方案的问题是,我的应用程序中的“n”非常大,因此矩阵R^{nxn}肯定无法放入内存。由@Divarak提供的解决方案优于此。我的问题是V.T@S@V太大,无法装入内存,因为它将是| R^{nxn}juqa是的,我已将答案更改为仅使用nx2数组。这与Divakar的答案基本相同,尽管einsum可能比乘法和求和更快。谢谢,我对一个有5000.000个条目的向量的两种解决方案进行了基准测试,您的直觉是正确的:einsum需要约100ms,而您的解决方案需要约150ms(通过多次迭代进行基准测试).您可能需要在末端进行重塑以匹配MWE,但除此之外,这是非常棒的!
S = S[np.newaxis, :, :]
VT = V.T[:, np.newaxis, :]
V = VT.transpose(0, 2, 1)    

tmp = np.matmul(S, V)
Res = np.matmul(VT, tmp)

print(Res)
#[[[2700]]
# [[3040]]
# [[3400]]
# [[3780]]
# [[4180]]
# [[4600]]]