详解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是几维的,进行矩阵运算时,是否满足矩阵运算的各维要求如果不满足,应该如何快速度进行转化