Numpy中矩陣縮並

張量縮並

在數學和物理領域,經常會用到更高階的數組,一般可以稱為張量。通常的矩陣 可以看成二階張量。張量和張量之間存在著多種運算方法,其中張量縮並是一種常 見的運算,對應於二維矩陣即矩陣的乘法。

C_{ik}=sum_{j}A_{ij}B_{jk}

這裡還有另外一種說法叫做愛因斯坦求和規則。大致的意思是兩個張量角標相同的維度 進行求和。例如:

C_{jlmrst}=A_{ijklmn}B_{iknrst}

在這樣的約定下,可以省去求和符號,顯得更加簡潔。注意對應求和維度的大小應該是一樣的。

numpy中的函數

在numpy中,提供了兩個進行張量縮並的函數:

  1. einsum
  2. tensordot

這兩個函數中,einsum的寫法非常接近愛因斯坦求和規則,但是效率較低,而tensordot相應相率很高,下面逐個進行介紹。

einsum

首先看一下官方文檔的內容:

numpy.einsum(subscripts, *operands, out=None, dtype=None, order=K, casting=safe, optimize=False)

Evaluates the Einstein summation convention on the operands. Using the Einstein summation convention, many common multi-dimensional array operations can be represented in a simple fashion. This function provides a way to compute such summations. The best way to understand this function is to try the examples below, which show how many common NumPy functions can be implemented as calls to einsum.

通常在使用時,我們只需關注前兩個參數,其它需要的時候可以參考連接:

numpy.einsum - NumPy v1.15 Manual?

docs.scipy.org

假設有兩個張量 A_{ijk}B_{ijm} ,對應的形狀分別為 a_1	imes a_2	imes a_3a_1	imes a_2	imes b_3 根據愛因斯坦求和規則: C_{km}=sum_{ij}A_{ijk}B_{ijm} ,這裡 C 矩陣的形狀為 a_3	imes b_3 。那麼利用einsum就可以寫成如下形式。

einsum("ijk,ijm->km",A,B)

第一個參數是用字元串表示求和規則,緊接著是參與運算的矩陣。當然也可以將運算結果 C 矩陣存儲為 C_{mk} ,只需把函數改為:

einsum("ijk,ijm->mk",A,B)

tensordot

tensordot同樣可以實現上述功能,並且運算效率更高,詳細參數請參考:

numpy.tensordot - NumPy v1.15 Manual?

docs.scipy.org

這裡仍然以 C_{km}=sum_{ij}A_{ijk}B_{ijm} 為例說明。

tensordot(A,B,axes=[(0,1),(0,1)]

函數的前兩個參數即為參與運算的張量,第三項axes輸入一個包含兩個元組的列表。第一個元組中包含矩陣 A 中需要收縮的角標,第二個元組為相應 B 矩陣中的角標。上面的意思就是 A 的第0和第1個角標分別和 B 的第0和第1個角標收縮。

tensordot的axes還可以取整數值,其中0,1,2的含義分別為:

  • axes = 0 : tensor product
  • axes = 1 : tensor dot product
  • axes = 2 : (default) tensor double contraction

推薦閱讀:

TAG:Python | numpy | 數值計算 |