广播对于NumPy数组 – 矢量化二次形式

huangapple go评论77阅读模式
英文:

Broadcasting for numpy array - vectorized quadratic form

问题

I'd like to compute the part of multivariate normal distribution density that is a quadratic form:

要计算多元正态分布密度的二次形式部分:

(X - mu)^T * S * (X - mu)

Assume the data:

假设数据如下:

mu = np.array([[1,2,3], [4,5,6]])
S = np.array([np.eye(3)*3, np.eye(3)*5])
X = np.array([np.random.random(3*10)]).reshape(10, 3)

Now, an iterative process would be to calculate:

现在,一个迭代的方法是计算:

(X[0] - mu[0]) @ S[0] @ (X[0] - mu[0]).T, (X[0] - mu[1]) @ S[1] @ (X[0] - mu[1]).T

However, I guess that's not the fastest approach. What I tried is:

不过,我猜这不是最快的方法。我尝试的是:

np.squeeze((X[0] - mu)[:, None] @ S) @ ((X[0] - mu)).T

But the values that I want are placed on the main diagonal of the matrix above. I could use np.diagonal(), but is there a better way to perform the calculations?

但我想要的值位于上面矩阵的主对角线上。我可以使用 np.diagonal(),但是否有更好的方法来执行计算?

英文:

I'd like to compute the part of multivariate normal distribution density that is a quadratic form

(X - mu)^T * S * (X - mu)

Assume the data

mu = np.array([[1,2,3], [4,5,6]])
S = np.array([np.eye(3)*3, np.eye(3)*5])
X = np.array([np.random.random(3*10)]).reshape(10, 3)

Now, an iterative process would be to calculate

(X[0] - mu[0]) @ S[0] @ (X[0] - mu[0]).T, (X[0] - mu[1]) @ S[1] @ (X[0] - mu[1]).T

(I don't need to vectorize with respect to X). However, I guess that's not the fastest approach. What I tried is

np.squeeze((X[0] - mu)[:, None] @ S) @ ((X[0] - mu)).T

But the values that I want are placed on the main diagonal of matrix above. I could use np.diagonal(), but is there a better way to perform the calculations?

答案1

得分: 2

我认为你差不多已经做到了。你有矩阵 A = np.squeeze((X[0] - mu)[:, None] @ S),然后你对它进行了矩阵乘法 B = ((X[0] - mu)).T),但你只想要对角元素。

正如在这里指出的那样,C = N.diag(A.dot(B)) 等同于 C = (A * B.T).sum(-1),这导致了以下解决方案:

import numpy as np

mu = np.array([[1,2,3], [4,5,6]])
S = np.array([np.eye(3)*3, np.eye(3)*5])
X = np.array([np.random.random(3*10)]).reshape(10, 3)

res1 = (X[0] - mu[0]) @ S[0] @ (X[0] - mu[0]).T, (X[0] - mu[1]) @ S[1] @ (X[0] - mu[1]).T

res2 = (np.squeeze((X[0] - mu)[:, None] @ S) * (X[0] - mu)).sum(-1)
print(res1)
print(res2)
英文:

I think you were almost there. You have matrix A = np.squeeze((X[0] - mu)[:, None] @ S) which you matrix multiply with B = ((X[0] - mu)).T) but you only want the diagonal elements.

As pointed out here C = N.diag(A.dot(B)) is equivalent to C = (A * B.T).sum(-1) which leads to the following solution:

import numpy as np

mu = np.array([[1,2,3], [4,5,6]])
S = np.array([np.eye(3)*3, np.eye(3)*5])
X = np.array([np.random.random(3*10)]).reshape(10, 3)

res1 = (X[0] - mu[0]) @ S[0] @ (X[0] - mu[0]).T, (X[0] - mu[1]) @ S[1] @ (X[0] - mu[1]).T

res2 = (np.squeeze((X[0] - mu)[:, None] @ S) * (X[0] - mu)).sum(-1)
print(res1)
print(res2)

答案2

得分: 1

这也可以使用 np.einsum 表达,允许您在 X 上进行广播:

import numpy as np
mu = np.array([[1,2,3], [4,5,6]])
S = np.array([np.eye(3)*3, np.eye(3)*5])
X = np.random.random((10, 3))

resOP = np.array([(X[0] - mu[0]) @ S[0] @ (X[0] - mu[0]).T, (X[0] - mu[1]) @ S[1] @ (X[0] - mu[1]).T])
resNin17 = np.einsum("...ij, ...ij->...i", np.einsum("...j, ...ij", (X[:, None] - mu), S), (X[:, None] - mu))

assert np.allclose(resOP, resNin17[0])

或者只计算一行:

assert np.array_equal(resNin17[2], np.einsum("...ij, ...ij->...i", np.einsum("...j, ...ij", (X[2] - mu), S), (X[2] - mu)))
英文:

This can also be expressed using np.einsum allowing you to broadcast over X as well:

import numpy as np
mu = np.array([[1,2,3], [4,5,6]])
S = np.array([np.eye(3)*3, np.eye(3)*5])
X = np.random.random((10, 3))

resOP = np.array([(X[0] - mu[0]) @ S[0] @ (X[0] - mu[0]).T, (X[0] - mu[1]) @ S[1] @ (X[0] - mu[1]).T])
resNin17 = np.einsum("...ij, ...ij->...i", np.einsum("...j, ...ij", (X[:, None] - mu), S), (X[:, None] - mu))

assert np.allclose(resOP, resNin17[0])

Or to just calculate one row:

assert np.array_equal(resNin17[2], np.einsum("...ij, ...ij->...i", np.einsum("...j, ...ij", (X[2] - mu), S), (X[2] - mu)))

huangapple
  • 本文由 发表于 2023年6月26日 15:56:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/76554646.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定