背景
前段時間在知識星球上立了一個Flag,至少寫10篇關於 Python,Matlab 和 C# 對比的總結。
這是第 4 篇,對比 Matlab 與 Numpy 中經常用到的各種矩陣,比如零矩陣、單位矩陣、全1矩陣、對角矩陣、均勻分布的隨機矩陣、標準正態分布的隨機矩陣等。
雖然 Numpy 定義了 matrix 類型,使用該 matrix 類型創建的是矩陣對象。但是由於 NumPy 中同時存在 ndarray 和 matrix 對象,因此用戶很容易將兩者弄混。這有違 Python 的「顯式優於隱式」的原則,因此官方並不推薦在程序中使用 matrix。在這裡,我們仍然用 ndarray 來介紹。
1. 零矩陣
零矩陣為矩陣內所有元素為零的矩陣。在具體任務中通常先用零矩陣來確定大小,隨後為矩陣元素賦值。
在 Matlab和Python 中都用zeros()函數來實現。
在 Matlab 中,zeros(m,n)表示零矩陣,其中
在 Numpy 中,numpy.zeros(shape, dtype=None, order='C')函數返回給定形狀和類型的零數組。
【例1】求3行4列的零矩陣。
Matlab:
>> A = zeros(3,4);
>> disp(A)
0 0 0 0
0 0 0 0
0 0 0 0
Python:
import numpy as np
A = np.zeros([3, 4])
print(A)
# [[0. 0. 0. 0.]
# [0. 0. 0. 0.]
# [0. 0. 0. 0.]]
【例2】求4階的零矩陣。
Matlab:
>> A = zeros(4);
>> disp(A)
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
Python:
import numpy as np
A = np.zeros([4, 4])
print(A)
# [[0. 0. 0. 0.]
# [0. 0. 0. 0.]
# [0. 0. 0. 0.]
# [0. 0. 0. 0.]]
A = np.zeros(4)
print(A)
# [0. 0. 0. 0.]
np.zeros(4)表示生成 Numpy 中的包含4個零元素的一維數組。
注意:在線性代數裡面講的維數和數組的維數不同,如線代中提到的 n 維行向量在 Numpy 中是一維數組,而線性代數中的 n 維列向量在 Numpy 中是一個shape為(n, 1)的二維數組。
2. 全1矩陣矩陣中所有元素為1,稱為全1矩陣。
在 Matlab和Numpy 中都用ones()函數來表示。
在 Matlab 中,ones(m,n)表示全1矩陣,其中為行數,為列數。若為方陣,則以ones(n)表示。
在 Numpy 中,numpy.ones(shape, dtype=None, order='C')函數返回給定形狀和類型的全1數組。
【例1】求4階全1矩陣。
Matlab:
>> A=ones(4);
>> disp(A)
1 1 1 1
1 1 1 1
1 1 1 1
1 1 1 1
Python:
import numpy as np
A = np.ones([4, 4])
print(A)
# [[1. 1. 1. 1.]
# [1. 1. 1. 1.]
# [1. 1. 1. 1.]
# [1. 1. 1. 1.]]
A = np.ones(4)
print(A)
# [1. 1. 1. 1.]
【例2】求3行4列的全1矩陣。
Matlab:
>> A=ones(3,4);
>> disp(A)
1 1 1 1
1 1 1 1
1 1 1 1
Python:
import numpy as np
A = np.ones([3, 4])
print(A)
# [[1. 1. 1. 1.]
# [1. 1. 1. 1.]
# [1. 1. 1. 1.]]
3. 單位矩陣單位矩陣為主對角線元素全為1,而其它元素全為零的矩陣,數學上以或表示之。
在 Matlab和Numpy 中都用eye()函數來表示,而 Numpy 中還提供了identity()函數來專門生成方陣。
在 Matlab 中,eye(m,n)表示單位矩陣,其中為行數,為列數,若為方陣,則以eye(n)表示。
在 Numpy 中,numpy.eye(N, M=None, k=0, dtype=float, order='C')函數返回一個對角線上為1,其它地方為零的單位數組。numpy.identity(n, dtype=None)函數則返回一個方的單位數組。
【例1】求4行4列的單位矩陣。
Matlab:
>> I=eye(4);
>> disp(I)
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
Python:
import numpy as np
I = np.eye(4)
print(I)
# [[1. 0. 0. 0.]
# [0. 1. 0. 0.]
# [0. 0. 1. 0.]
# [0. 0. 0. 1.]]
A = np.identity(4)
print(A)
# [[1. 0. 0. 0.]
# [0. 1. 0. 0.]
# [0. 0. 1. 0.]
# [0. 0. 0. 1.]]
【例2】求3行4列的單位矩陣。
Matlab:
>> I=eye(3,4);
>> disp(I)
1 0 0 0
0 1 0 0
0 0 1 0
Python:
import numpy as np
I = np.eye(3, 4)
print(I)
# [[1. 0. 0. 0.]
# [0. 1. 0. 0.]
# [0. 0. 1. 0.]]
4. 對角矩陣在 Matlab和Numpy 中都用diag()函數來表示,並且含義相同。
若書寫格式為X=diag(v,k)。將向量寫入矩陣的主對角線上,而矩陣的其它元素為零。表示上移或下移行數,正表示上移,負表示下移,則恰好在主對角線上,當時可以默認不寫。
另一種書寫格式為v=diag(X,k)。它是從矩陣中提取對角線元素到向量上。或默認,則提取主對角線元素,否則提取上移行或下移行的對角線元素,正號表示上移,負號表示下移。
【例1】已知行向量v=(1 2 3 4),將向量元素寫入矩陣的主對角線,求對角矩陣,以及上移一行的對角矩陣和下移一行的對角矩陣。
Matlab:
>> v=[1,2,3,4];
>> lambda = diag(v);
>> disp(lambda)
1 0 0 0
0 2 0 0
0 0 3 0
0 0 0 4
>> lambda = diag(v,1);
>> disp(lambda)
0 1 0 0 0
0 0 2 0 0
0 0 0 3 0
0 0 0 0 4
0 0 0 0 0
>> lambda = diag(v,-1);
>> disp(lambda)
0 0 0 0 0
1 0 0 0 0
0 2 0 0 0
0 0 3 0 0
0 0 0 4 0
Python:
import numpy as np
v = [1, 2, 3, 4]
lamb = np.diag(v)
# print(lamb)
# [[1 0 0 0]
# [0 2 0 0]
# [0 0 3 0]
# [0 0 0 4]]
lamb = np.diag(v, k=1)
print(lamb)
# [[0 1 0 0 0]
# [0 0 2 0 0]
# [0 0 0 3 0]
# [0 0 0 0 4]
lamb = np.diag(v, k=-1)
print(lamb)
# [[0 0 0 0 0]
# [1 0 0 0 0]
# [0 2 0 0 0]
# [0 0 3 0 0]
# [0 0 0 4 0]]
【例2】已知u=(2 3 5 8 11),創建Vandermonde矩陣,提取的主對角線賦予向量,主對角線上移一行賦予向量,下移一行賦予向量。
>> u=[2,3,5,8,11];
>> X=vander(u);
>> disp(X)
16 8 4 2 1
81 27 9 3 1
625 125 25 5 1
4096 512 64 8 1
14641 1331 121 11 1
>> v=diag(X);
>> disp(v)
16
27
25
8
1
>> v1=diag(X,1)';
>> disp(v1)
8 9 5 1
>> v2=diag(X,-1)';
>> disp(v2)
81 125 64 11
Python:
import numpy as np
def vander(u):
n = len(u)
a = np.ones([n, n], dtype=np.int)
for i in range(n - 2, -1, -1):
a[:, i] = u ** (n - i - 1)
return a
u = np.array([2, 3, 5, 8, 11])
X = vander(u)
print(X)
# [[ 16 8 4 2 1]
# [ 81 27 9 3 1]
# [ 625 125 25 5 1]
# [ 4096 512 64 8 1]
# [14641 1331 121 11 1]]
v = np.diag(X)
print(v)
# [16 27 25 8 1]
v1 = np.diag(X, k=1)
print(v1)
# [8 9 5 1]
v2 = np.diag(X, k=-1)
print(v2)
# [ 81 125 64 11]
5. 均勻分布的隨機矩陣在 Matlab和Numpy 中都可以生成均勻分布的隨機矩陣。
在 Matlab 中,有rand(),rands(),randi()三種方式:
rand(m,n)得到一個由均勻分布在(0,1)區間內元素組成的的矩陣。rands(m,n)得到一個由均勻分布在(-1,1)區間內元素組成的的矩陣。randi(iMax,n)是一個由均勻分布在[1,iMax]區間內整型元素組成的的矩陣。randi(iMax,m,n)是一個由均勻分布在[1,iMax]區間內整型元素組成的的矩陣。randi([iMin,iMax],m,n)是一個由均勻分布在[iMin,iMax]區間內整型元素組成的矩陣。在 Numpy 中,有uniform(),rand(),randint()三種方式:
numpy.random.uniform(low=0.0, high=1.0, size=None) 從均勻分布中抽取樣本,區間為[low, high) 。numpy.random.rand() 作為uniform(d0, d1, ..., dn)的特列,可以得到[0,1)之間的均勻分布的隨機數。numpy.random.randint(low, high=None, size=None, dtype='l') 作為uniform的另一特例,可以得到[low,high)之間均勻分布的隨機整數,如果high=None,那麼區間為[0,low)。【例1】求兩個4階在(0,1)範圍內的均勻分布的隨機矩陣,兩個4階在[1,100]範圍內的整型均勻分布的隨機數,兩個4×1的在(-1,1)範圍內的列向量,分別賦值給A1,A2。
Matlab:
>> A1=rand(4);
>> A2=rand(4);
>> disp(A1)
0.2232 0.6585 0.3061 0.9472
0.8876 0.8102 0.2829 0.6746
0.7311 0.2015 0.4056 0.7016
0.3146 0.1130 0.8241 0.6380
>> disp(A2)
0.2420 0.6504 0.2952 0.6328
0.9741 0.0814 0.3742 0.2157
0.8539 0.8477 0.7121 0.4115
0.7950 0.1764 0.6574 0.4196
>> A1 = randi(100,4);
>> A2 = randi(100,4);
>> disp(A1)
47 56 32 61
65 25 94 93
83 5 19 92
25 76 55 4
>> disp(A2)
69 86 47 41
4 84 98 3
51 80 59 9
30 81 73 59
>> A1=rands(4);
>> A2=rands(4);
>> disp(A1)
0.2796
0.4079
0.5119
-0.9015
>> disp(A2)
0.7674
-0.4059
0.3743
-0.3374
Python:
import numpy as np
A1 = np.random.rand(4, 4)
A2 = np.random.rand(4, 4)
print(A1)
# [[0.26928205 0.36481389 0.66676956 0.86820657]
# [0.91229641 0.04239373 0.88579269 0.41331319]
# [0.45072909 0.16651979 0.09096757 0.63638447]
# [0.96256553 0.12203043 0.88213325 0.70119275]]
print(A2)
# [[0.99001364 0.59498628 0.18862191 0.24256341]
# [0.1211043 0.32129381 0.9460552 0.05122717]
# [0.63987355 0.61879931 0.31145657 0.32688994]
# [0.73492717 0.43796817 0.9866393 0.93774641]]
A1 = np.random.randint(1, 100, [4, 4])
A2 = np.random.randint(1, 100, [4, 4])
print(A1)
# [[ 9 44 72 10]
# [33 89 55 47]
# [77 59 84 83]
# [43 23 86 59]]
print(A2)
# [[ 5 89 33 11]
# [21 95 73 92]
# [ 2 55 30 25]
# [54 40 65 83]]
A1 = np.random.uniform(-1, 1, 4)
A2 = np.random.uniform(-1, 1, 4)
print(A1.reshape(4, 1))
# [[ 0.93055573]
# # [-0.86806273]
# # [-0.8755103 ]
# # [ 0.54197419]]
print(A2.reshape(4, 1))
# [[-0.32703134]
# [ 0.80505337]
# [-0.83637509]
# [ 0.69088863]]
【例2】求三個階均勻分布的隨機矩陣,範圍在(0,1),(-1,1)和[10,100],分別賦值給A1,A2,A3。
Matlab:
>> A1=rand(3,4);
>> disp(A1)
0.7850 0.5495 0.0590 0.1740
0.0589 0.5529 0.1722 0.8426
0.3510 0.1447 0.4489 0.4642
>> A2=rands(3,4);
>> disp(A2)
-0.3603 -0.5592 0.2269 0.0017
-0.4025 -0.7993 -0.8550 0.6255
0.2765 0.6801 0.4448 -0.2550
>> A3 = randi([10,100],3,4);
>> disp(A3)
59 66 63 81
31 55 50 63
15 88 98 34
Python:
import numpy as np
A1 = np.random.rand(3, 4)
print(A1)
# [[0.39787012 0.13709285 0.43893989 0.96172473]
# [0.43530643 0.05443109 0.36316048 0.94816304]
# [0.55265213 0.60320904 0.24952952 0.83926361]]
A2 = np.random.uniform(-1, 1, [3, 4])
print(A2)
# [[ 0.32297696 -0.78124371 -0.39123924 0.24991417]
# [ 0.85884802 -0.23765347 0.56611597 0.90097203]
# [-0.72628246 -0.10791575 -0.11244534 0.40308801]]
A3 = np.random.randint(10, 100, [3, 4])
print(A3)
# [[29 53 65 89]
# [10 77 44 33]
# [28 85 35 42]]
【例3】使用種子使得每次隨機數相同。
Matlab:
>> s=rng(20200821); % 保存隨機數seed
>> disp(s)
Type: 'twister'
Seed: 20200821
State: [625×1 uint32]
>> rng(s) % 調用隨機數seed
>> A1=rand(4);
>> disp(A1)
0.0172 0.6571 0.8932 0.3110
0.6420 0.8373 0.8906 0.3815
0.0978 0.8899 0.6041 0.8875
0.4353 0.7270 0.5803 0.3294
>> rng(s)
>> A2=rand(4);
>> disp(A2)
0.0172 0.6571 0.8932 0.3110
0.6420 0.8373 0.8906 0.3815
0.0978 0.8899 0.6041 0.8875
0.4353 0.7270 0.5803 0.3294
Python:
import numpy as np
np.random.seed(20200821)
A1 = np.random.rand(4, 4)
print(A1)
# [[0.32452405 0.49496274 0.88643592 0.75054701]
# [0.88940824 0.4339118 0.45194462 0.80973677]
# [0.39462383 0.72057367 0.21335562 0.87752275]
# [0.42963472 0.92526431 0.22639798 0.83541325]]
np.random.seed(20200821)
A2 = np.random.rand(4, 4)
print(A2)
# [[0.32452405 0.49496274 0.88643592 0.75054701]
# [0.88940824 0.4339118 0.45194462 0.80973677]
# [0.39462383 0.72057367 0.21335562 0.87752275]
# [0.42963472 0.92526431 0.22639798 0.83541325]]
6. 正態分布的隨機矩陣在 Matlab和Numpy 中都用randn()函數來表示抽取標準正態分布的樣本。
註:既然是隨機數,無論產生多少個,都只能算是樣本,所謂期望,是對樣本數量足夠多的情況而言的。一般而言,樣本數量越大,其均值越接近0,但並不是說就一定為0。
【例1】列出4階正態分布的隨機矩陣。
Matlab:
randn(m,n)產生一個期望為0,標準差為1且服從正態分布的隨機矩陣,其中為行數,為列數,若為方陣,則以randn(n)表示。
>> A = randn(4);
>> disp(A)
0.5611 -0.6045 -0.0025 -1.1567
-1.1985 -0.1034 0.1916 0.6170
-1.0359 1.1587 -0.4981 0.0227
-0.5967 -1.8604 0.9566 0.8366
>> A=randn(100000,1);
>> histogram(A)
Python:
numpy.random.randn(d0, d1, ..., dn)從均值為0,標準差為1的標準正態分布中抽取樣本。import numpy as np
import matplotlib.pyplot as plt
A = np.random.randn(4, 4)
print(A)
# [[-1.6652191 2.57166227 -2.12784124 1.52365121]
# [-1.03609184 -0.32386994 0.45424631 0.58238759]
# [-0.02458478 -1.69242129 0.01512539 0.8165994 ]
# [-0.39558196 -1.62699892 -0.5198507 2.29518816]]
A = np.random.randn(100000, 1)
plt.hist(A, bins=20)
plt.show()
總結以上總結的不一定全,但先有個框架等後面在實踐的過程中慢慢補充。今天就到這裡吧。See You!
後臺回復「搜搜搜」,隨機獲取電子資源!
歡迎關注,請掃描二維碼: