Numpy矩阵操作总结

numpy数据类型转换

numpy数据类型转换需要调用方法astype(),不能直接修改dtype。调用astype返回数据类型修改后的数据,但是源数据的类型不会变,需要进一步对源数据的赋值操作才能改变。例如

1
2
3
4
5
6
7
8
9
10
11
12
>>> a=np.array([1.1, 1.2])
>>> a.dtype
dtype('float64')
>>> a.astype(np.int16)
array([1, 1], dtype=int16)
>>> a.dtype
dtype('float64') #a的数据类型并没有变
>>> a=a.astype(np.int16) #赋值操作后a的数据类型变化
>>> a.dtype
dtype('int16')
>>> a
array([1, 1], dtype=int16)

直接修改dtype数据会强制用新数据类型表示,并没有转换,因此输出错误数据

1
2
3
4
5
6
7
8
9
10
>>> a=np.array([1.1, 1.2])
>>> a.dtype
dtype('float64')
>>> a.dtype=np.int16
>>> a.dtype
dtype('int16')
>>> a
array([-26214, -26215, -26215, 16369, 13107, 13107, 13107, 16371], dtype=int16)
#原来float64相当于4个int16的位宽,这样强制转换后会将他们直接拆开成4个数,
#因此原来的两个float64成了8个int16

numpy索引

使用索引数组进行索引

1
2
3
4
5
6
7
8
9
>>> a = np.arange(12)**2                       # the first 12 square numbers
>>> i = np.array( [ 1,1,3,8,5 ] ) # an array of indices
>>> a[i] # the elements of a at the positions i
array([ 1, 1, 9, 64, 25])
>>>
>>> j = np.array( [ [ 3, 4], [ 9, 7 ] ] ) # a bidimensional array of indices
>>> a[j] # 生成的数组形状和j一样
array([[ 9, 16],
[81, 49]])

如果被索引的数组a是多维的,那么索引数组将引用数组a的第一维

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
>>> palette = np.array( [ [0,0,0],                # black
... [255,0,0], # red
... [0,255,0], # green
... [0,0,255], # blue
... [255,255,255] ] ) # white
>>> image = np.array( [ [ 0, 1, 2, 0 ], # each value corresponds to a color in the palette
... [ 0, 3, 4, 0 ] ] )
>>> palette[image] # the (2,4,3) color image
array([[[ 0, 0, 0],
[255, 0, 0],
[ 0, 255, 0],
[ 0, 0, 0]],
[[ 0, 0, 0],
[ 0, 0, 255],
[255, 255, 255],
[ 0, 0, 0]]])

也可以给出多于1维的索引。针对每个维的索引数组必须形状相同。

1
2
3
4
5
6
7
8
9
10
11
12
13
>>> a = np.arange(12).reshape(3,4)
>>> a
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
>>> i = np.array( [ [0,1], # 第一个轴的索引
... [1,2] ] )
>>> j = np.array( [ [2,1], # 第二个轴的索引
... [3,3] ] )
>>>
>>> a[i,j] # i 和 j形状必须相同
array([[ 2, 5],
[ 7, 11]])

解释一下这个过程:a[i,j]的机制是数组i和数组j相同位置的对应数字两两组成一对索引,然后用这对索引在数组a中进行取值。比如数组i的索引(0,0)处的值为0,数组j的索引(0,0)处的值为2,它们组成的索引对是(0,2),在数组a中对应的值是2。在这样的机制下,理所当然要求数组i和数组j需要有相同的形状,否则将无法取得相应的索引对。又因为数组i和数组j分别是数组a的两个轴(axis)上的索引数组,所以最终的结果也就和数组i/j的形状相同。

1
2
3
>>> a[i,2]
array([[ 2, 6],
[ 6, 10]])

上面的过程是:数组i是数组a第一个轴的索引数组,a[i,2]中的数字2表示数组a的第二个轴的索引,数组i中的每个数字都与2组成索引对,也就是([ [(0,2), (1,2)], [(1,2),(2,2)] ]),然后依据这些索引对和相应的形状取数组a中的值。

1
2
3
4
5
6
7
>>> a[:,j]
array([[[ 2, 1],
[ 3, 3]],
[[ 6, 5],
[ 7, 7]],
[[10, 9],
[11, 11]]])

上面的过程是:对数组a第一个轴进行完整切片,得到(0,1,2),然后每个值都与数组j中的元素两两组成索引对,也就是组成3个二维索引对,然后根据索引对取数组a中的值。

自然,我们也可以将ij放入一个序列(比如一个列表)中,然后用这个序列进行索引。

1
2
3
4
>>> l = [i,j]
>>> a[l] # 等价于 a[i,j]
array([[ 2, 5],
[ 7, 11]])

但是,我们不能把ij组成大数组后再去对数组a进行索引,因为根据前面的内容,我们知道,用1个索引数组(不同于多个索引)对另一个数据索引时,索引数组中的元素都被解释成数组a第一维的索引。

1
2
3
4
5
6
7
8
9
10
11
12
13
>>> s = np.array( [i,j] )
>>> s
array([[[0, 1],
[1, 2]],

[[2, 1],
[3, 3]]])
>>> s.shape
(2, 2, 2)
>>> a[s]
Traceback (most recent call last):
File "<stdin>", line 1, in ?
IndexError: index (3) out of range (0<=index<=2) in dimension 0

上面的错误信息很明确地指出:数组a的第一维索引最大为2,而数组s中出现了3,超出了索引范围。也就是说,出错的根本原因是索引超出了范围,而不是a[s]语法本身有问题。可以自己试验来验证。

1
2
3
>>> a[tuple(s)]                                # 等价于a[i,j]
array([[ 2, 5],
[ 7, 11]])

可以利用数组索引对数组赋值。

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

但是,如果索引列表有重复值,赋值的话也会多次赋值,以最后一次赋值为准:

1
2
3
4
>>> a = np.arange(5)
>>> a[[0,0,2]]=[1,2,3]
>>> a
array([2, 1, 3, 3, 4])

看起来很合理,但要小心,如果你想要使用Python的+=运算,结果可能大出所料:

1
2
3
4
>>> a = np.arange(5)
>>> a[[0,0,2]]+=1
>>> a
array([1, 1, 3, 3, 4])

尽管索引列表中0出现了2次,0号元素却只增加了1。

使用布尔值数组进行索引

使用布尔索引最自然的方式是布尔值数组与原数组有相同的形状:

1
2
3
4
5
6
7
8
>>> a = np.arange(12).reshape(3,4)
>>> b = a > 4
>>> b # b is a boolean with a's shape
array([[False, False, False, False],
[False, True, True, True],
[ True, True, True, True]], dtype=bool)
>>> a[b] # 选中的元素组成一维数组
array([ 5, 6, 7, 8, 9, 10, 11])

这个性质很适合用来给元素重新赋值:

1
2
3
4
5
>>> a[b] = 0                                   # All elements of 'a' higher than 4 become 0
>>> a
array([[0, 1, 2, 3],
[4, 0, 0, 0],
[0, 0, 0, 0]])

