前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >NumPy快速入门-- Less 基础/线性代数

NumPy快速入门-- Less 基础/线性代数

作者头像
Michael阿明
发布2021-02-20 14:14:05
发布2021-02-20 14:14:05
47900
代码可运行
举报
运行总次数:0
代码可运行

1. 广播(Broadcasting)规则

Broadcasting允许通用函数以有意义的方式处理具有不完全相同形状的输入。

  • 第一个规则,如果所有输入数组不具有相同数量的维度,则“1”将被重复地添加到较小数组的形状,直到所有数组具有相同数量的维度
  • 第二个规则,确保沿着特定维度具有大小为1的数组表现得好像它们具有沿着该维度具有最大形状的数组的大小。假定数组元素的值沿“Broadcasting”数组的该维度相同。

在应用广播规则之后,所有阵列的大小必须匹配。

(以上不是特别明白)

2. 使用索引数组索引

代码语言:javascript
代码运行次数:0
复制
>>> a = np.arange(12)**2
>>> a
array([  0,   1,   4,   9,  16,  25,  36,  49,  64,  81, 100, 121],
      dtype=int32)
>>> i = np.array([1,1,3,8,5])
>>> a[i]
array([ 1,  1,  9, 64, 25], dtype=int32)
>>> 
>>> j = np.array([[3,4],[9,7]])
>>> a[j]					# a[j] 形状与 j 一致
array([[ 9, 16],
       [81, 49]], dtype=int32)
  • 当被索引的数组 a 是一个多维数组,单个索引数组指的是 a第一个维度。以下示例通过使用调色板将标签图像转换为彩色图像来作为举例。
代码语言:javascript
代码运行次数:0
复制
>>> palette = np.array([[0,0,0],[255,0,0],[0,255,0],[0,0,255],[255,255,255]])
>>> image = np.array([[0,1,2,0],[0,3,4,0]])
>>> palette[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]]])
  • 也可以给出多个维度的索引。每个维度的索引数组必须具有相同的形状。
代码语言:javascript
代码运行次数:0
复制
>>> 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 必须有相同的shape
array([[ 2,  5],
       [ 7, 11]])
>>> 
>>> a[i,2]
array([[ 2,  6],
       [ 6, 10]])
>>> 
>>> a[:,j]		#行和列的组合(0行所有的j...)
array([[[ 2,  1],
        [ 3,  3]],

       [[ 6,  5],
        [ 7,  7]],

       [[10,  9],
        [11, 11]]])
  • 当然,我们可以把 ij 放在一个序列中(比如一个列表), 然后用列表进行索引。
代码语言:javascript
代码运行次数:0
复制
>>> l = [i,j]
>>> a[l]
array([[ 2,  5],		# 等效于 a[i,j]
       [ 7, 11]])
  • 不能将 ij 放入一个数组中,因为这个数组将被解释为索引第一个维度。
代码语言:javascript
代码运行次数:0
复制
>>> s = np.array([i,j])
>>> s
array([[[0, 1],
        [1, 2]],

       [[2, 1],
        [3, 3]]])
>>> a[s]
Traceback (most recent call last):
  File "<pyshell#36>", line 1, in <module>
    a[s]
IndexError: index 3 is out of bounds for axis 0 with size 3
>>> a[tuple(s)]		# 与 a[i,j] 一样
array([[ 2,  5],
       [ 7, 11]])
  • 索引数组的另一个常见用途是搜索时间相关序列的最大值
代码语言:javascript
代码运行次数:0
复制
>>> time_max = time[idx]
>>> data_max = data[idx, range(data.shape[1])]	# => data[idx[0],0], data[idx[1],1]...
>>> time_max
array([ 82.5 ,  20.  , 113.75,  51.25])
>>> data_max
array([0.98935825, 0.84147098, 0.99060736, 0.6569866 ])
>>> np.all(data_max == data.max(axis=0))
True
  • 还可以使用数组索引作为目标来赋值
代码语言:javascript
代码运行次数:0
复制
>>> a = np.arange(5)
>>> a
array([0, 1, 2, 3, 4])
>>> a[[1,2,3]] = 0
>>> a
array([0, 0, 0, 0, 4])
  • 当索引列表包含重复时,赋值多次,只留最后一个值
代码语言:javascript
代码运行次数:0
复制
>>> a = np.arange(5)
>>> a[[0,0,2]] = [1,2,3]		# a[0]=1,a[0]=2,a[2]=3
>>> a
array([2, 1, 3, 3, 4])
  • 使用Python的 += 构造要小心,可能得不到你想要的效果
代码语言:javascript
代码运行次数:0
复制
>>> a
array([0, 1, 2, 3, 4])
>>> a[[0,0,2]] += 1		# a[0] 只加了1次
>>> a
array([1, 1, 3, 3, 4])

即使0在索引列表中出现2次,第0个元素只会增加一次。这是因为Python要求“a + = 1”等同于“a = a + 1”

3. 使用布尔值作为数组索引

使用布尔值作为索引时,我们明确地选择数组中的哪些元素我们想要的,哪些不是。

我们可以想到的布尔索引最自然的方式是使用与原始数组具有相同形状的布尔数组

代码语言:javascript
代码运行次数:0
复制
>>> a = np.arange(12).reshape(3,4)
>>> a
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])
>>> b = a > 4
>>> b
array([[False, False, False, False],
       [False,  True,  True,  True],
       [ True,  True,  True,  True]])
>>> a[b]		# 取出true的元素
array([ 5,  6,  7,  8,  9, 10, 11])
  • 此属性在赋值时非常有用
代码语言:javascript
代码运行次数:0
复制
>>> a[b] = 0		# a中大于4的元素赋值为0
>>> a
array([[0, 1, 2, 3],
       [4, 0, 0, 0],
       [0, 0, 0, 0]])

使用布尔索引生成 Mandelbrot 集的图像(不懂)

代码语言:javascript
代码运行次数:0
复制
import numpy as np
import matplotlib.pyplot as plt
def mandelbrot(h,w,maxit=20):
	# Returns an image of the Mandelbrot fractal of size (h,w)
	y,x = np.ogrid[-1.4:1.4:h*1j, -2:0.8:w*1j]
	c = x+y*1j
	z = c
	divtime = maxit + np.zeros(z.shape, dtype=int)

	for i in range(maxit):
		z = z**2 + c
		diverge = z*np.conj(z) > 2**2
		div_now = diverge & (divtime==maxit)
		divtime[div_now] = i
		z[diverge] = 2

	return divtime

plt.imshow(mandelbrot(400,400))
plt.show()

第二种使用布尔索引的方法更类似于整数索引; 对于数组的每个维度,给出一个一维布尔数组,选择我们想要的切片

代码语言:javascript
代码运行次数:0
复制
>>> a = np.arange(12).reshape(3,4)
>>> b1 = np.array([False,True,True])             # 第一轴长度3=a中的3
>>> b2 = np.array([True,False,True,False])       # 第二轴长度4=a中的4
>>>
>>> a[b1,:]                                   # 选择b1内true的行
array([[ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])
>>>
>>> a[b1]                                     # 同上
array([[ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])
>>>
>>> a[:,b2]                                   # 选择b2内true的列
array([[ 0,  2],
       [ 4,  6],
       [ 8, 10]])
>>>
>>> a[b1,b2]                                  # 奇怪的结果!!!
array([ 4, 10])

1D布尔数组的长度必须与你要切片的维度(或轴)的长度一致。b1 是rank为1的数组,其长度为3( a 中行的数量), b2 (长度4)适合于索引 a 的第二个rank(列)。

4. ix_()函数

可以使用 ix_ 函数来组合不同的向量以获得每个n-uplet的结果。例如,如果要计算从向量a、b和c中的取得的所有三元组的所有a + b * c

代码语言:javascript
代码运行次数:0
复制
>>> 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

以下版本的reduce的优点是它使用Broadcasting规则,以避免创建参数数组输出的大小乘以向量的数量。

代码语言:javascript
代码运行次数:0
复制
>>> def func(f, *vectors):
	vs = np.ix_(*vectors)
	r = f.identity
	for v in vs:
		r = f(r,v)
	return r

>>> func(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]]])

5. 线性代数 简单数组操作

代码语言:javascript
代码运行次数:0
复制
>>> a = np.array([[1.0,2.0],[3.0,4.0]])
>>> print(a)
[[1. 2.]
 [3. 4.]]
>>> a.transpose()		#转置
array([[1., 3.],
       [2., 4.]])
>>> np.linalg.inv(a)		#矩阵求逆
array([[-2. ,  1. ],
       [ 1.5, -0.5]])

>>> u = np.eye(2)	#对角线是1
>>> u
array([[1., 0.],
       [0., 1.]])
>>> j = np.array([[0.0,-1.0],[1.0,0.0]])
>>> np.dot(j,j)		#矩阵点积
array([[-1.,  0.],
       [ 0., -1.]])
>>> np.trace(u)
2.0
>>> y =  np.array([[5.0],[7.0]])
>>> np.linalg.solve(a,y)	# 求解矩阵方程
array([[-3.],
       [ 4.]])
>>> np.linalg.eig(j)
(array([0.+1.j, 0.-1.j]), array([[0.70710678+0.j        , 0.70710678-0.j        ],
       [0.        -0.70710678j, 0.        +0.70710678j]]))

6. 技巧和提示

6.1 “自动”整形

可以省略一个维度的尺寸,由其自动计算出来

代码语言:javascript
代码运行次数:0
复制
>>> a = np.arange(30)
>>> a.shape = 2,-1,3	# -1 表示自行推导,省略
>>> a.shape
(2, 5, 3)
>>> a
array([[[ 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]]])

6.2 矢量堆叠

column_stack,dstack,hstack,vstack

代码语言:javascript
代码运行次数:0
复制
>>> x = np.arange(0,10,2)	#array([0, 2, 4, 6, 8])
>>> y = np.arange(5)		#array([0, 1, 2, 3, 4])
>>> m = np.vstack([x,y])
>>> m
array([[0, 2, 4, 6, 8],
       [0, 1, 2, 3, 4]])
>>> xy = np.hstack([x,y])
>>> xy
array([0, 2, 4, 6, 8, 0, 1, 2, 3, 4])
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019/09/03 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 广播(Broadcasting)规则
  • 2. 使用索引数组索引
  • 3. 使用布尔值作为数组索引
  • 4. ix_()函数
  • 5. 线性代数 简单数组操作
  • 6. 技巧和提示
    • 6.1 “自动”整形
    • 6.2 矢量堆叠
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档