基于Numpy的矩阵相乘
@author: Heisenberg
主要介绍了矩阵乘法、哈达玛积、克罗内克积的概念及基于numpy的实现。
1. 矩阵乘法
1.1 概念
即线性代数中不满足交换律的矩阵乘法,又称为矩阵内积、点积(dot-product)。 i . e . A B ≠ B A i.e. AB\neq BA i.e.AB=BA。一般记为 A ⋅ B A\cdot B A⋅B。
A ( m × n ) ⋅ B ( n × k ) = C ( m × k ) A_{(m\times n)}\cdot B_{(n\times k)}=C_{(m\times k)} A(m×n)⋅B(n×k)=C(m×k)基本算法是 A A A的第一行乘以 B B B的第一列求和作为新矩阵第一个元素 C 11 C_{11} C11, A A A的第一行乘以 B B B的第二列求和作为新矩阵第一个元素 C 12 C_{12} C12,以此类推。
举个栗子:
[
1
0
2
−
1
3
1
]
⋅
[
3
1
2
1
1
0
]
=
[
5
1
4
2
]
\left[\begin{array}{ccc} 1 & 0 & 2 \\ -1 & 3 & 1 \end{array}\right] \cdot\left[\begin{array}{ll} 3 & 1 \\ 2 & 1 \\ 1 & 0 \end{array}\right]=\left[\begin{array}{ll} 5 & 1 \\ 4 & 2 \end{array}\right]
[1−10321]⋅⎣⎡321110⎦⎤=[5412]
1.2 实现方法
1.2.1 @方法
import numpy as np
A = np.array([[1,0,2],[-1,3,1]])
B = np.array([[3,1],[2,1],[1,0]])
A@B
#Out[1]:
#array([[5, 1],
# [4, 2]])
1.2.2 dot方法
A.dot(B) #or np.dot(A,B)
#Out[2]:
#array([[5, 1],
# [4, 2]])
1.2.3 matmul方法
np.matmul(A,B)
#Out[3]:
#array([[5, 1],
# [4, 2]])
1.2.4 dot() vs matmul()
在两个array的维度均为两维的情况下结果相同。
但在3个维度时,结合下例来看:
-
matmul()方法将最后两个维度作为矩阵的两维,相当于有2个 2 × 2 2\times 2 2×2的矩阵,在这个维度上进行对应位置的矩阵乘法,即可以视为
[ [ 2 × 3 ] [ 2 × 3 ] ] ⋅ [ [ 3 × 2 ] [ 3 × 2 ] ] = [ [ 2 × 3 ] ⋅ [ 3 × 2 ] [ 2 × 3 ] ⋅ [ 3 × 2 ] ] = [ [ 2 × 2 ] [ 2 × 2 ] ] \left[\begin{array}{c}[2\times 3] \\ [2\times 3] \end{array}\right]\cdot\left[\begin{array}{c}[3\times 2] \\ [3\times 2] \end{array}\right] = \left[\begin{array}{c}[2\times 3]\cdot [3\times 2] \\ [2\times 3]\cdot [3\times 2] \end{array}\right]=\left[\begin{array}{c}[2\times 2] \\ [2\times 2] \end{array}\right] [[2×3][2×3]]⋅[[3×2][3×2]]=[[2×3]⋅[3×2][2×3]⋅[3×2]]=[[2×2][2×2]]np.matmul中,多维的矩阵,将前n-2维视为后2维的元素后,进行乘法运算;且禁止矩阵与标量的乘法。
-
dot()方法将 A A A的最后一个维度作为向量,并将 B B B的倒数第二维看作另一个向量,因此 A A A可以看成有 2 × 2 2\times2 2×2个向量, B B B中有 2 × 2 2\times2 2×2个向量,dot会将 A A A的向量与 B B B的向量全部组合在一起,因此会有种 ( 2 × 2 ) × ( 2 × 2 ) (2\times2)\times(2\times2) (2×2)×(2×2)个结果,即可以视为
[ [ 1 × 3 ] [ 1 × 3 ] [ 1 × 3 ] [ 1 × 3 ] ] ⋅ [ [ 3 × 1 ] [ 3 × 1 ] [ 3 × 1 ] [ 3 × 1 ] ] = [ 1 × 3 ] ⋅ [ [ 3 × 1 ] [ 3 × 1 ] [ 3 × 1 ] [ 3 × 1 ] ] + [ 1 × 3 ] ⋅ [ [ 3 × 1 ] [ 3 × 1 ] [ 3 × 1 ] [ 3 × 1 ] ] + [ 1 × 3 ] ⋅ [ [ 3 × 1 ] [ 3 × 1 ] [ 3 × 1 ] [ 3 × 1 ] ] + [ 1 × 3 ] ⋅ [ [ 3 × 1 ] [ 3 × 1 ] [ 3 × 1 ] [ 3 × 1 ] ] = [ [ 2 × 2 ] [ 2 × 2 ] [ 2 × 2 ] [ 2 × 2 ] ] \left[\begin{array}{llll}[1\times 3] \\ [1\times 3] \\ [1\times 3] \\ [1\times 3] \end{array}\right]\cdot\left[\begin{array}{cc}[3\times 1]&[3\times 1] \\ [3\times 1]&[3\times 1] \end{array}\right] \\= [1\times 3]\cdot\left[\begin{array}{cc}[3\times 1]&[3\times 1] \\ [3\times 1]&[3\times 1] \end{array}\right]+[1\times 3]\cdot\left[\begin{array}{cc}[3\times 1]&[3\times 1] \\ [3\times 1]&[3\times 1] \end{array}\right]+[1\times 3]\cdot\left[\begin{array}{cc}[3\times 1]&[3\times 1] \\ [3\times 1]&[3\times 1] \end{array}\right]+[1\times 3]\cdot\left[\begin{array}{cc}[3\times 1]&[3\times 1] \\ [3\times 1]&[3\times 1] \end{array}\right]\\ =\left[\begin{array}{c}[2\times 2] \\ [2\times 2]\\ [2\times 2]\\ [2\times 2] \end{array}\right] ⎣⎢⎢⎡[1×3][1×3][1×3][1×3]⎦⎥⎥⎤⋅[[3×1][3×1][3×1][3×1]]=[1×3]⋅[[3×1][3×1][3×1][3×1]]+[1×3]⋅[[3×1][3×1][3×1][3×1]]+[1×3]⋅[[3×1][3×1][3×1][3×1]]+[1×3]⋅[[3×1][3×1][3×1][3×1]]=⎣⎢⎢⎡[2×2][2×2][2×2][2×2]⎦⎥⎥⎤
>>>A = np.array([i for i in range(12)]).reshape([2,2,3])
>>>B = np.array([i for i in range(12)]).reshape([2,3,2])
"""
A
[[[ 0 1 2]
[ 3 4 5]]
[[ 6 7 8]
[ 9 10 11]]]
B
[[[ 0 1]
[ 2 3]
[ 4 5]]
[[ 6 7]
[ 8 9]
[10 11]]]
"""
>>>np.matmul(A,B)
"""
array([[[ 10, 13],
[ 28, 40]],
[[172, 193],
[244, 274]]])
"""
>>>np.dot(A,B)
'''
array([[[[ 10, 13],
[ 28, 31]],
[[ 28, 40],
[100, 112]]],
[[[ 46, 67],
[172, 193]],
[[ 64, 94],
[244, 274]]]])
'''
2. 哈达玛积(按位相乘)
2.1 概念
哈达马积,将矩阵中相同位置的元素相乘,又称element-wise product。一般记为 A ∗ B A*B A∗B。
举个栗子:
(
1
3
2
1
0
0
1
2
2
)
∗
(
0
0
2
7
5
0
2
1
1
)
=
(
1
⋅
0
3
⋅
0
2
⋅
2
1
⋅
7
0
⋅
5
0
⋅
0
1
⋅
2
2
⋅
1
2
⋅
1
)
=
(
0
0
4
7
0
0
2
2
2
)
\left(\begin{array}{lll} 1 & 3 & 2 \\ 1 & 0 & 0 \\ 1 & 2 & 2 \end{array}\right) *\left(\begin{array}{lll} 0 & 0 & 2 \\ 7 & 5 & 0 \\ 2 & 1 & 1 \end{array}\right)=\left(\begin{array}{lll} 1 \cdot 0 & 3 \cdot 0 & 2 \cdot 2 \\ 1 \cdot 7 & 0 \cdot 5 & 0 \cdot 0 \\ 1 \cdot 2 & 2 \cdot 1 & 2 \cdot 1 \end{array}\right)=\left(\begin{array}{lll} 0 & 0 & 4 \\ 7 & 0 & 0 \\ 2 & 2 & 2 \end{array}\right)
⎝⎛111302202⎠⎞∗⎝⎛072051201⎠⎞=⎝⎛1⋅01⋅71⋅23⋅00⋅52⋅12⋅20⋅02⋅1⎠⎞=⎝⎛072002402⎠⎞
2.2 实现方法
2.2.1 *方法
A = np.array([[1,2],[3,4]])
B = np.array([[5,6],[7,8]])
A*B
#array([[ 5, 12],
# [21, 32]])
2.2.2 multiply()方法
np.multiply(A,B)
#array([[ 5, 12],
# [21, 32]])
3. 克罗内克积
3.1 概念
克罗内克积也被称为直积或张量积,适用于任意矩阵大小,一般记作 A ⊗ B A\otimes B A⊗B。
举个栗子:
(
1
2
3
1
)
⊗
(
0
3
2
1
)
=
(
1
⋅
0
1
⋅
3
2
⋅
0
2
⋅
3
1
⋅
2
1
⋅
1
2
⋅
2
2
⋅
1
3
⋅
0
3
⋅
3
1
⋅
0
1
⋅
3
3
⋅
2
3
⋅
1
1
⋅
2
1
⋅
1
)
=
(
0
3
0
6
2
1
4
2
0
9
0
3
6
3
2
1
)
\left(\begin{array}{ll} 1 & 2 \\ 3 & 1 \end{array}\right) \otimes\left(\begin{array}{ll} 0 & 3 \\ 2 & 1 \end{array}\right)=\left(\begin{array}{llll} 1 \cdot 0 & 1 \cdot 3 & 2 \cdot 0 & 2 \cdot 3 \\ 1 \cdot 2 & 1 \cdot 1 & 2 \cdot 2 & 2 \cdot 1 \\ 3 \cdot 0 & 3 \cdot 3 & 1 \cdot 0 & 1 \cdot 3 \\ 3 \cdot 2 & 3 \cdot 1 & 1 \cdot 2 & 1 \cdot 1 \end{array}\right)=\left(\begin{array}{llll} 0 & 3 & 0 & 6 \\ 2 & 1 & 4 & 2 \\ 0 & 9 & 0 & 3 \\ 6 & 3 & 2 & 1 \end{array}\right)
(1321)⊗(0231)=⎝⎜⎜⎛1⋅01⋅23⋅03⋅21⋅31⋅13⋅33⋅12⋅02⋅21⋅01⋅22⋅32⋅11⋅31⋅1⎠⎟⎟⎞=⎝⎜⎜⎛0206319304026231⎠⎟⎟⎞
3.2 np.kron()方法
A = np.array([[1,2],[3,4]])
B = np.array([[5,6],[7,8]])
np.kron(A,B)
#array([[ 5, 6, 10, 12],
# [ 7, 8, 14, 16],
# [15, 18, 20, 24],
# [21, 24, 28, 32]])