简体   繁体   English

如何在 numpy 中有效地将 3D 矩阵与二维矩阵相乘

[英]How to multiply a 3D matrix with a 2D matrix efficiently in numpy

I have two multidimensional arrays, which I want to multiply with each other.我有两个多维 arrays,我想将它们相乘。 One has the shape N,N,3 and the other has the shape N,N.一个形状为 N,N,3,另一个形状为 N,N。

Let me set the stage:让我设置舞台:

I have an array of atom positions of the shape N,3 :我有一个形状为N,3的原子位置数组:

atom_positions = [[x1,y1,z1],
                  [x2,y2,z2],
                  [x3,y3,z3],
                  ...       
                            ]

From these I calculate an upper triangular matrix of distance vectors so that the resulting N,N,3 matrix contains all unique pair distance vectors r_ij of the vectors inside atom_positions :从这些我计算距离向量的上三角矩阵,以便生成的 N,N,3 矩阵包含atom_positions r_ij

pair_distance_vectors = [[[0,0,0],[x2-x1,y2-y1,z2-z1],[x3-x1,y3-y1,z3-z1],...],
                         [[0,0,0],[0,0,0]            ,[x3-x2,y3-y2,z3-z2],...],
                          ...
                                                                              ]

Now I want to normalize each of these pair distance vectors.现在我想对这些对距离向量中的每一个进行归一化。 For that I want to use my N,N pair_distances array, which contains the length of every vector inside pair_distance_vectors .为此,我想使用我的 N,N pair_distances数组,其中包含pair_distance_vectors中每个向量的长度。 The formula for a single vector is: r_ij/|r_ij|单个向量的公式为:r_ij/|r_ij|

I want to do that by doing a matrix multiplication, where every entry in the N,N array becomes a scalar by which a vector inside the N,N,3 array is multiplied.我想通过进行矩阵乘法来做到这一点,其中 N,N 数组中的每个条目都变成一个标量,N,N,3 数组中的向量乘以该标量。 I'm pretty sure that this can be achieved somehow with numpy by using numpy.dot() or a different function, but I just can't find the answer myself.我很确定这可以通过使用numpy.dot()或不同的 function 以某种方式通过 numpy 实现,但我自己找不到答案。 Also, I'm afraid if I do find a transformation which allows for this, that my maths will be faulty.另外,我担心如果我确实找到了允许这样做的转换,我的数学就会出错。

Here's some demonstration code, which achieves what I want in a very inefficient fashion:这是一些演示代码,它以非常低效的方式实现了我想要的:

import numpy as np

pair_distance_vectors = np.ones(shape=(2,2,3))
pair_distances = np.array(((1,2),(3,4)))
normalized_pair_distance_vectors  = np.zeros(shape=(2,2,3))

for i,vec_list in enumerate(pair_distance_vectors):
    for j,vec in enumerate(vec_list):
        normalized_pair_distance_vectors[i,j] = vec*pair_distances[i,j]

print(normalized_pair_distance_vectors)

Thanks in advance.提前致谢。

EDIT: Maybe this is clearer:编辑:也许这更清楚:

distance_vectors = [[[x11,y11,z11],[x12,y12,z12],[x13,y13,z13],...],
                    [[x21,y21,z21],[x22,y22,z22],[x23,y23,z23],...],
                    ...                                            ]

distance_matrix = [[r_11,r_12,r_13,...],
                   [r_21,r_22,r_23,...],
                    ...                 ]

norm_distance_vectors = some_operation(distance_vectors,distance_matrix)

norm_distance_vectors = [[r_11*[x11,y11,z11],r_12*[x12,y12,z12],r_13*[x13,y13,z13],...],
                         [r_21*[x21,y21,z21],r_22*[x22,y22,z22],r_23*[x23,y23,z23],...],
                          ...                                                    ]

You won't need a loop.你不需要循环。 Trick is to expand your pair_distance in the 3rd dimension by repeating it m times ( m being the dimension of your vectors, here 3D) and then divide two arrays element wise (works for any m -dimensional vectors, replace 3 with m ):诀窍是通过重复m次来扩展您的pair_distance在第三维( m是向量的维度,这里是 3D),然后将两个 arrays 元素分开(适用于任何m维向量,将 3 替换为m ):

pair_distances = np.repeat(pair_distances[:,:,None], 3, axis=2)
normalized_pair_distance_vectors = np.nan_to_num(pair_distance_vectors/ pair_distances)

Output for your example inputs: Output 用于您的示例输入:

[[[1.         1.         1.        ]
  [0.5        0.5        0.5       ]]

 [[0.33333333 0.33333333 0.33333333]
  [0.25       0.25       0.25      ]]]

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

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