Numpy库:它提供了高性能的多维数组对象,以及相关工具。
数组array
一个numpy数组是一个由不同数值组成的网格。网格中的数据都是同一种数据类型,可以通过非负整型数的元组来访问。
维度的数量成为数组的阶。数组大小是一个由整型数构成的元组,可以描述数组不同维度上的大小。
从列表创建数组,利用方括号[]访问其中元素:
# 数组array
import numpy as np
a = np.array([1, 2, 3])# creat a rank 1 array 1阶数组
print(a) # [1 2 3]
print(type(a)) # <class 'numpy.ndarray'>
print(a.shape) # (3,)
print(a[0], a[1], a[2]) # 1 2 3
a[0] = 5
print(a) # [5 2 3]
b = np.array([[1,2,3],[4,5,6]])# creat a rank 2 array 2阶数组
print(b)
# [[1 2 3]
# [4 5 6]]
print(b.shape) # (2, 3)
print(b[0,0], b[0,1], b[1,0]) # 1 2 4
Numpy还提供了其他创建数组的方法:
import numpy as np
a = np.zeros((2,2)) # 生成全为0的数组array
print(a)
# [[ 0. 0.]
# [ 0. 0.]]
b = np.ones((1,2)) # 生成全为1的数组array
print(b)
# [[ 1. 1.]]
c = np.full((2,2), 8) # 常数均为8的2x2数组
print(c)
# [[8 8]
# [8 8]]
d = np.eye(2) # 单位矩阵identity matrix
print(d)
# [[ 1. 0.]
# [ 0. 1.]]
e = np.random.random((2,2))
print(e)
# [[ 0.46699318 0.2937788 ]
# [ 0.35273887 0.30353399]]
访问数组
切片:与python列表类似,numpy数组可以使用切片语法。而数组是多维的,所以必须为每个维度指定好切片。
# 创建一个2维3x4的数组 create the following rank 2 array with shape (3, 4)
# [[ 1 2 3 4]
# [ 5 6 7 8]
# [ 9 10 11 12]]
a = np.array([[1,2,3,4], [5,6,7,8], [9,10,11,12]])
# 使用切片选出行索引2前(不包含2)即index=0,1,第一行第二行
# 选择出索引1,2(不包含3)即第二,三列
# [[2 3]
# [6 7]]
b = a[:2, 1:3]
print(a[0,1]) # 2
b[0,0] = 88 # b[0,0]等价于a[0,1]:b[0,0] is the same piece of data as a[0,1]
print(a)
# [[ 1 88 3 4]
# [ 5 6 7 8]
# [ 9 10 11 12]]
print(a[0,1]) # 88
可以同时使用整型和切片语法来访问数组,但,这样会产生一个比原数组低阶的新数组。
a = np.array([[1,2,3,4], [5,6,7,8], [9,10,11,12]])
row_r1 = a[1, :]
row_r2 = a[1:2, :]
print(row_r1, row_r1.shape) # [5 6 7 8] (4,)
print(row_r2, row_r2.shape) # [[5 6 7 8]] (1, 4)
col_r1 = a[:, 1]
col_r2 = a[:, 1:2]
print(col_r1, col_r1.shape) # [ 2 6 10] (3,)
print(col_r2, col_r2.shape)
# [[ 2]
# [ 6]
# [10]] (3, 1)
整型数组访问:使用切片语法访问数组时,得到的总是原数组的一个子集。整型数组访问我们利用其它数组的数据构建一个新的数组:
import numpy as np
a = np.array([[1,2], [3,4], [5,6]])
# [[1 2]
# [3 4]
# [5 6]]
# 整型数组访问
print(a[[0,1,2], [0,1,0]]) # [1 4 5]
#等价于
print(np.array([a[0,0], a[1,1], a[2,0]]))
print(a[[0,0], [1,1]]) # [2 2]
# 等价于
print(np.array([a[0,1], a[0,1]]))
整型数组还可以选择或更改矩阵中每行的一个元素:
import numpy as np
a = np.array([[1,2,3], [4,5,6], [7,8,9], [10,11,12]])
print(a)
# [[ 1 2 3]
# [ 4 5 6]
# [ 7 8 9]
# [10 11 12]]
b = np.array([0,2,0,1]) # 创建一个数组索引
# 选取每行对应b中索引的元素
print(np.arange(4)) # [0 1 2 3]
print(a[np.arange(4), b]) # [ 1 6 7 11]
a[np.arange(4), b] += 10
print(a)
# [[11 2 3]
# [ 4 5 16]
# [17 8 9]
# [10 21 12]]
布尔型数组访问:布尔型数组访问可以选择数组中任意元素。通常,这种访问方式用于选取数组中满足某些条件的元素:
# 布尔型数组访问
import numpy as np
a = np.array([[1, 2], [3, 4], [5, 6]])
bool_idx = (a > 2) # 找到数组a中比2大的元素
print(bool_idx)
# [[False False]
# [ True True]
# [ True True]]
print(a[bool_idx])
# [3 4 5 6]
print(a[a > 2]) # [3 4 5 6]
数据类型
每个numpy数组都是数据类型相同的元素组成的网格。当创建数组时,numpy会猜测数组的数据类型,我们可以通过参数直接指定数据:
# 数据类型
import numpy as np
x = np.array([1, 2])
print(x.dtype)
x = np.array([1.0, 2.0])
print(x.dtype)
# x = np.array([1, 2], dtype=np.int64)
# print(x.dtype) # for python2 is ok,but python3 is false
数组计算
基本数学计算函数会对数组中的元素逐个进行计算,既可以利用操作符重载,也可以使用函数方式:
# 数组计算
import numpy as np
x = np.array([[1,2], [3,4]])
y = np.array([[5,6], [7,8]])
print(x + y)
print(np.add(x, y))
# [[ 6 8]
# [10 12]]
print(x - y)
print(np.subtract(x, y))
# [[-4 -4]
# [-4 -4]]
print(x * y)
print(np.multiply(x, y))
# [[ 5 12]
# [21 32]]
print(x / y)
print(np.divide(x, y))
# [[ 0.2 0.33333333]
# [ 0.42857143 0.5 ]]
print(np.sqrt(x))
# [[ 1. 1.41421356]
# [ 1.73205081 2. ]]
和matlab不同,
* 是元素
逐个相乘,不是矩阵乘法。numpy中使用
dot来进行
矩阵乘法
# 数组的元素逐个相乘以及矩阵乘法
import numpy as np
x = np.array([[1,2], [3,4]])
y = np.array([[5,6], [7,8]])
v = np.array([9, 10])
w = np.array([11,12])
print(v.dot(w))
print(np.dot(v, w))
# 219
print(x.dot(v))
print(np.dot(x, v))
# [29 67]
print(x.dot(y))
print(np.dot(x, y))
# [[19 22]
# [43 50]]
numpy提供了很多计算数组的函数,其中最常用的一个是sum:
# sum函数
import numpy as np
x = np.array([[1,2], [3,4]])
# [[1 2]
# [3 4]]
print(np.sum(x)) # 10 即数组中所有元素之和
print(np.sum(x, axis=0)) # [4 6] 数组中每列(axis=0)元素相加
print(np.sum(x, axis=1)) # [3 7] 数组中每行(axis=1)元素相加
除了计算,还需改变数组或者操作其中的元素。其中numpy中用
T 将矩阵转置
# 转置T
import numpy as np
x = np.array([[1,2],
[3,4]])
print(x)
# [[1 2]
# [3 4]]
print(x.T)
# [[1 3]
# [2 4]]
v = np.array([1,2,3]) # 对一维数组不起作用
print(v) # [1 2 3]
print(v.T) # [1 2 3]
广播broadcasting
广播是一种强有力的机制,它使Numpy可以让不同大小的矩阵在一起进行数学计算。我们常会有一个小的矩阵和一个大的矩阵,然后需要用小的矩阵对大的矩阵做一些计算。
# baseline for循环
import numpy as np
# We will add the vector v to each row of the matrix x,
# storing the result in the matrix y
x = np.array([[1,2,3], [4,5,6], [7,8,9], [10,11,12]])
v = np.array([1, 0, 1])
y = np.empty_like(x) # 创建一个空矩阵大小和x一样 create an empty matrix with the same shape as x
print(y)
# [[0 0 0]
# [0 0 0]
# [0 0 0]
# [0 0 0]]
# Add the vector v to each row of the matrix x with an explicit
for i in range(4):
y[i, :] = x[i, :] + v
print(y)
# [[ 2 2 4]
# [ 5 5 7]
# [ 8 8 10]
# [11 11 13]]
以上是baseline,但是当x矩阵非常大的时候,循环的计算就会很慢,我们换成矩阵的思路:
# 矩阵思路
import numpy as np
x = np.array([[1,2,3], [4,5,6], [7,8,9], [10,11,12]])
v = np.array([1, 0, 1])
vv = np.tile(v, (4, 1)) # Stack 4 copies of v on top of each other 拓展
print(vv)
# [[1 0 1]
# [1 0 1]
# [1 0 1]
# [1 0 1]]
y = x + vv
print(y)
# [[ 2 2 4]
# [ 5 5 7]
# [ 8 8 10]
# [11 11 13]]
numpy广播机制可以让我们不用创建vv,直接运算:
# 广播机制
import numpy as np
x = np.array([[1,2,3], [4,5,6], [7,8,9], [10,11,12]])
v = np.array([1, 0, 1])
y = x + v
print(y)
# [[ 2 2 4]
# [ 5 5 7]
# [ 8 8 10]
# [11 11 13]]
对两个数组使用广播机制要遵守下列规则:
- 如果数组的秩不同,使用1来将秩较小的数组进行扩展,直到两个数组的尺寸的长度都一样。
- 如果两个数组在某个维度上的长度是一样的,或者其中一个数组在该维度上长度为1,那么我们就说这两个数组在该维度上是相容的。
- 如果两个数组在所有维度上都是相容的,他们就能使用广播。
- 如果两个输入数组的尺寸不同,那么注意其中较大的那个尺寸。因为广播之后,两个数组的尺寸将和那个较大的尺寸一样。
- 在任何一个维度上,如果一个数组的长度为1,另一个数组长度大于1,那么在该维度上,就好像是对第一个数组进行了复制。
如果上述解释看不明白,可以读一读文档和这个解释。译者注:强烈推荐阅读文档中的例子。
下面是一些广播机制的使用:
# examples
import numpy as np
v = np.array([1,2,3]) # v has shape (3,)
w = np.array([4,5]) # w has shape (2,)
# To compute an outer product, we first reshape v to be a column
# vector of shape (3, 1); we can then broadcast it against w to yield
print(np.reshape(v, (3, 1))) # 变成3行一列
# [[1]
# [2]
# [3]]
# an output of shape (3, 2), which is the outer product of v and w:
print(np.reshape(v, (3, 1)) * w)
# [[ 4 5]
# [ 8 10]
# [12 15]]
x = np.array([[1,2,3],
[4,5,6]])
print(x * 2)
# [[ 2 4 6]
# [ 8 10 12]]
print(x + v)
# [[2 4 6]
# [5 7 9]]
print(x.T)
# [[1 4]
# [2 5]
# [3 6]]
print((x.T + w).T)
# [[ 5 6 7]
# [ 9 10 11]]
print(np.reshape(w, (2,1)))
# [[4]
# [5]]
print(x + np.reshape(w, (2,1)))
# [[ 5 6 7]
# [ 9 10 11]]
Numpy文档
这篇教程涉及了你需要了解的numpy中的一些重要内容,但是numpy远不止如此。可以查阅numpy文献来学习更多。
以上内容转载整理来自知乎专栏点击打开链接,侵删侵删。