3D numpy数组A
包含一系列D
形状的2D numpy数组2 x 2
(在此示例中,我选择3)。 D
矩阵如下:
D = np.array([[1,2],[3,4]])
A
的初始化和分配如下:
idx = np.arange(3)
A = np.zeros((3,2,2))
A[idx,:,:] = D # This gives A = [[[1,2],[3,4]],[[1,2],[3,4]],\
# [[1,2],[3,4]]]
# In mathematical notation: A = {D, D, D}
现在,执行代码后基本上需要的是:
从数学上讲,A = {D^0, D^1, D^2} = {D0, D1, D2}
其中D0 = [[1,0],[0,1]]
,D1 = [[1,2],[3,4]]
,D2=[[7,10],[15,22]]
是否可以在不使用for循环的情况下为A
中的每个矩阵元素加电?我将在更大的矩阵中处理更多的序列。
我已经定义了n = np.array([0,1,2])
#对应于0、1和2的幂并尝试了
Result = np.power(A,n)
,但没有得到所需的输出。
是否有一种有效的方法?
完整代码:
D = np.array([[1,2],[3,4]])
idx = np.arange(3)
A = np.zeros((3,2,2))
A[idx,:,:] = D # This gives A = [[[1,2],[3,4]],[[1,2],[3,4]],\
# [[1,2],[3,4]]]
# In mathematical notation: A = {D, D, D}
n = np.array([0,1,2])
Result = np.power(A,n) # ------> Not the desired output.
答案 0 :(得分:3)
一个累积乘积以numpy存在,但不适用于矩阵。因此,您需要创建自己的“ matcumprod”功能。您可以为此使用np.dot,但是np.matmul(或@
)专用于矩阵乘法。
由于您声明自己的功率始终从0变为some_power,因此建议使用以下函数:
def matcumprod(D, upto):
Res = np.empty((upto, *D.shape), dtype=A.dtype)
Res[0, :, :] = np.eye(D.shape[0])
Res[1, :, :] = D.copy()
for i in range(1,upto):
Res[i, :, :] = Res[i-1,:,:] @ D
return Res
顺便说一句,如果内置的numpy函数占用大量内存,则循环通常会比内置的numpy函数性能好,因此,如果您的能力不在限制之内,请不要担心...
答案 1 :(得分:2)
好的,我在这个问题上花了很多时间,但是似乎找不到您想要的矢量化解决方案。因此,我想先提出一个基本的解决方案,然后在需要连续功率的情况下进行优化。
您要查找的函数称为numpy.linalg.matrix_power
import numpy as np
D = np.matrix([[1,2],[3,4]])
idx = np.arange(3)
A = np.zeros((3,2,2))
A[idx,:,:] = D # This gives A = [[[1,2],[3,4]],[[1,2],[3,4]],\
# [[1,2],[3,4]]]
# In mathematical notation: A = {D, D, D}
np.zeros(A.shape)
n = np.array([0,1,2])
result = [np.linalg.matrix_power(D, i) for i in n]
np.array(result)
#Output:
array([[[ 1, 0],
[ 0, 1]],
[[ 1, 2],
[ 3, 4]],
[[ 7, 10],
[15, 22]]])
但是,如果您注意到,最终将为同一基本矩阵计算多个功效。我们可以改用中间结果,然后使用numpy.linalg.multi_dot
def all_powers_arr_of_matrix(A):
result = np.zeros(A.shape)
result[0] = np.linalg.matrix_power(A[0], 0)
for i in range(1, A.shape[0]):
result[i] = np.linalg.multi_dot([result[i - 1], A[i]])
return result
result = all_powers_arr_of_matrix(A)
#Output:
array([[[ 1., 0.],
[ 0., 1.]],
[[ 1., 2.],
[ 3., 4.]],
[[ 7., 10.],
[15., 22.]]])
此外,我们可以避免完全创建矩阵A,从而节省一些时间。
def all_powers_matrix(D, *rangeargs): #end exclusive
''' Expects 2D matrix.
Use as all_powers_matrix(D, end) or
all_powers_matrix(D, start, end)
'''
if len(rangeargs) == 1:
start = 0
end = rangeargs[0]
elif len(rangeargs) == 2:
start = rangeargs[0]
end = rangeargs[1]
else:
print("incorrect args")
return None
result = np.zeros((end - start, *D.shape))
result[0] = np.linalg.matrix_power(A[0], start)
for i in range(start + 1, end):
result[i] = np.linalg.multi_dot([result[i - 1], D])
return result
return result
result = all_powers_matrix(D, 3)
#Output:
array([[[ 1., 0.],
[ 0., 1.]],
[[ 1., 2.],
[ 3., 4.]],
[[ 7., 10.],
[15., 22.]]])
请注意,如果您决定按原样使用这些功能,则需要添加错误处理。
答案 2 :(得分:0)
我没有完整的解决方案,但是有些事情我想提一下,这些评论太长了。
如果您要计算大型矩阵的强大功率,则可能首先要研究addition chain exponentiation。这基本上是在询问给定A^k
的计算k
需要多少个矩阵乘法。例如A^5 = A(A^2)^2
,因此您只需要三个矩阵乘法:A^2
和(A^2)^2
和A(A^2)^2
。这可能是提高效率的最简单方法,但是您可能仍然必须使用显式循环。
您的问题还与针对给定的Ax, A^2x, ... , A^kx
和A
计算x
的问题有关。这是当前研究的一个活跃领域(搜索“矩阵幂核”),因为有效地计算此类序列对于避免Krylov子空间方法的并行/通信很有用。如果您正在寻找一种非常有效的解决方案,那么值得研究一下相关结果。
答案 3 :(得分:0)
要计算矩阵A
的幂,一种方法可能是使用np.linalg.eig
查找矩阵的特征值和右特征向量,然后提高对角矩阵的幂,因为它更容易,然后经过操作,您可以使用两个np.einsum
来计算#get eigvalues and eigvectors
eigval, eigvect = np.linalg.eig(D)
# to check how it works, you can do:
print (np.dot(eigvect*eigval,np.linalg.inv(eigvect)))
#[[1. 2.]
# [3. 4.]]
# so you get back on D
#use power as ufunc of outer with n on the eigenvalues to get all the one you want
arrp = np.power.outer( eigval, n).T
#apply_along_axis to create the diagonal matrix along the last axis
diagp = np.apply_along_axis( np.diag, axis=-1, arr=arrp)
#finally use two np.einsum to calculate with the subscript to get what you want
A = np.einsum('lij,jk -> lik',
np.einsum('ij,kjl -> kil',eigvect,diagp), np.linalg.inv(eigvect)).round()
print (A)
print (A.shape)
#[[[ 1. 0.]
# [-0. 1.]]
#
# [[ 1. 2.]
# [ 3. 4.]]
#
# [[ 7. 10.]
# [15. 22.]]]
#
#(3, 2, 2)
A connection to myapicall was leaked. Did you forget to close a response body?