詳解numpy中array類型和matrix類型
Numpy中兩大重要類型array類型(N維數組ndarray)和矩陣類型matrix是很多基於Numpy數值計算的基礎,因此搞清楚兩者的關係是相當重要的, 特別是程序中混雜了這兩種類型,還夾帶着一些加減乘除的運算,那簡直有一種剪不斷理還亂的感覺,時不時腦袋就飛出一句話:尼瑪,程序又不聽話了!
咱們來捋一捋他們之間的關係, 首先Numpy中最重要的數據結構就是ndarry,簡寫爲array, 即N維數組,matrix其實也是一種array,只不過是維數爲2的特殊array,matrix的維數是固定的,這點和一般array顯著不同,即便加減乘除各種運算,matrix的維數不會發生變化,而array在運算時特別是歸約時維數會發生變化,一句話,matrix的維數永遠是2.
首先二者之間的轉化,array轉matrix用np.asmatrix或者np.matrix,matrix轉array用np.asarray或者matrix的A屬性
再看行向量或者列向量對應的array和matrix的實際維數
>>> a = np.array([1, 2, 3, 4, 5])
>>>> a
array([1, 2, 3, 4, 5])
>>> print(a.shape) # 顯示爲1維,表示a是一維array
(5L,)
>>> b = np.array([[1, 2, 3, 4, 5]]) # 與b = a.reshape(1,5)等價
>>> print(b);print(b.shape)
[[1 2 3 4 5]] # b是二維,shape=(1,5)
(1L, 5L)
>>> c = np.array([[1], [2], [3], [4], [5]]) # 與c = a.reshape(5,1)等價
>>> print(c);print(c.shape) # c是二維,shape=(5,1)
[[1]
[2]
[3]
[4]
[5]]
(5L, 1L)
再看看array的一維變多維,多維變一維。一維轉換爲多維用reshape
>>> a = np.arange(12)
>>> print(a);print(a.shape)
[ 0 1 2 3 4 5 6 7 8 9 10 11]
(12L,)
>>> b = a.reshape(3, 4);print(b);print(b.shape) # 從一維變爲二維
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]
(3L, 4L)
>>> c = a.reshape(2, 2, 3);print(c);print(c.shape) # 從一維變成三維
[[[ 0 1 2]
[ 3 4 5]]
[[ 6 7 8]
[ 9 10 11]]]
(2L, 2L, 3L)
>>> d = c.ravel();print(d);print(d.shape) # 多維轉一維,使用ravel函數,這個函數matrix也可以用,但是因爲matrix不管怎麼運算都是二維的(即shape數組長度爲2),所以matrix使用這個函數就是將二維矩陣M×N壓扁成一行形成1×K(K爲M和N的乘積)的二維矩陣
[ 0 1 2 3 4 5 6 7 8 9 10 11]
(12L,)
array中的很多函數(ufunc)運算都是元素級的,即函數針對array的每個元素進行處理,而matrix中的是根據矩陣的定義進行整體處理的
>>> a = np.array([1, 2, 3])
>>> b = np.array([4, 5, 6])
>>> c = a + b;print(c) # 運算爲元素級
[5 7 9]
>>> d = a - b;print(d) # 運算爲元素級
[-3 -3 -3]
>>> e = a * b;print(e) # 運算爲元素級
[ 4 10 18]
>>> f = a**2;print(f) # 運算爲元素級
[1 4 9]
如果想要array實現A和B矩陣式相乘,則要用np.dot(A,B)或者A.dot(B)
對於A和B都是一維的向量進行矩陣式相乘,最後得到的是一個數
>>> a = np.array([1, 2, 3])
>>> b = np.array([1, 2, 3])
>>> c = a.dot(b);print(c);print(c.shape);print(type(c))
14
() # 由於最後結果是一個數值,不是array,自然沒有shape屬性了
<type 'numpy.int32'>
>>> d = b.dot(a);print(d) # d與c完全一樣
14
# 這是二者都是一維的比較特殊的情況,如果A(m×n)或者B(p×q)大於一維,則np.dot(A,B)必須遵守矩陣乘法規則,即n必須與p相等
>>> a = np.array([[1, 2, 3], [1, 1, 1]]);b = np.array([1, 2, 3]);print(a.shape);
print(b.shape);c = a.dot(b);print(c);print(c.shape)
(2L, 3L)
(3L,)
[14 6]
(2L,)
>>> a = np.array([[1, 2, 3], [1, 1, 1]]);b = np.array([[1, 1], [2, 2] ,[3, 3]]);
print(a.shape);print(b.shape);c = a.dot(b);print(c);print(c.shape)
(2L, 3L)
(3L, 2L)
[[14 14]
[ 6 6]]
(2L, 2L)
對於matrix的加減乘除,都是按照矩陣的定義進行的,當然運算結果都是二維的
>>> a = np.mat([[1, 2, 3], [4, 5, 6]]);print(a);print(a.shape)
[[1 2 3]
[4 5 6]]
(2L, 3L)
>>> b = np.mat([[4, 5, 6], [7, 8, 9]]);print(b);print(b.shape)
[[4 5 6]
[7 8 9]]
(2L, 3L)
>>> c = a + b;print(c);print(c.shape) # 運算爲矩陣定義的加法
[[ 5 7 9]
[11 13 15]]
(2L, 3L)
>>> c = a - b;print(c);print(c.shape) # 運算爲矩陣定義的減法
[[-3 -3 -3]
[-3 -3 -3]]
(2L, 3L)
>>> d = np.matrix([[1, 4], [2, 5], [3, 6]]);print(d);print(d.shape)
[[1 4]
[2 5]
[3 6]]
(3L, 2L)
>>> e = a * d;print(e);print(e.shape) # 運算爲矩陣定義的乘法
[[14 32]
[32 77]]
(2L, 2L)
>>> f = np.matrix([[1, 2], [3, 4]]);g = f**2;print(f);print(g) # 運算爲矩陣乘法g = f * f
[[1 2]
[3 4]]
[[ 7 10]
[15 22]]
matrix應用ravel函數得到的仍然是matrix,形狀爲1×N
>>> print(g.ravel());print(g.shape)
[[ 7 10 15 22]]
(1L, 4L)
# 如果想得到一維的array,可以使用屬性A1
>>> i = g.A1;print(i);print(i.shape)
[ 7 10 15 22]
(4L,)
對於轉置,array和matrix都可以用transpose函數,matrix還可以直接使用T屬性
>>> a = np.arange(6).reshape(2, 3)
>>> a
array([[0, 1, 2],
[3, 4, 5]])
>>> print(a.transpose())
[[0 3]
[1 4]
[2 5]]
>>> b = np.matrix(a)
>>> b
matrix([[0, 1, 2],
[3, 4, 5]])
>>> b.transpose()
matrix([[0, 3],
[1, 4],
[2, 5]])
# 對於一維的array,談不上轉置,使用transpose函數後結果還是其自己
>>> a = np.array([1, 2, 3, 4]);print(a.shape)
(4L,)
>>> a
array([1, 2, 3, 4])
>>> b = a.transpose();print(b.shape)
(4L,)
>>> b
array([1, 2, 3, 4])
總結:一定要認識到matrix是二維的,一定要搞清楚你使用的array是幾維的,進行矩陣運算時,是否滿足矩陣運算的各維要求如果不滿足,應該如何快速度進行轉化