简体   繁体   English

使用 numpy 对多个向量进行对角化

[英]diagonalize multiple vectors using numpy

Say I have a matrix of shape (2,3), I need to diagonalize the 3-elements vector into matrix of shape (3,3), for all the 2 vectors at once.假设我有一个形状为 (2,3) 的矩阵,我需要一次将所有 2 个向量的 3 元素向量对角化为形状 (3,3) 的矩阵。 That is, I need to return matrix with shape (2,3,3).也就是说,我需要返回形状为 (2,3,3) 的矩阵。 How can I do that with Numpy elegantly?如何优雅地使用 Numpy 做到这一点?

given data = np.array([[1,2,3],[4,5,6]])

i want the result [[[1,0,0],
                    [0,2,0],
                    [0,0,3]],
                    
                   [[4,0,0],
                    [0,5,0],
                    [0,0,6]]]
             

Thanks谢谢

tl;dr, my one-liner: mydiag=np.vectorize(np.diag, signature='(n)->(n,n)') tl;博士,我的单行: mydiag=np.vectorize(np.diag, signature='(n)->(n,n)')

I suppose here that by "diagonalize" you mean "applying np.diag".我想这里的“对角化”是指“应用 np.diag”。 Which, as a teacher of linear algebra, tickles me a bit.作为线性代数的老师,这让我有点发痒。 Since "diagonalizing" has a specific meaning, which is not that (it is computing eigen vectors and values, and from there, writing M=P⁻¹ΛP. Which you cannot do from the inputs you have).由于“对角化”具有特定含义,但并非如此(它正在计算特征向量和值,并从那里写入 M=P⁻¹ΛP。您无法从您拥有的输入中做到这一点)。

So, I suppose that if input matrix is所以,我想如果输入矩阵是

[[1, 2, 3],
 [9, 8, 7]]

The output matrix you want is您想要的 output 矩阵是

[[[1, 0, 0],
  [0, 2, 0],
  [0, 0, 3]],
 [[9, 0, 0],
  [0, 8, 0],
  [0, 0, 7]]]

If not, you can ignore this answer [Edit: in the meantime, you explained exactly that.如果没有,您可以忽略此答案 [编辑:与此同时,您对此进行了准确的解释。 So yo may continue to read].所以你可以继续阅读]。

There are many way to do that.有很多方法可以做到这一点。 My one liner would be我的一个班轮将是

mydiag=np.vectorize(np.diag, signature='(n)->(n,n)')

Which build a new functions which does what you want (it interprets the input as a list of 1D-array, call np.diag of each of them, to get a 2D-array, and put each 2D-array in a numpy array, thus getting a 3D-array)它构建了一个可以执行您想要的新功能(它将输入解释为一维数组的列表,调用每个数组的 np.diag 以获取二维数组,并将每个二维数组放入 numpy 数组中,从而得到一个3D阵列)

Then, you just call mydiag(M)然后,您只需调用mydiag(M)

One advantage of vectorize, is that it uses numpy broadcasting.矢量化的优点之一是它使用 numpy 广播。 In other words, the loops are executed in C, not in python.换句话说,循环在 C 中执行,而不是在 python 中执行。 In yet other words, it is faster.换句话说,它更快。 Well it is supposed to be (on small matrix, it is in fact slower than Michael's method - in comment; on large matrix, it is has the exact same speed. Which is frustrating, since einsum doc itself specify that it sacrifices broadcasting).好吧,它应该是(在小矩阵上,它实际上比迈克尔的方法慢 - 在评论中;在大矩阵上,它具有完全相同的速度。这令人沮丧,因为 einsum doc 本身指定它牺牲了广播)。

Plus, it is a one-liner, which has no other interest than bragging on forums.另外,它是单线的,除了在论坛上吹牛之外没有其他兴趣。 But well, here we are.但是,我们到了。

Here is one way with indexing:这是索引的一种方法:

out = np.zeros(data.shape+(data.shape[-1],), dtype=data.dtype)

x,y = np.indices(data.shape).reshape(2, -1)
out[x,y,y] = data.ravel()

output: output:

array([[[1, 0, 0],
        [0, 2, 0],
        [0, 0, 3]],

       [[4, 0, 0],
        [0, 5, 0],
        [0, 0, 6]]])

We use array indexing to precisely grab those elements that are on the diagonal.我们使用数组索引来精确抓取对角线上的那些元素。 Note that array indexing allows broadcasting between the indices, so we have index1 contain the index of the array, and index2 contain the index of the diagonal element.请注意,数组索引允许在索引之间广播,因此我们让 index1 包含数组的索引,而 index2 包含对角元素的索引。

index1 = np.arange(2)[:, None] # 2 is the number of arrays
index2 = np.arange(3)[None, :] # 3 is the square size of each matrix

result = np.zeros((2, 3, 3))
result[index1, index2, index2] = data

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM