用 Python+Numpy+scipy 執行 Matlab 的矩陣計算 2 產生 numpy 的 數組, 矩陣點乘 等

46 篇文章 1 订阅
32 篇文章 1 订阅

“Talk is cheap. Show me the code.”
― Linus Torvalds

老子第41章
上德若谷
大白若辱
大方無隅
大器晚成
大音希聲
大象無形
道隱無名

拳打千遍, 身法自然

20200706


本系列文章之連結

  • 用 Python+Numpy+scipy 執行 Matlab 的矩陣計算 1 Python科學計算第三方庫, 原生指令, 內建模組, 外部模組 link

  • 用 Python+Numpy+scipy 執行 Matlab 的矩陣計算 1.1 scipy.linalg 官網完整列表 link

  • 用 Python+Numpy+scipy 執行 Matlab 的矩陣計算 2 產生 numpy 的 數組, 矩陣點乘 等 link

  • 用 Python+Numpy+scipy 執行 Matlab 的矩陣計算 3 向量與矩陣運算 link

  • 用 Python+Numpy+scipy 執行 Matlab 的矩陣計算 4 函數向量化 function vectorized
    link

  • 用 Python+Numpy+scipy 執行 Matlab 的矩陣計算 5 矩陣特徵值等不變量計算 link

  • 用 Python+Numpy+scipy 執行 Matlab 的矩陣計算 5.1 矩陣分解的指令 link

  • 用 Python+Numpy+scipy 執行 Matlab 的矩陣計算 6 解線性方程組 直接法: Gauss 消去, LU 等 link

  • 用 Python+Numpy+scipy 執行 Matlab 的矩陣計算 7 解線性方程組 迭代法: Jacobi iterated,Gauss-Seidel 等 link


文章目录


以下直接以例子講解

以下例子會同步將原生 list 與 numpy 模組 的 np.array() 兩種作比較, 可能讀者剛讀會有點混淆, 只要注意, 有 np. 開頭的就是numpy 模組 的 np.array() , 沒有就是指 原生 list.

Python 的 原生 list(串列 or列表) 是最常用的放資料的容器, 用 [ ] 包住就是

Python 的 原生 list: [a,b,c,d, … \dots ]
>>> [1,2,3,4,5]
[1, 2, 3, 4, 5]
>>> type([1,2,3,4,5])
<class 'list'>
Python 原生最簡單產生數列的方式: range(start, end, stride) ( Matlab: start:stride:end)

range(1,6) 會產生 1,2,3,4,5

>>> range(1,6)
range(1, 6)
>>> type(range(10))
<class 'range'>

他是一個 跌代器 iterator, 為了提高效能, 不會印出來, 要看他的內容, 要用 for loop print 印出來

>>> for i in range(1,6):
	print(i)	
1
2
3
4
5
>>> for i in range(1,6,2):
	print(i)
1
3
5

如果要由大到小 用
令 b>a, range(b,a,-1) 會得到 b,b-1,a+1
例如 range(10,5,-1)

>>> for i in range(10,5,-1):
	print(i)
10
9
8
7
6
NumPy 數組 np.array 最簡單產生 numpy 數列的方式: np.arange(start, end, stride) (Matlab: start:stride:end)

產生 a 到 (b-1) 間格 間格 gap, 之 等分點, 可以用以下指令, 指定間格寬度為 gap
np.arange(a, b, gap)
就是
np.arange(start, end, stride)
arrangearray range 的意思, 是 numpy 的指令, 初學容易跟原生的 range 混淆

>>> np.arange(1,6)
array([1, 2, 3, 4, 5])

>>> np.arange(1,6,2)
array([1, 3, 5])
>>> type(np.arange(1,6))
<class 'numpy.ndarray'>
# 反轉
>>> np.arange(10,5,-1)
array([10,  9,  8,  7,  6])

  • 以下可以等進階時再細看
Python 的 原生 list 做 copy 要小心

Python 的 原生 list 可以放 list在裡面, 可以是較複雜的,
例如 以下, a 串列的元素有純量, 有 list, 也有 dict (字典),

>>> a = [1,2,3,[4,5,6],'abc',{'a':1,'b':2,'c':3}]
>>> a
[1, 2, 3, [4, 5, 6], 'abc', {'a': 1, 'b': 2, 'c': 3}]

註: 因為Python 的 原生 list 可以放一層一層的資料容器在內, 在copy 時會出現不預期的狀況, 後面介紹深拷貝跟淺拷貝, 有點繁瑣, 建議第一次閱讀, 可以跳過.
如果只是要拷貝某個 aList 內容, 不想跟原來的 aList 會有連動, 就用

import copy
aDeepCopy=aList.copy.deepcopy()

執行深複製, 全部(各層)不連動, 避免產生不預期的狀況.

  • 以上可以等進階時再細看

list 的 擷取元素與切片 (indexing 與 slicing)
>>> aList = [1,2,3,4,5]
>>> aList
[1, 2, 3, 4, 5]
取用 aList 的其中一個元素, 我們稱為 indexing, 取用第 index 個元素

特別注意 Python 的所有資料的容器(例如 list) 下標是從 0 開始
( Python, C, JavaScript 下標是從 0 開始
Matlab, R 下標是從 1 開始 )

>>> aList[0]
1
>>> aList[1]
2
取用 aList 的其中一段元素, 我們稱為 slicing (slice 切片)

所謂 slicing 語法, 是指  n:m  語法

>>> aList[1:3]
[2, 3]
>>> b = aList[1:3]
>>> b
[2, 3]

b 是 aList 的 slice, a 改變, 不會影響 b
( Python 的 list 之 slice 不會連動)
(注意: np.array()的 slice 會連動)

>>> aList[1]=22
>>> aList
[1, 22, 3, 4, 5]
>>> b
[2, 3]

Python 的 list 不能用 真假值或整數 list 取切片
但是 np.array 可以用 真假值或整數 之 np.array 或 lis 取切片

請參考後面 fancy indexing: np.array 的切片可以用 真假值之 list 或整數 之 list 或 np.array 做下標集, 提取內容, 但不連動

>>> aList
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> aList[[0,2,4]]
Traceback (most recent call last):
  File "<pyshell#76>", line 1, in <module>
    aList[[0,2,4]]
TypeError: list indices must be integers or slices, not list

  • 以下可以等進階時再細看
list 複製

Python 深淺拷貝, 只差在第二層以上
當 list 中含有 list 時, 深淺拷貝才會有差別

*aCopy1=aList[:] 淺複製, 只有第一層不連動

aCopy1=aList[:]
當 aList 改變 其中一個純量元素 時, aCopy 不會連動

>>> aList = [1,22,3,4,5]
>>> aCopy1 = aList[:]
>>> aCopy1
[1, 22, 3, 4, 5]
>>> aCopy1[0]=2
>>> aCopy1
[2, 22, 3, 4, 5]
>>> aList
[1, 22, 3, 4, 5]

對於 aList 是 list 含有 list 時

>>> aList = [1,2,3,4,[1,2,3]]
>>> aCopy = alist[:]
>>> aCopy
[1, 2, 3, 4, [1, 2, 3]]
>>> aList[4][0]=11
>>> aList
[1, 2, 3, 4, [11, 2, 3]]
>>> aCopy
[1, 2, 3, 4, [11, 2, 3]]
aCopy=aList.copy() 淺複製, 只有第一層不連動

aCopy=aList.copy()
當 aList 改變 其中一個純量元素 時, aCopy 不會連動

>>> aList
[1, 22, 3, 4, 5]
>>> aCopy=aList.copy()
>>> aCopy
[1, 22, 3, 4, 5]
>>> aCopy is aList
False
>>> aCopy == aList
True
>>> aCopy[0]=2
>>> aCopy
[2, 22, 3, 4, 5]
>>> aList
[1, 22, 3, 4, 5]

當 list 中含有 list 時, 如果只改變 list 中的 list 的一個元素 時, 淺拷貝還是會連動
當 aList 改變 list 中的 list 的一個元素 時, aCopy 也跟著改了

>>> aList = [1,22,3,4,[1,2,3]]
>>> aList
[1, 22, 3, 4, [1, 2, 3]]
>>> aCopy=aList.copy()
>>> aCopy
[1, 22, 3, 4, [1, 2, 3]]
>>> aList[0]=2
>>> aList
[2, 22, 3, 4, [1, 2, 3]]
>>> aCopy
[1, 22, 3, 4, [1, 2, 3]]
# 當 aList 改變  list 中的 list 的一個元素 時, aCopy 也跟著改了
>>> aList[4][1]=0
>>> aList
[2, 22, 3, 4, [1, 0, 3]]
>>> aCopy
[1, 22, 3, 4, [1, 0, 3]]
>>> aList[4] == aCopy[4]
True
>>> aList[4] is aCopy[4]
True
>>> aList[0] is aCopy[0]
True
>>> aList is aCopy
False
# 當 aList 改變 其中一個純量元素 時, aCopy 不會改
>>> aList[0]=3
>>> aList
[3, 22, 3, 4, [1, 0, 3]]
>>> aCopy
[2, 22, 3, 4, [1, 0, 3]]

當 aList 改變 list 中的 整個 list 時, 淺拷貝不連動
如果把 list 中的 list, 整條換掉, 似乎指向 list 中的該 list 的位址就改變了,
就把 aList[4] 與 aCopy[4] 的關聯脫鉤了!
( 如果只是更改 aList[4][1], 則 aList[4] 與 aCopy[4] 仍是同位址)

>>> aList[4]=[11,0,33]
>>> aList
[3, 22, 3, 4, [11, 0, 33]]
>>> aCopy
[2, 22, 3, 4, [1, 0, 3]]
>>> aList[4][1]=2
>>> aList
[3, 22, 3, 4, [11, 2, 33]]
>>> aCopy
[2, 22, 3, 4, [1, 0, 3]]
>>> aList[4] is aCopy[4]
False
  • 以上可以等進階時再細看

深複製, 全部(各層)不連動

import copy
aDeepCopy=copy.deepcopy(aList)

>>> import copy
>>> aDeepCopy=aList.copy.deepcopy()
Traceback (most recent call last):
  File "<pyshell#39>", line 1, in <module>
    aDeepCopy=aList.copy.deepcopy()
AttributeError: 'builtin_function_or_method' object has no attribute 'deepcopy'
>>> aDeepCopy=copy.deepcopy(aList)
>>> aDeepCopy
[1, 22, 3, 4, 5]
>>> aDeepCopy is aList
False
>>> aDeepCopy == aList
True

即使 aList 是一個 list 中含有 list, aDeepCopy是深複製得來的, 它還是, 各層都不會與 aList 連動

>>> aList = [1,2,3,4,[1,2,3]]
>>> aDeepCopy = copy.deepcopy(aList)
>>> aDeepCopy
[1, 2, 3, 4, [1, 2, 3]]
>>> aList[4][0] = 11
>>> aList
[1, 2, 3, 4, [11, 2, 3]]
>>> aDeepCopy
[1, 2, 3, 4, [1, 2, 3]]
複製但連動, 完全一樣

用等號 aListRef = aList, 其實是得到完全一樣

>>> aListRef = aList
>>> aListRef
[1, 22, 3, 4, 5]
>>> aListRef == aList
True
>>> aListRef is aList
True

產生 numpy 的 數組: np.array(), (Matlab: [1,2,3; 4,5,6])

對照: 劉正君, 3.4

>>> import numpy as np
>>> A = np.array([[1,2,3],[4,5,6]]);A
array([[1, 2, 3],
       [4, 5, 6]])
>>> B = np.arange(11,17);B
array([11, 12, 13, 14, 15, 16])
>>> B.reshape(3,2)
array([[11, 12],
       [13, 14],
       [15, 16]])

產生 numpy 的 數組: 各類特殊矩陣: 零矩陣、都是1的矩陣、 單位矩陣(對角線為1之矩陣)、 取用對角線矩陣、 上三角矩陣

ref: 劉正君, 3.6. 3

zeros filled array 零矩陣 (Matlab: zeros(3,5))

>>> a = np.zeros(5)
>>> a
array([0., 0., 0.,>>> a1 = np.zeros([5,5])
>>> a1
array([[0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0.]]) 0., 0.])
# 注意, 維度用 [5,5] 包住
>>> a1 = np.ones(5,5);a1
Traceback (most recent call last):
  File "<pyshell#5>", line 1, in <module>
    a1 = np.ones(5,5);a1
  File "C:\Users\user\AppData\Local\Programs\Python\Python38-32\lib\site-packages\numpy\core\numeric.py", line 207, in ones
    a = empty(shape, dtype, order)
TypeError: data type not understood

ones filled array 1矩陣 (Matlab: ones(3,5))

>>> b = np.ones(5)
>>> b
array([1., 1., 1., 1., 1.])
>>> b1 = np.ones([5,5])
>>> b1
array([[1., 1., 1., 1., 1.],
       [1., 1., 1., 1., 1.],
       [1., 1., 1., 1., 1.],
       [1., 1., 1., 1., 1.],
       [1., 1., 1., 1., 1.]])

any number filled array 任意數字填滿矩陣 (Matlab: ones(3,5)*9 )

>>> b2 = b1*3
>>> b2
array([[3., 3., 3., 3., 3.],
       [3., 3., 3., 3., 3.],
       [3., 3., 3., 3., 3.],
       [3., 3., 3., 3., 3.],
       [3., 3., 3., 3., 3.]])

identity array 單位矩陣(對角線矩陣) (Matlab: eye(3))

>>> c = np.eye(4)
>>> c
array([[1., 0., 0., 0.],
       [0., 1., 0., 0.],
       [0., 0., 1., 0.],
       [0., 0., 0., 1.]])
>>> c1 = np.identity(4)
>>> c1
array([[1., 0., 0., 0.],
       [0., 1., 0., 0.],
       [0., 0., 1., 0.],
       [0., 0., 0., 1.]])

給定 np.array a 取用a 的對角線 (Matlab: diag(a), diag(a,0))

>>> a
array([[1, 2, 3],
       [4, 5, 6],
       [7, 8, 9]])
>>> a_diag = np.diag(a)
>>> a_diag
array([1, 5, 9])
>>> a_diag2d = a_diag*np.eye(3)
>>> a_diag2d
array([[1., 0., 0.],
       [0., 5., 0.],
       [0., 0., 9.]])

隨機數組 (Matlab: rand(3,4))

>>> a_rand = np.random.rand(3,4)
>>> a_rand
array([[0.65543729, 0.32649166, 0.21621299, 0.58931067],
       [0.7932652 , 0.35415987, 0.83885435, 0.02375679],
       [0.01526737, 0.95740181, 0.36366563, 0.66846968]])

改變形狀 np.reshape()、 np.resize() (Matlab: reshape(1:6,3,2))

注意: 使用 reshape()時, 原array沒改變!

>>> B=np.array([11, 12, 13, 14, 15, 16])
>>> B
array([11, 12, 13, 14, 15, 16])
# 將 B reshape() 後的 array指定給 B1
>>> B1 = B.reshape(2,3)
>>> B1
array([[11, 12, 13],
       [14, 15, 16]])
# B 原 array 沒改變
>>> B
array([11, 12, 13, 14, 15, 16])

注意 A.reshape 後指定給另一個名稱, 例如 A_reform, A 與 A_reform 會連動,

>>> A = np.arange(1,11)
>>> A
array([ 1,  2,  3,  4,  5,  6,  7,  8,  9, 10])
>>> A.reshape(2,5)
array([[ 1,  2,  3,  4,  5],
       [ 6,  7,  8,  9, 10]])
>>> A
array([ 1,  2,  3,  4,  5,  6,  7,  8,  9, 10])
>>> A_reform=A.reshape(2,5)
>>> A_reform
array([[ 1,  2,  3,  4,  5],
       [ 6,  7,  8,  9, 10]])
>>> A_reform[1,2]
8
>>> A_reform[1,2]=18
>>> A_reform
array([[ 1,  2,  3,  4,  5],
       [ 6,  7, 18,  9, 10]])
>>> A
array([ 1,  2,  3,  4,  5,  6,  7, 18,  9, 10])

注意: 使用 resize()時, 原array會改變!

>>> B2 = np.resize(B,(3,2))
>>> B2
array([[11, 12],
       [13, 14],
       [15, 16]])
>>> B
array([[11, 12],
       [13, 14],
       [15, 16]])

用 B2 = B.resize(3,2)會出錯

>>> B2 = B.resize(3,2)
>>> B2
>>> B2[0]
Traceback (most recent call last):
  File "<pyshell#46>", line 1, in <module>
    B2[0]
TypeError: 'NoneType' object is not subscriptable

np.array()的元素可以是那些?

基本上就是整數、浮點數、複數、字串等

>>> np.typeDict.values()
dict_values([<class 'numpy.bool_'>, <class 'numpy.bool_'>, <class 'numpy.int8'>, <class 'numpy.int8'>, <class 'numpy.int8'>, <class 'numpy.uint8'>, <class 'numpy.uint8'>, <class 'numpy.uint8'>, <class 'numpy.int16'>, <class 'numpy.int16'>, <class 'numpy.int16'>, <class 'numpy.uint16'>, <class 'numpy.uint16'>, <class 'numpy.uint16'>, <class 'numpy.intc'>, <class 'numpy.intc'>, <class 'numpy.uint32'>, <class 'numpy.uintc'>, <class 'numpy.uintc'>, <class 'numpy.intc'>, <class 'numpy.intc'>, <class 'numpy.uintc'>, <class 'numpy.uintc'>, <class 'numpy.int32'>, <class 'numpy.int32'>, <class 'numpy.int32'>, <class 'numpy.uint32'>, <class 'numpy.uint32'>, <class 'numpy.int64'>, <class 'numpy.int64'>, <class 'numpy.int64'>, <class 'numpy.uint64'>, <class 'numpy.uint64'>, <class 'numpy.uint64'>, <class 'numpy.float16'>, <class 'numpy.float16'>, <class 'numpy.float16'>, <class 'numpy.float32'>, <class 'numpy.float32'>, <class 'numpy.float64'>, <class 'numpy.float64'>, <class 'numpy.float64'>, <class 'numpy.longdouble'>, <class 'numpy.longdouble'>, <class 'numpy.longdouble'>, <class 'numpy.complex128'>, <class 'numpy.complex64'>, <class 'numpy.complex64'>, <class 'numpy.complex128'>, <class 'numpy.complex128'>, <class 'numpy.complex128'>, <class 'numpy.clongdouble'>, <class 'numpy.clongdouble'>, <class 'numpy.clongdouble'>, <class 'numpy.object_'>, <class 'numpy.object_'>, <class 'numpy.bytes_'>, <class 'numpy.bytes_'>, <class 'numpy.str_'>, <class 'numpy.str_'>, <class 'numpy.str_'>, <class 'numpy.void'>, <class 'numpy.void'>, <class 'numpy.void'>, <class 'numpy.datetime64'>, <class 'numpy.datetime64'>, <class 'numpy.timedelta64'>, <class 'numpy.timedelta64'>, <class 'numpy.bool_'>, <class 'numpy.bool_'>, <class 'numpy.bool_'>, <class 'numpy.int32'>, <class 'numpy.int32'>, <class 'numpy.int32'>, <class 'numpy.uint32'>, <class 'numpy.uintc'>, <class 'numpy.uint32'>, <class 'numpy.float16'>, <class 'numpy.float16'>, <class 'numpy.float16'>, <class 'numpy.float32'>, <class 'numpy.float32'>, <class 'numpy.float32'>, <class 'numpy.float64'>, <class 'numpy.float64'>, <class 'numpy.float64'>, <class 'numpy.complex64'>, <class 'numpy.complex64'>, <class 'numpy.complex64'>, <class 'numpy.complex128'>, <class 'numpy.complex128'>, <class 'numpy.complex128'>, <class 'numpy.object_'>, <class 'numpy.object_'>, <class 'numpy.bytes_'>, <class 'numpy.bytes_'>, <class 'numpy.str_'>, <class 'numpy.str_'>, <class 'numpy.void'>, <class 'numpy.void'>, <class 'numpy.datetime64'>, <class 'numpy.datetime64'>, <class 'numpy.datetime64'>, <class 'numpy.timedelta64'>, <class 'numpy.timedelta64'>, <class 'numpy.timedelta64'>, <class 'numpy.uint32'>, <class 'numpy.int64'>, <class 'numpy.int64'>, <class 'numpy.int64'>, <class 'numpy.uint64'>, <class 'numpy.uint64'>, <class 'numpy.uint64'>, <class 'numpy.int16'>, <class 'numpy.int16'>, <class 'numpy.int16'>, <class 'numpy.uint16'>, <class 'numpy.uint16'>, <class 'numpy.uint16'>, <class 'numpy.int8'>, <class 'numpy.int8'>, <class 'numpy.int8'>, <class 'numpy.uint8'>, <class 'numpy.uint8'>, <class 'numpy.uint8'>, <class 'numpy.complex128'>, <class 'numpy.intc'>, <class 'numpy.uintc'>, <class 'numpy.float32'>, <class 'numpy.complex64'>, <class 'numpy.complex64'>, <class 'numpy.float64'>, <class 'numpy.intc'>, <class 'numpy.uintc'>, <class 'numpy.int32'>, <class 'numpy.longdouble'>, <class 'numpy.clongdouble'>, <class 'numpy.clongdouble'>, <class 'numpy.bool_'>, <class 'numpy.bytes_'>, <class 'numpy.bytes_'>, <class 'numpy.str_'>, <class 'numpy.object_'>, <class 'numpy.str_'>, <class 'numpy.int32'>, <class 'numpy.float64'>, <class 'numpy.complex128'>, <class 'numpy.bool_'>, <class 'numpy.object_'>, <class 'numpy.str_'>, <class 'numpy.bytes_'>, <class 'numpy.bytes_'>])

如果元素是 list, 或是 np.array 的類型,也可以

>>> a=np.array(['a','b',[1,2]])
>>> a
array(['a', 'b', list([1, 2])], dtype=object)
>>> a=np.array(['a','b',np.array([1,2])])
>>> a
array(['a', 'b', array([1, 2])], dtype=object)
>>> a[0]
'a'
>>> a[2]
array([1, 2])

為何不用 Python 的 原生 list 來執行類似數組的操作?

Ans:

  1. NumPy 的 array 是用 C 的 知名線性代數工具庫 去計算, 而 list 的效能並沒有用 C 優化,
  2. NumPy 的 array 允許用真假值(布林值)或整數 之 list 或 真假值(布林值)或整數 之 np.array 做下標集, 提取內容, 但 list 無此功能

有關上面 2. 的測試:
產生一個 Python 的 原生 list

# 產生一個 Python 的 原生 list
>>> aList = [0,1,2,3,4,5]
>>> aList
[0, 1, 2, 3, 4, 5]
# 定義一個真假值(布林值) list
>>> booleanIndex = [ True, False, True, False, True, False]
# 用真假值(布林值)做下標集, 提取
# 出現錯誤訊息, 顯示, list 的 下標集只能用單一整數或是 slices 切片(用 n:m 語法)
>>> aList[booleanIndex]
Traceback (most recent call last):
  File "<pyshell#3>", line 1, in <module>
    aList[booleanIndex]
TypeError: list indices must be integers or slices, not list

產生一個 np 的 array, 用跟上面一樣的真假值(布林值) list: booleanIndex 去提取內容, 發現可以!

>>> import numpy as np
>>> aArray = np.array([0,1,2,3,4,5])
>>> aArray
array([0, 1, 2, 3, 4, 5])
>>> aArray[booleanIndex]
array([0, 2, 4])
>>> 

請參考後面 fancy indexing: np.array 的切片可以用 真假值之 list 或整數 之 list 或 np.array 做下標集, 提取內容, 但不連動

A 的長寬高 A.shape(), A 的元素個數 A.size (Matlab: size(A), length(A))

array (或matrix) 常需要維度的訊息

>>> A.shape
(2, 3)
>>> np.shape(A)
(2, 3)
>>> len(A)
2
>>> B.shape
(6,)
>>> B1.shape
(3, 2)
>>> B2.shape
(2, 3)

>>> A.size
6
>>> np.size(A)
6

A 的維度有幾維 A.ndim (Matlab: ndims(A))

以下Array 有3維
在操作線性代數時, 有時會需要知道該數組的維度有幾維

>>> aArray = np.array([[[1,2,3],[4,5,6]],[[7,8,9],[10,11,12]]])
>>> aArray
array([[[ 1,  2,  3],
        [ 4,  5,  6]],

       [[ 7,  8,  9],
        [10, 11, 12]]])
>>> aArray.ndim
3

此時 A 與 B1的維度相合, 就可以進行矩陣相乘

矩陣相乘

  • 在 Matlab 中是用 A * B1,
  • 在 numpy中用 numpy.dot(A, B1), 或是
  • numpy.matmul(A,B1)
>>> np.dot(A,B1)
array([[ 82,  88],
       [199, 214]])
>>> np.matmul(A,B1)
array([[ 82,  88],
       [199, 214]])

矩陣點乘

  • 在 Matlab 中是用 A .* B
  • 在 numpy中用 A*B
>>> B2=B.reshape(2,3)
>>> B2
array([[11, 12, 13],
       [14, 15, 16]])
>>> A*B2
array([[11, 24, 39],
       [56, 75, 96]])
>>> np.multiply(A,B2)
array([[11, 24, 39],
       [56, 75, 96]])

矩陣點除

  • 在 Matlab 中是用 A ./ B
  • 在 numpy中用 A/B
>>> A/B2
array([[0.09090909, 0.16666667, 0.23076923],
       [0.28571429, 0.33333333, 0.375     ]])

矩陣複製

np 中最常出錯的是對一個array 做 copy 的動作
ref: Scipy lecture notes, Edition 2020.1: sec 4.1.6 copy and view
**ref: 何敏煌, Python 程式設計實務, sec 6.3.5: a is b **

如果直接用 A1= A

則得到一個完全一樣的 A, 只是多一個別名叫 A1 而已,
此時你改變 A1, 就等於改變A, A 與 A1 都指向同一個位址

>>> A1 = A
>>> A1 is A
True
>>> A.shape
(2, 3)
>>> A1.shape
(2, 3)
>>> A1.shape=(3,2)
>>> A1.shape
(3, 2)
>>> A.shape
(3, 2)
>>> A
array([[1, 2],
       [3, 4],
       [5, 6]])
>>> A1
array([[1, 2],
       [3, 4],
       [5, 6]])
>>> id(A)
60451360
>>> id(A1)
60451360
切片是 view 會連動

view 是(淺層)拷貝 (shallow) copy
取 slicing 就是 view
當 S 是 A 的 slice, 改變 S, 也會改變 A, 會連動

>>> A
array([[1, 2],
       [3, 4],
       [5, 6]])
>>> S = A[:,1]
>>> S
array([2, 4, 6])
>>> S[:] = 10
>>> S
array([10, 10, 10])
>>> A
array([[ 1, 10],
       [ 3, 10],
       [ 5, 10]])
copy(), id()

copy 是(深層)拷貝 (deep) copy
D = A.copy(), 則D 的資料與 A 一樣, 但是, 位址不同, 改變D, 與 A 無關!

>>> D = A.copy()
>>> D
array([[ 1, 10],
       [ 3, 10],
       [ 5, 10]])
>>> D is A
False
>>> D[0,:]=9
>>> D
array([[ 9,  9],
       [ 3, 10],
       [ 5, 10]])
>>> A
array([[ 1, 10],
       [ 3, 10],
       [ 5, 10]])

>>> id(A)
60451360
>>> id(D)
206144320
fancy indexing: np.array 的切片可以用 真假值之 list 或整數 之 list 或 np.array 做下標集, 提取內容, 但不連動

NumPy 的 array 允許用真假值(布林值)或整數 之 list 或 真假值(布林值)或整數 之 np.array 做下標集, 提取內容(但 list 無此功能), 與原來的 array 不連動, scipy lecture notes 稱此為 fancy indexing.

ref: Scipy lecture notes, Edition 2020.1: sec4.1.7 Fancy indexing

以下用 整數 之 list 取切片, 不連動

>>> import numpy as np
>>> aArray = np.array([1,2,3,4,5])
>>> aArray
array([1, 2, 3, 4, 5])
>>> aArray[[0,1,4]]
array([1, 2, 5])
>>> bArray = aArray[[0,1,4]]
>>> bArray
array([1, 2, 5])
>>> aArray[0]=22
>>> aArray
array([22,  2,  3,  4,  5])
>>> bArray
array([1, 2, 5])
>>> bArray[0]=11
>>> bArray
array([11,  2,  5])
>>> aArray
array([22,  2,  3,  4,  5])
>>> arrayIndex = np.array([1,2,4])
>>> arrayIndex
array([1, 2, 4])
>>> bArray = aArray[arrayIndex]
>>> bArray
array([2, 3, 5])

以下用 整數 之 np.array 取切片, 不連動

>>> arrayIndex = np.array([0,1,4])
>>> arrayIndex
array([0, 1, 4])
>>> bArray = aArray[arrayIndex]
>>> bArray
array([22,  2,  5])
>>> aArray[0]=222
>>> aArray
array([222,   2,   3,   4,   5])
>>> bArray
array([22,  2,  5])

NumPy 的 速查簡表

Ref: 以下我們參考: Python Numpy全世界最長基礎教程最適合小白學習 還詳細很全速拿, https://twgreatdaily.com/AhWyTG8BMH2_cNUgWU4g.html link.

一、數組方法

創建數組:arange()創建一維數組;array()創建一維或多維數組,其參數是類似於數組的對象,如列表等

創建數組:np.zeros((2,3)),或者np.ones((2,3)),參數是一個元組分別表示行數和列數

對應元素相乘,a * b,得到一個新的矩陣,形狀要一致;但是允許a是向量而b是矩陣,a的列數必須等於b的列數,a與每個行向量點乘

    • / 與 * 的運算規則相同。

數學上定義的矩陣乘法 np.dot(a, b)。如果形狀不匹配會報錯;但是允許允許a和b都是向量,返回兩個向量的內積。只要有一個參數不是向量,就應用矩陣乘法。

(PS:總之就是,向量很特殊,在運算中可以自由轉置而不會出錯,運算的返回值如果維度為1,也一律用行向量[]表示)

讀取數組元素:如a[0],a[0,0]

數組變形:如b=a.reshape(2,3,4)將得到原數組變為234的三維數組後的數組;或是a.shape=(2,3,4)或a.resize(2,3,4)直接改變數組a的形狀

數組組合:水平組合hstack((a,b))或concatenate((a,b),axis=1);垂直組合vstack((a,b))或concatenate((a,b),axis=0);深度組合dstack((a,b))

數組分割(與數組組合相反):分別有hsplit,vsplit,dsplit,split(split與concatenate相對應)

將np數組變為py列表:a.tolist()

數組排序(小到大):列排列np.msort(a),行排列np.sort(a),np.argsort(a)排序後返回下標

複數排序:np.sort_complex(a)按先實部後虛部排序

數組的插入:np.searchsorted(a,b)將b插入原有序數組a,並返回插入元素的索引值

類型轉換:如a.astype(int),np的數據類型比py豐富,且每種類型都有轉換方法

條件查找,返回滿足條件的數組元素的索引值:np.where(條件)

條件查找,返回下標:np.argwhere(條件)

>>> A
array([ 1,  4,  7, 10])
>>> np.argwhere(A==7)
array([[2]], dtype=int64)
>>> np.where(A==7)
(array([2], dtype=int64),)
>>> np.where(A%2==0)
(array([1, 3], dtype=int64),)
>>> np.argwhere(A%2==0)
array([[1],
       [3]], dtype=int64)

條件查找,返回滿足條件的數組元素:np.extract([條件],a)

根據b中元素作為索引,查找a中對應元素:np.take(a,b)一維

數組中最小最大元素的索引:np.argmin(a),np.argmax(a)

多個數組的對應位置上元素大小的比較:np.maximum(a,b,c,……)返回每個索引位置上的最大值,np.minimum(…….)相反

將a中元素都置為b:a.fill(b)

每個數組元素的指數:np.exp(a)

生成等差行向量:如np.linspace(1,6,10)則得到1到6之間的均勻分布,總共返回10個數

求余:np.mod(a,n)相當於a%n,np.fmod(a,n)仍為求余且餘數的正負由a決定

計算平均值:np.mean(a)

計算最大值:amax(a, axis=None, out=None, keepdims=False) 。Return the maximum of an array or maximum along an axis.

計算加權平均值:np.average(a,b),其中b是權重

計算數組的極差:np.pth(a)=max(a)-min(a)

計算方差(總體方差):np.var(a)

標準差:np.std(a)

算術平方根,a為浮點數類型:np.sqrt(a)

對數:np.log(a)

修剪數組,將數組中小於x的數均換為x,大於y的數均換為y:a.clip(x,y)

所有數組元素乘積:a.prod()

數組元素的累積乘積:a.cumprod()

數組元素的符號:np.sign(a),返回數組中各元素的正負符號,用1和-1表示

數組元素分類:np.piecewise(a,[條件],[返回值]),分段給定取值,根據判斷條件給元素分類,並返回設定的返回值。

判斷兩數組是否相等: np.array_equal(a,b)

判斷數組元素是否為實數: np.isreal(a)

去除數組中首尾為0的元素:np.trim_zeros(a)

對浮點數取整,但不改變浮點數類型:np.rint(a)

二、數組屬性

1.獲取數組每一維度的大小:a.shape

2.獲取數組維度:a.ndim

3.元素個數:a.size

4.數組元素在內存中的字節數:a.itemsize

5.數組字節數:a.nbytes==a.size*a.itemsize

6.數組元素覆蓋:a.flat=1,則a中數組元素都被1覆蓋

7.數組轉置:a.T

不能求逆、求協方差、跡等,不適用於複雜科學計算,可以將array轉換成matrix。

三、矩陣方法

np.mat(『…』) 官網已建議不要使用
創建矩陣:np.mat(『…』)通過字符串格式創建,np.mat(a)通過array數組創建,也可用matrix或bmat函數創建

創建複合矩陣:np.bmat(『A B』,』AB』),用A和B創建複合矩陣AB(字符串格式)

創建n*n維單位矩陣:np.eye(n)

矩陣的轉置:A.T

矩陣的逆矩陣:A.I

計算協方差矩陣:np.cov(x),np.cov(x,y)

計算矩陣的跡(對角線元素和):a.trace()

相關係數:np.corrcoef(x,y)

給出對角線元素:a.diagonal()

四、線性代數

估計線性模型中的係數:a=np.linalg.lstsq(x,b),有b=a*x

求方陣的逆矩陣:np.linalg.inv(A)

求廣義逆矩陣:np.linalg.pinv(A)

求矩陣的行列式:np.linalg.det(A)

解形如AX=b的線性方程組:np.linalg.solve(A,b)

求矩陣的特徵值:np.linalg.eigvals(A)

求特徵值和特徵向量:np.linalg.eig(A)

Svd分解:np.linalg.svd(A)

五、機率分布

產生二項分布的隨機數:np.random.binomial(n,p,size=…),其中n,p,size分別是每輪試驗次數、機率、輪數

產生超幾何分布隨機數:np.random.hypergeometric(n1,n2,n,size=…),其中參數意義分別是物件1總量、物件2總量、每次採樣數、試驗次數

產生N個正態分布的隨機數:np.random.normal(均值,標準差,N)

產生N個對數正態分布的隨機數:np.random.lognormal(mean,sigma,N)

六、多項式

多項式擬合:poly= np.polyfit(x,a,n),擬合點集a得到n級多項式,其中x為橫軸長度,返回多項式的係數

多項式求導函數:np.polyder(poly),返回導函數的係數

得到多項式的n階導函數:多項式.deriv(m = n)

多項式求根:np.roots(poly)

多項式在某點上的值:np.polyval(poly,x[n]),返回poly多項式在橫軸點上x[n]上的值

兩個多項式做差運算: np.polysub(a,b)

Matpoltlib簡單繪圖方法

引入簡單繪圖的包import matplotlib.pyplot as plt,最後用plt.show()顯示圖像

基本畫圖方法:plt.plot(x,y),plt.xlabel(『x』),plt.ylabel(『y』),plt.title(『…』)

子圖:plt.subplot(abc),其中abc分別表示子圖行數、列數、序號

創建繪圖組件的頂層容器:fig = plt.figure()

添加子圖:ax = fig.add_subplot(abc)

設置橫軸上的主定位器:ax.xaxis.set_major_locator(…)

繪製方圖:plt.hist(a,b),a為長方形的左橫坐標值,b為柱高

繪製散點圖:plt.scatter(x,y,c = 『…』,s = …),c表示顏色,s表示大小

添加網格線:plt.grid(True)

添加注釋:如ax.annotate(‘x’, xy=xpoint, textcoords=‘offsetpoints’,xytext=(-50, 30), arrowprops=dict(arrowstyle=“->”))

增加圖例:如plt.legend(loc=‘best’, fancybox=True)

對坐標取對數:橫坐標plt.semilogx(),縱坐標plt.semilogy(),橫縱同時plt.loglog()

NumPy 與 Matlab, R, Octave 等的對照速查簡表

可以參考以下 References.

References

  • Python Numpy全世界最長基礎教程最適合小白學習 還詳細很全速拿, https://twgreatdaily.com/AhWyTG8BMH2_cNUgWU4g.html link.

Python NumPy 與 Matlab, R, Octave 等的對照:

  • Thesaurus of Mathematical Languages,
    or MATLAB synonymous commands in Python/NumPy
    列出 Matlab, Python, R, Octave等, 相對應的指令,
    有 pdf檔.
    Copyright ©2006,2008 Vidar Bronken Gundersen, http://mathesaurus.sf.net/
    link

  • NumPy for Matlab users
    列出 Matlab, Python 相對應的指令.
    https://numpy.org/doc/stable/user/numpy-for-matlab-users.html
    link

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值