將Numpy中的大量矩陣運算矢量化的最快方法是什么?

更新時間:2024-04-02 13:09:48

問題闡述

假設我要在Numpy中做大量的矩陣乘法;最快的方法是什么?

具體來說,假設問題是這樣的:我有兩個很長的矩陣列表,我想要將它們逐個相乘。也就是說,我有

[a_1, a_2, a_3, ..., a_N]

[b_1, b_2, b_3, ..., b_N],
其中每個a_ib_i是一個nxn矩陣(n是小的,比如n=2),而N是大的(比如N = 100000),我想找出矩陣乘積a_1 * b_1, a_2 * b_2, ...

使用Python和Numpy/Scipy執行此操作的最快方法是什么?

部分選項包括:

  1. 使用for循環--這很慢,因為Python循環很慢。
  2. 將較小的矩陣放入兩個NxN塊對角線矩陣AB--這將導致必須將一個比所需大得多的矩陣相乘。
  3. 使用vectorize--這是最容易編碼的,但并不比for循環快。

精準答案

您已經可以將3D數組相乘,只需將數組列表放入NumPy數組即可,例如

A = np.array([a_1, a_2, ..., a_N])
B = np.array([b_1, b_2, ..., b_N])

然后乘以A @ B(@是矩陣乘法運算符)。以下是使用兩個3x3數組列表的示例:

In [1]: import numpy as np

In [2]: x = np.random.randint(0, 9, (2, 3, 3))

In [3]: y = np.random.randint(0, 9, (2, 3, 3))

In [4]: x
Out[4]:
array([[[0, 4, 8],
        [2, 5, 5],
        [3, 0, 5]],

       [[7, 6, 1],
        [7, 0, 7],
        [5, 2, 8]]])

In [5]: y
Out[5]:
array([[[7, 2, 6],
        [6, 1, 4],
        [6, 8, 5]],

       [[8, 5, 4],
        [8, 2, 7],
        [3, 7, 0]]])

In [7]: x @ y
Out[7]:
array([[[ 72,  68,  56],
        [ 74,  49,  57],
        [ 51,  46,  43]],

       [[107,  54,  70],
        [ 77,  84,  28],
        [ 80,  85,  34]]])

要證明所有這些都是每個矩陣在相應索引處的乘積:

In [8]: x[0]
Out[8]:
array([[0, 4, 8],
       [2, 5, 5],
       [3, 0, 5]])

In [9]: y[0]
Out[9]:
array([[7, 2, 6],
       [6, 1, 4],
       [6, 8, 5]])

In [10]: x[0] @ y[0]
Out[10]:
array([[72, 68, 56],
       [74, 49, 57],
       [51, 46, 43]])

In [11]: (x @ y)[0]
Out[11]:
array([[72, 68, 56],
       [74, 49, 57],
       [51, 46, 43]])