日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

python中使用numpy包的向量矩陣相乘np.dot和np.matmul實現_python

作者:ViviranZ ? 更新時間: 2023-05-10 編程語言

一直對np的線性運算不太清晰,正好上課講到了,做一個筆記整個理解一下?

1.向量和矩陣

在numpy中,一重方括號表示的是向量vector,vector沒有行列的概念。二重方括號表示矩陣matrix,有行列。

代碼顯示如下:

import numpy as np
a=np.array([1,2,3])
a.shape
#(3,)
b=np.array([[1,2,3],[3,4,5]])
b.shape
#(2, 3)
c=np.array([[1],[2],[3]])
c.shape
#(3, 1)

即使[1,2,3]、[[1,2,3]]看起來內容一樣 使用過程中也會有完全不一樣的變化。下面以向量乘法為例解釋。

2.向量和向量乘法

1.* 對應對應位置相乘

普通的*:在numpy里表示普通的對應位置相乘,注意相乘的兩個向量、矩陣要保證維數相同

a1=np.array([1,2,3])
a2=np.array([1,2,3])
a1*a2
#array([1, 4, 9])
 
b1=np.array([[1,2,3]])
b2=np.array([[1,2,3]])
b1*b2
#array([[1, 4, 9]])
 
b1=np.array([[1,2,3],[3,4,5]])
b2=np.array([[1,2,3],[3,4,5]])
b1*b2
# array([[ 1,  4,  9],
#        [ 9, 16, 25]])

2.廣播機制

如果單純出現維數對不上,python會報error

b1=np.array([[1,2]])
b2=np.array([[1,2,3]])
b1*b2
#operands could not be broadcast together with shapes (1,2) (1,3) 

但是,還有一種情況會出現乘出來一個好大的矩陣,這個情況常出現在無意之中把行、列的數字搞反的情況下。被稱為廣播機制,需要兩個乘子都有一個維數是1,如果是對不上且不為1就會報錯

Numpy中的廣播機制,你確定正確理解了嗎?

在普通的對應位置相乘,會出現?

a1=np.array([1,2,3])
a3=np.array([[1],[2],[3]])
a1*a3#broadcast together
# array([[1, 2, 3],
#        [2, 4, 6],
#        [3, 6, 9]])

倒過來也會出現

a1=np.array([1,2,3])
a3=np.array([[1],[2],[3]])
a3*a1#broadcast together
# array([[1, 2, 3],
#        [2, 4, 6],
#        [3, 6, 9]])

3.向量點乘np.dot

必須要(行向量,列向量)形式的輸入

a1=np.array([1,2,3])
a3=np.array([[1],[2],[3]])
np.dot(a3,a1)
#array([14])
#ValueError: shapes (3,1) and (3,) not aligned: 1 (dim 1) != 3 (dim 0)

?都是行向量,不行

b1=np.array([[1,2,3]])
b2=np.array([[1,2,3]])
np.dot(b1,b2) 
#shapes (1,3) and (1,3) not aligned: 3 (dim 1) != 1 (dim 0)

都是列向量,觸發廣播機制

a1=np.array([[1,2,3]])
a3=np.array([[1],[2],[3]])
np.dot(a3,a1)
# array([[1, 2, 3],
#        [2, 4, 6],
#        [3, 6, 9]])

3.矩陣和向量乘法

1.對應位置相乘

如果單純采用*的方式進行矩陣和向量乘法,那就是廣播機制

矩陣+向量

A1=np.array([[1,2,3],[2,3,4]])
b1=np.array([1,2,3])
A1*b1 #broadcast together
# array([[ 1,  4,  9],
#        [ 2,  6, 12]])

?對應的向量如果是矩陣形式,結果相同

A2=np.array([[1,2,3],[2,3,4]])
b2=np.array([[1,2,3]])
A2*b2 #broadcast together
# array([[ 1,  4,  9],
#        [ 2,  6, 12]])

相似的,如果維數對不上,不會觸發廣播機制

A3=np.array([[1,2,3],[2,3,4]])
b3=np.array([[1],[2],[3]])
A3*b3 #operands could not be broadcast together with shapes (2,3) (3,1) 

2.矩陣乘法

如果真正想要算矩陣*向量的矩陣乘法,要用np.dot

A4=np.array([[1,2,3],[2,3,4]])
b4=np.array([1,2,3])
np.dot(A4,b4)#dot product
#array([14, 20])

列向量也有類似結果

A4=np.array([[1,2,3],[2,3,4]])
b4=np.array([[1],[2],[3]])
np.dot(A4,b4)#dot product
# array([[14],
#        [20]])

4.矩陣矩陣乘法?

1.直接相乘

同樣,也是對應位置相乘

A4=np.array([[1,2,3],[2,3,4]])
B4=np.array([[1,2,3],[4,5,6]])
A4*B4
# array([[ 1,  4,  9],
#        [ 8, 15, 24]])

?有廣播機制

A4=np.array([[1,2,3],[2,3,4]])
B4=np.array([[1,2,3]])
A4*B4
# array([[ 1,  4,  9],
#        [ 2,  6, 12]])

2.np.dot

需要第一個的列數和第二個的行數相對應

A4=np.array([[1,2,3],[2,3,4]])
B4=np.array([[1,2,3],[4,5,6]])
np.dot(A4,B4.T)
# array([[14, 32],
#        [20, 47]])
 
A5=np.array([[1,2,3],[2,3,4]])
B5=np.array([[1,2,3],[4,5,6],[7,8,9]])
np.dot(A5,B5)
# array([[30, 36, 42],
#        [42, 51, 60]])

對不上會報錯

A4=np.array([[1,2,3],[2,3,4]])
B4=np.array([[1,2,3],[4,5,6]])
np.dot(A4,B4)
# shapes (2,3) and (2,3) not aligned: 3 (dim 1) != 2 (dim 0)

5.np.dot 和np.matmul的區別

Numpy中np.dot與np.matmul的區別

主要參考以上博客。

1.在二維(矩陣中),二者是一致的

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.dot很清晰,就是a的每一行分別和b的兩層乘起來,于是2*2輸出了四個“矩陣”(表示成4維的常數):

 
"""
a11= [ 0  1  2]
a12= [ 3  4  5]
a21= [ 6  7  8]
a22= [ 9 10 11]
b
[[[ 0  1]
  [ 2  3]
  [ 4  5]]
 [[ 6  7]
  [ 8  9]
  [10 11]]]
c[:,i,j]=aij*b
"""

如:

[ 10, ?13]?=[0 1 2]*[[ 0 ?1]
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? [ 2 ?3]
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? [ 4 ?5]]
? [ 28, ?31]=[0 1 2]*[[ 6 ?7]
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? [ 8? 9]
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? [ 10? 11]]

>>> np.dot(a,b)
array([[[[ 10,  13],
         [ 28,  31]],
 
        [[ 28,  40],
         [100, 112]]],
 
 
       [[[ 46,  67],
         [172, 193]],
 
        [[ 64,  94],
         [244, 274]]]])
>>> np.dot(a,b).shape
(2, 2, 2, 2)

np.matmul的結果:

>>> np.matmul(a,b)
array([[[ 10,  13],
        [ 28,  40]],
 
       [[172, 193],
        [244, 274]]])
>>> np.matmul(a,b).shape
(2, 2, 2)

可以看出,如果把np.dot視為8行、matmul視為4行的話,matmul正好取第1、3、6、8四行,也就是第一層的前兩行和第二層的后兩行……

直觀理解,ok

原文鏈接:https://blog.csdn.net/weixin_55703970/article/details/129006976

欄目分類
最近更新