使用布尔索引的第二种方式比较类似于整数索引;对数组每一维,我们提供一维的布尔数组来选择我们想要的值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
>>> a = np.arange(12).reshape(3,4)
>>> a
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
>>> b1 = np.array([False,True,True]) # first dim selection
>>> b2 = np.array([True,False,True,False]) # second dim selection
>>>
>>> a[b1,:] # 选择第2、3行的所有列
array([[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
>>>
>>> a[b1] # same thing
array([[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
>>>
>>> a[:,b2] # selecting columns
array([[ 0, 2],
[ 4, 6],
[ 8, 10]])
>>>
>>> a[b1,b2] # 奇怪的事发生了
array([ 4, 10])

注意一维布尔数组的长度必须和你要切片的维(或axis)的长度相同。在上面的例子中,b1是长度为2的一维数组,b2是长度为2,适合索引数组a的二维索引,两个值的下标为(1,0)、(2,2)

ix_()函数

ix_ 函数可以合并不同的向量来获得各个n元组的结果。

举个例子,如果你想要计算三个向量两两组合的结果$a+bc$,也就是说要计算$\sum_{i=0}(a_i+\prod_{j=0,k=0}b_jc_k)$,在下面的例子中,$a,b,c$长度分别为4,3,5,这样算下来,最终的结果应该有$60(435)$个。数据量少的时候可以手工算,如果数据量大的话,ix_函数就排上用场了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
>>> a = np.array([2,3,4,5])
>>> b = np.array([8,5,4])
>>> c = np.array([5,4,6,8,3])
>>> ax,bx,cx = np.ix_(a,b,c)
>>> ax
array([[[2]],
[[3]],
[[4]],
[[5]]])
>>> bx
array([[[8],
[5],
[4]]])
>>> cx
array([[[5, 4, 6, 8, 3]]])
>>> ax.shape, bx.shape, cx.shape
((4, 1, 1), (1, 3, 1), (1, 1, 5))
>>> result = ax+bx*cx
>>> result
array([[[42, 34, 50, 66, 26],
[27, 22, 32, 42, 17],
[22, 18, 26, 34, 14]],
[[43, 35, 51, 67, 27],
[28, 23, 33, 43, 18],
[23, 19, 27, 35, 15]],
[[44, 36, 52, 68, 28],
[29, 24, 34, 44, 19],
[24, 20, 28, 36, 16]],
[[45, 37, 53, 69, 29],
[30, 25, 35, 45, 20],
[25, 21, 29, 37, 17]]])
>>> result[3,2,4]
17
>>> a[3]+b[2]*c[4]
17

显然,最后的结果数组result包含了所有可能的数值,且位置和原数组一一对应,比如a[2]+b[0]*c[4]正是result[2,0,4]

还可以像下面一样来执行同样的功能:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
>>> def ufunc_reduce(ufct, *vectors):
... vs = np.ix_(*vectors)
... r = ufct.identity
... for v in vs:
... r = ufct(r,v)
... return r
and then use it as:

>>>
>>> ufunc_reduce(np.add,a,b,c)
array([[[15, 14, 16, 18, 13],
[12, 11, 13, 15, 10],
[11, 10, 12, 14, 9]],
[[16, 15, 17, 19, 14],
[13, 12, 14, 16, 11],
[12, 11, 13, 15, 10]],
[[17, 16, 18, 20, 15],
[14, 13, 15, 17, 12],
[13, 12, 14, 16, 11]],
[[18, 17, 19, 21, 16],
[15, 14, 16, 18, 13],
[14, 13, 15, 17, 12]]])

list索引

1
2
3
4
5
import numpy as np
time_steps,vocab_size = 5,8
batch_in = np.zeros([time_steps, vocab_size])
b_ = [0,2,5,3,7]
batch_in[range(time_steps), b_] = 1

取出range(time_steps)中的一个值,再取出b_[:-1]中的一个值;以这两个值为下标置1。b_中的每一个取值均在[0,vocab_size-1]之间。

结果:

再比如一个简单的例子:

1
2
3
4
5
6
In[17]: a = [1,4,5,6,9,6,7]
In[18]: b = [0,1,5]
In[20]: a = np.array(a)
In[21]: a[b]
Out[21]:
array([1, 4, 6])

求和

求和使用np.sum()函数,具体用法如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
import numpy as np
a = np.array([[1,2,3],[4,5,6]])

a
Out[7]:
array([[1, 2, 3],
[4, 5, 6]])

np.sum(a, axis=0)
Out[8]: array([5, 7, 9])

np.sum(a, axis=1)
Out[9]: array([ 6, 15])

分析:np.sum(a, axis),其中的axis为在哪一个维度上求和,结果为将哪一个维度消失。例如,a的维度为(2,3),当np.sum(a, axis=0)的时候,按列求和,让axis=0上的2维度消失,结果为array([5, 7, 9]),维度为(3,)。可以看到维度2已经消失了。当np.sum(a, axis=1)的时候,按行求和,让axis=1上的3维度消失,结果为array([6,15]),维度为(2,)。可以看到维度3已经消失了。

如果分不清axis的作用,只需要记住,这个数字为a时,原始数据的第a个维度消失。

均值

mean()函数功能:求取均值

经常操作的参数为axis,以m * n矩阵举例:

  • axis 不设置值,对m*n个数求均值,返回一个实数
  • axis = 0:压缩行,对各列求均值,返回 1* n 矩阵
  • axis =1 :压缩列,对各行求均值,返回 m *1 矩阵

举例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
>>>  import numpy as np

>>> num1 = np.array([[1,2,3],[2,3,4],[3,4,5],[4,5,6]])
>>> now2 = np.mat(num1)
>>> now2
matrix([[1, 2, 3],
[2, 3, 4],
[3, 4, 5],
[4, 5, 6]])


>>> np.mean(now2) # 对所有元素求均值
3.5

>>> np.mean(now2,0) # 压缩行,对各列求均值
matrix([[ 2.5, 3.5, 4.5]])

>>> np.mean(now2,1) # 压缩列,对各行求均值
matrix([[ 2.],
[ 3.],
[ 4.],
[ 5.]])

转置

1
2
3
4
5
from numpy import *
import numpy as np
>>> c = [[1,2,5],[4,5,8]]
>>> print c
[[1, 2, 5], [4, 5, 8]]

先mat,然后转置T

1
2
3
4
>>> print mat(c).T
[[1 4]
[2 5]
[5 8]]

或者:先转为array,然后T(最好不用这个)

1
2
3
4
5
6
7
>>> d = np.array(c)
>>> print d
[[1 2 5] [4 5 8]]
>>> print d.T
[[1 4]
[2 5]
[5 8]]

求逆

用mat转为numpy.matrix以后,然后用I

1
2
3
4
5
>>> a = [[1,3,4],[2,5,9],[4,9,8]]
>>> print mat(a).I
[[-3.72727273 1.09090909 0.63636364]
[ 1.81818182 -0.72727273 -0.09090909]
[-0.18181818 0.27272727 -0.09090909]]

但是对于numpy.array,是没有I的函数的。

1
2
3
4
>>> print np.array(a).I
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'numpy.ndarray' object has no attribute 'I'

若要想使用numpy.array,需要用到numpy.linalg.inv

1
2
3
4
5
6
7
import numpy as np
a = np.array([[1,3,4],[2,5,9],[4,9,8]])
print(np.linalg.inv(a))
# 输出结果
[[-3.72727273 1.09090909 0.63636364]
[ 1.81818182 -0.72727273 -0.09090909]
[-0.18181818 0.27272727 -0.09090909]]

当矩阵的行列式等于零的时候,矩阵没有逆,这个时候可以使用numpy.linalg.pinv其伪逆:

1
2
3
4
5
6
7
8
9
import numpy as np
b = np.array([[1, -1], [-1, 1]])
# print('inv:\n', np.linalg.inv(b)) # error
print('pinv:\n', np.linalg.pinv(b))

# 输出结果
pinv:
[[ 0.25 -0.25]
[-0.25 0.25]]

当矩阵的逆存在时,可以使用numpy.linalg.pinv以及numpy.linalg.inv,此时两者的运行结果相同:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
a = np.array([[1, -1, 3], [2, -1, 4], [-1, 2, -4]])
print('inv:\n', np.linalg.inv(a))
print('pinv:\n', np.linalg.pinv(a))

# 输出结果
inv:
[[-4. 2. -1.]
[ 4. -1. 2.]
[ 3. -1. 1.]]
pinv:
[[-4. 2. -1.]
[ 4. -1. 2.]
[ 3. -1. 1.]]

# 当然也可以用pytorch
aa = torch.from_numpy(a).float()
print(torch.inverse(aa))
# 输出结果
tensor([[-4.0000, 2.0000, -1.0000],
[ 4.0000, -1.0000, 2.0000],
[ 3.0000, -1.0000, 1.0000]])

numpy的列操作

numpy类型去掉一列(例子中为倒数第一列):

1
cut_data = np.delete(mydata, -1, axis=1)

numpy按类标取出:

1
2
3
dataone = list(d for d in raw_data[:] if d[mark_line] == 0)
datatwo = list(d for d in raw_data[:] if d[mark_line] == 1)
datathree = list(d for d in raw_data[:] if d[mark_line] == 2)

取出一列数据:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
a = np.random.randint(0,10,(3,5))

a
Out[7]:
array([[9, 0, 9, 5, 6],
[7, 2, 6, 8, 0],
[3, 6, 7, 9, 1]])

# 取出第一列
a[:,0]
Out[19]: array([9, 7, 3])

np.shape(a[:,0])
Out[6]: (3,)

# 转换维度
b = np.expand_dims(a[:, 0], axis=1)

b
Out[9]:
array([[2],
[0],
[3]])

np.shape(b)
Out[10]: (3, 1)

矩阵拼接

list先转化为list形式,然后用mat转为矩阵,再用 c = np.hstack((a,b)) 水平组合, d = np.vstack((a,b)) 垂直组合, np.dstack深度组合。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
>>> a = [[1,2,3],[4,5,6]]
>>> b = [[11,22,33],[44,55,66]]
>>> a_a = mat(a)
>>> b_b = mat(b)
>>> print a_a
[[1 2 3]
[4 5 6]]
>>> print b_b
[[11 22 33]
[44 55 66]]
>>> c = np.hstack((a,b))
>>> d = np.vstack((a,b))
>>> print c
[[ 1 2 3 11 22 33]
[ 4 5 6 44 55 66]]
>>> print d
[[ 1 2 3]
[ 4 5 6]
[11 22 33]
[44 55 66]]

a = np.array([[1, 2], [3, 4]])
b = np.array([[5, 6], [7, 8]])
tmp = np.dstack((a, b))

tmp
Out[4]:
array([[[1, 5],
[2, 6]],

[[3, 7],
[4, 8]]])

np.shape(tmp)
Out[5]: (2, 2, 2)

矩阵排序

list也可以这样做,只是返回值仍然是一个排好序的list

1
2
3
4
 a = [[4,1,5],[1,2,5]]
>>> c = sorted(a,key = operator.itemgetter(1),reverse = True)
>>> print c
[[1, 2, 5], [4, 1, 5]]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import operator
a = [[4,1,5],[1,2,5]]
>>> b = np.array(a)
>>> print b
[[4 1 5]
[1 2 5]]
## 注意必须在b前面也加上c变量用于记录位置,否则的话b是不变的
>>> c = sorted(b,key = operator.itemgetter(1),reverse = True) #按照第二列进行排序,并按高到低排序
[array([1, 2, 5]), array([4, 1, 5])]
>>> sorted(b,key = operator.itemgetter(0),reverse = True)
[array([4, 1, 5]), array([1, 2, 5])]
>>> sorted(b,key = operator.itemgetter(0),reverse = True)
[array([4, 1, 5]), array([1, 2, 5])]
>>> c = sorted(a ,key = operator.itemgetter(1),reverse = True) # list 也可以排序,但是里面的类型不同
>>> print c
[[1, 2, 5], [4, 1, 5]]

判断两个矩阵是不是相等

注意不能直接用 == 号

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
>>> a = [[1,2,3],[4,5,6],[7,8,9]]
>>> b = [[1,2,3],[4,5,6],[7,8,9]]
>>> c = np.array(a)
>>> d = np.array(b)
>>> print c
[[1 2 3]
[4 5 6]
[7 8 9]]
>>> print d
[[1 2 3]
[4 5 6]
[7 8 9]]
>>> if c == d:
... print 'yes'
...
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
>>> if (c == d).all():
... print 'yes'
...
yes

若还是报错的话,则使用np.close(a, b):

1
2
3
4
5
6
7
8
9
10
11
12
>>> a = [array([ 4.90312812,  0.31002876, -3.41898514]), array([ 16.02316243,   1.51557803,  82.28424555])]
>>> b = [array([ 1.57286264, 2.1289384 , -1.57890685]), array([ 10.22050379, 6.02365441, 48.91208021])]
>>> a == b
Traceback (most recent call last):
File "<input>", line 1, in <module>
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
>>> (a == b).all()
Traceback (most recent call last):
File "<input>", line 1, in <module>
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
>>> np.allclose(a,b)
False

矩阵的copy问题

当用copy()的时候相当于另外开辟了一个空间存储这个变量与copy过来的值,否则的话仍然在以前变量的基础上修改!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
>>> a = [[1,2,3],[4,5,6],[7,8,9]]
>>> b = np.array(a)
>>> print b
[[1 2 3]
[4 5 6]
[7 8 9]]
>>> c = b.copy()
>>> c[1,1] = 100
>>> print c
[[ 1 2 3]
[ 4 100 6]
[ 7 8 9]]
>>> print b
[[1 2 3]
[4 5 6]
[7 8 9]]
>>> d = b
>>> d[1,1] = 99
>>> print d
[[ 1 2 3]
[ 4 99 6]
[ 7 8 9]]
>>> print b
[[ 1 2 3]
[ 4 99 6]
[ 7 8 9]]

numpy维度转换

numpy多维转一维

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#coding=utf-8
#anthor:ABian

import numpy as np

x=np.arange(3,5,0.2)
x=x.reshape(2,5)

print(x)
#ravel和flatten可以将数组降为一维,默认为行优先
print(x.ravel())
print(x.flatten())
#改为列优先
print(x.ravel('F'))
print(x.flatten('F'))
#二者差别,flatten返回的是拷贝,ravel是直接指向
x.ravel()[0]=10
print(x)
x.flatten()[9]=10#因为返回的是拷贝,输出以后能发现第十个数没有改变
print(x)

numpy一维转二维

例如:对于二维数组而言,(3,1)与(3,)是不同的

1
2
3
4
5
6
7
8
9
10
11
12
13
>>> a = [[1],[2],[3]]
>>> a = np.array(a)
>>> a
array([[1],
[2],
[3]])
>>> np.shape(a)
(3, 1)
>>> b = a[:,0]
>>> b
array([1, 2, 3])
>>> np.shape(a=b)
(3,)

expand_dims用法:

Examples:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
>>> x = np.array([1,2])
>>> x.shape
(2,)
>>> y = np.expand_dims(x, axis=0)
>>> y
array([[1, 2]])
>>> y.shape
(1, 2)
>>> y = np.expand_dims(x, axis=1) # Equivalent to x[:,newaxis]
>>> y
array([[1],
[2]])
>>> y.shape
(2, 1)

对称矩阵

判断是否为对阵矩阵

判断X矩阵是否为对称矩阵

1
np.allclose(X, X.T)

产生对称矩阵(对角线为0)

1
2
3
4
5
import numpy as np

X = np.random.rand(5 ** 2).reshape(5, 5)
X = np.triu(X)
X += X.T - np.diag(X.diagonal()) - np.diag(X.diagonal())

提取上三角,下三角,对角元素

若保留矩阵的维度,只要上三角或者下三角的元素,其余元素为0,可以采用下面方法。注意可以调节参数k来实现是否保留对角元素,k参数默认等于0。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
a = np.array([[1,2,3],[4,5,6],[7,8,9]])
>>> a
array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])

tri_upper_diag = np.triu(a, k=0)
>>> tri_upper_diag
array([[1, 2, 3],
[0, 5, 6],
[0, 0, 9]])

tri_upper_no_diag = np.triu(a, k=1)
>>> tri_upper_no_diag
array([[0, 2, 3],
[0, 0, 6],
[0, 0, 0]])

tri_lower_diag = np.tril(a, k=0)
>>> tri_lower_diag
array([[1, 0, 0],
[4, 5, 0],
[7, 8, 9]])

tri_lower_no_diag = np.tril(a, k=-1)
>>> tri_lower_no_diag
array([[0, 0, 0],
[4, 0, 0],
[7, 8, 0]])

# 提取对角元素
a.diagonal()
Out[3]: array([1, 5, 9])

要将上三角形值或者下三角形提取到平面矢量,您可以执行以下操作,注意可以调节参数k来实现是否保留对角元素,k参数默认等于0。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import numpy as np

a = np.array([[1,2,3],[4,5,6],[7,8,9]])
print(a)

#array([[1, 2, 3],
# [4, 5, 6],
# [7, 8, 9]])

a[np.triu_indices(3)]
# array([1, 2, 3, 5, 6, 9])

list(a[np.triu_indices(3)])
# [1, 2, 3, 5, 6, 9]

a[np.triu_indices(3, k=1)]
# array([2, 3, 6])

a[np.tril_indices(3)]
# array([1, 4, 5, 7, 8, 9])

a[np.tril_indices(3, k=-1)]
# array([4, 7, 8])

矩阵乘法

np.dot()

np.dot(A, B):对于二维矩阵,计算真正意义上的矩阵乘积,同线性代数中矩阵乘法的定义。对于一维矩阵,计算两者的内积。见如下Python代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import numpy as np

# 2-D array: 2 x 3
two_dim_matrix_one = np.array([[1, 2, 3], [4, 5, 6]])
# 2-D array: 3 x 2
two_dim_matrix_two = np.array([[1, 2], [3, 4], [5, 6]])

two_multi_res = np.dot(two_dim_matrix_one, two_dim_matrix_two)
print('two_multi_res: %s' %(two_multi_res))

# 1-D array
one_dim_vec_one = np.array([1, 2, 3])
one_dim_vec_two = np.array([4, 5, 6])
one_result_res = np.dot(one_dim_vec_one, one_dim_vec_two)
print('one_result_res: %s' %(one_result_res))

结果如下:

1
2
3
two_multi_res: [[22 28]
[49 64]]
one_result_res: 32

np.multiply()

np.multiply()用来实现对应元素相乘(element-wise product)。见如下Python代码:

1
2
3
4
5
6
7
8
9
import numpy as np

# 2-D array: 2 x 3
two_dim_matrix_one = np.array([[1, 2, 3], [4, 5, 6]])
another_two_dim_matrix_one = np.array([[7, 8, 9], [4, 7, 1]])

# 对应元素相乘 element-wise product
element_wise_2 = np.multiply(two_dim_matrix_one, another_two_dim_matrix_one)
print('element wise product: %s' % (element_wise_2))

结果如下:

1
2
element wise product: [[ 7 16 27]
[16 35 6]]

*

对于该运算,分为两种情况,若矩阵为numpy.array类型,则为矩阵元素相乘;若矩阵为numpy.matrix类型,则为矩阵相乘。另外若有一个为numpy.array类型而另外一个为numpy.matrix类型,则该运算也表示矩阵相乘。

见下面Python代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import numpy as np

# 2-D array: 2 x 3
two_dim_matrix_one = np.array([[1, 2, 3], [4, 5, 6]])
another_two_dim_matrix_one = np.array([[7, 8, 9], [4, 7, 1]])

# 对应元素相乘 element-wise product
element_wise = two_dim_matrix_one * another_two_dim_matrix_one
print('element wise product: %s' %(element_wise))

# 2-D array: 2 x 3
two_dim_matrix_one = np.matrix([[1, 2, 3], [4, 5, 6]])
another_two_dim_matrix_one = np.matrix([[7, 8], [9, 4] ,[7, 1]])
# 矩阵相乘
two_multi_res = np.dot(two_dim_matrix_one, another_two_dim_matrix_one)
print('two_multi_res: %s' %(two_multi_res))

# 2-D array: 2 x 3
two_dim_matrix_one = np.matrix([[1, 2, 3], [4, 5, 6]])
another_two_dim_matrix_one = np.array([[7, 8], [9, 4] ,[7, 1]])
# 矩阵相乘
two_multi_res = np.dot(two_dim_matrix_one, another_two_dim_matrix_one)
print('two_multi_res: %s' %(two_multi_res))

结果如下:

1
2
3
4
5
6
7
8
element wise product: [[ 7 16 27]
[16 35 6]]

two_multi_res: [[ 46 19]
[115 58]]

two_multi_res: [[ 46 19]
[115 58]]

np.where

首先强调一下,where()函数对于不同的输入,返回的只是不同的。

  1. 当数组是一维数组时,返回的值是一维的索引,所以只有一组索引数组
  2. 当数组是二维数组时,满足条件的数组值返回的是值的位置索引,因此会有两组索引数组来表示值的位置

例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
>>>b=np.arange(10)
>>>b
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>>np.where(b>5)
(array([6, 7, 8, 9], dtype=int64),)

>>>a=np.reshape(np.arange(20),(4,5))
>>>a
array([[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14],
[15, 16, 17, 18, 19]])
>>>np.where(a>10)
(array([2, 2, 2, 2, 3, 3, 3, 3, 3], dtype=int64),
array([1, 2, 3, 4, 0, 1, 2, 3, 4], dtype=int64))

对numpy标准库里的解释做一个介绍:numpy.where(condition[, x, y]) 基于条件condition,返回值来自x或者y. 如果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
>>> np.where([[True, False], [True, True]],
... [[1, 2], [3, 4]],
... [[9, 8], [7, 6]])
array([[1, 8],
[3, 4]])
>>>
>>> np.where([[0, 1], [1, 0]])
(array([0, 1]), array([1, 0]))
>>>
>>> x = np.arange(9.).reshape(3, 3)
>>> np.where( x > 5 )
(array([2, 2, 2]), array([0, 1, 2]))
>>> x[np.where( x > 3.0 )] # Note: result is 1D.
array([ 4., 5., 6., 7., 8.])
>>> np.where(x < 5, x, -1) # Note: broadcasting.
array([[ 0., 1., 2.],
[ 3., 4., -1.],
[-1., -1., -1.]])
Find the indices of elements of x that are in goodvalues.

>>>
>>> goodvalues = [3, 4, 7]
>>> ix = np.in1d(x.ravel(), goodvalues).reshape(x.shape)
>>> ix
array([[False, False, False],
[ True, True, False],
[False, True, False]], dtype=bool)
>>> np.where(ix)
(array([1, 1, 2]), array([0, 1, 1]))

# 又比如下面例子
>>> a = [[1,2,3],[4,5,6],[7,8,9]]
>>> b = np.array(a)
>>> print b
[[1 2 3]
[4 5 6]
[7 8 9]]
>>> np.where(b = 5)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: where() takes no keyword arguments
>>> np.where(5)
(array([0]),)
>>> np.where(b == 5)
(array([1]), array([1]))
>>> np.where(b == 6)
(array([1]), array([2]))

np.pad

对一维数组的填充

1
2
3
4
5
6
7
8
9
10
11
12
13
import numpy as np
arr1D = np.array([1, 1, 2, 2, 3, 4])
'''不同的填充方法'''
print 'constant: ' + str(np.pad(arr1D, (2, 3), 'constant'))
print 'edge: ' + str(np.pad(arr1D, (2, 3), 'edge'))
print 'linear_ramp: ' + str(np.pad(arr1D, (2, 3), 'linear_ramp'))
print 'maximum: ' + str(np.pad(arr1D, (2, 3), 'maximum'))
print 'mean: ' + str(np.pad(arr1D, (2, 3), 'mean'))
print 'median: ' + str(np.pad(arr1D, (2, 3), 'median'))
print 'minimum: ' + str(np.pad(arr1D, (2, 3), 'minimum'))
print 'reflect: ' + str(np.pad(arr1D, (2, 3), 'reflect'))
print 'symmetric: ' + str(np.pad(arr1D, (2, 3), 'symmetric'))
print 'wrap: ' + str(np.pad(arr1D, (2, 3), 'wrap'))

解释:

  • 第一个参数是待填充数组
  • 第二个参数是填充的形状,(2,3)表示前面两个,后面三个
  • 第三个参数是填充的方法

填充方法:

  • constant连续一样的值填充,有关于其填充值的参数。constant_values=(x, y)时前面用x填充,后面用y填充。缺参数是为0000。。。
  • edge用边缘值填充
  • linear_ramp边缘递减的填充方式
  • maximum, mean, median, minimum分别用最大值、均值、中位数和最小值填充
  • reflect, symmetric都是对称填充。前一个是关于边缘对称,后一个是关于边缘外的空气对称╮(╯▽╰)╭
  • wrap用原数组后面的值填充前面,前面的值填充后面
  • 也可以有其他自定义的填充方法

对多维数组的填充

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import numpy as np
arr3D = np.array([[[1, 1, 2, 2, 3, 4], [1, 1, 2, 2, 3, 4], [1, 1, 2, 2, 3, 4]],
[[0, 1, 2, 3, 4, 5], [0, 1, 2, 3, 4, 5], [0, 1, 2, 3, 4, 5]],
[[1, 1, 2, 2, 3, 4], [1, 1, 2, 2, 3, 4], [1, 1, 2, 2, 3, 4]]])
'''对于多维数组'''
print 'constant: \n' + str(np.pad(arr3D, ((0, 0), (1, 1), (2, 2)), 'constant'))
print 'edge: \n' + str(np.pad(arr3D, ((0, 0), (1, 1), (2, 2)), 'edge'))
print 'linear_ramp: \n' + str(np.pad(arr3D, ((0, 0), (1, 1), (2, 2)), 'linear_ramp'))
print 'maximum: \n' + str(np.pad(arr3D, ((0, 0), (1, 1), (2, 2)), 'maximum'))
print 'mean: \n' + str(np.pad(arr3D, ((0, 0), (1, 1), (2, 2)), 'mean'))
print 'median: \n' + str(np.pad(arr3D, ((0, 0), (1, 1), (2, 2)), 'median'))
print 'minimum: \n' + str(np.pad(arr3D, ((0, 0), (1, 1), (2, 2)), 'minimum'))
print 'reflect: \n' + str(np.pad(arr3D, ((0, 0), (1, 1), (2, 2)), 'reflect'))
print 'symmetric: \n' + str(np.pad(arr3D, ((0, 0), (1, 1), (2, 2)), 'symmetric'))
print 'wrap: \n' + str(np.pad(arr3D, ((0, 0), (1, 1), (2, 2)), 'wrap'))

numpy、list、mat区别

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
>>> print a
[[1, 3, 4], [2, 5, 9], [4, 9, 8]]
>>> print type(a)
<type 'list'>
>>> print np.array(a)
[[1 3 4]
[2 5 9]
[4 9 8]]
>>> print mat(a)
[[1 3 4]
[2 5 9]
[4 9 8]]
>>> print type(a[0])
<type 'list'>
>>> print type(np.array(a)[0])
<type 'numpy.ndarray'>
>>> print type(mat(a)[0])
<class 'numpy.matrixlib.defmatrix.matrix'>
>>> print np.array(a)[0,0]
1
>>> print mat(a)[0,0]

打印全部元素

添加下面语句即可。

1
set_printoptions(threshold='nan')

np.ascontiguousarray

返回连续内存空间的矩阵

1
2
3
4
5
>>> np.ascontiguousarray(x, dtype=np.float32)
array([[0., 1., 2.],
[3., 4., 5.]], dtype=float32)
>>> x.flags['C_CONTIGUOUS']
True

参考

NumPy之四:高级索引和索引技巧
python 的numpy库中的mean()函数用法
提取numpy矩阵的上三角或下三角部分
用Numpy求逆矩阵?

------ 本文结束------
坚持原创技术分享,您的支持将鼓励我继续创作!

欢迎关注我的其它发布渠道