简介
Numpy是一个用于科学计算的开源python库,其底层由c语言实现,有着优异的性能,使得计算更加高效。由于其他科学计算库以及深度学习框架是利用numpy中的对象实现,所以是使用其他高阶工具的基础。
ndarray对象
Numpy中有一个强大的N维数组对象ndarray,可以提供快速高效的矢量运算,即使不使用循环,也可以对数组中的数据进行标准运算。
ndarray对象有其重要的属性和方法。
ndarray属性
ndarray的维度称之为axes,维度的个数称之为rank,比如[1,2,3]只有一维,就可以用axex = 0
指代这一维。而[[1,2,3],[4,5,6],[7,8,9]]
是一个二维数组,其rank=2
,axex=0
表示行,axes=1
表示其列。
- ndarray.ndim
即ndarray的维度
import numpy as np
a = np.array([1,2,3])
b = np.array([[3,2,1],
[4,5,6]])
c = np.array([[[ 0, 1],
[ 2, 3],
[ 4, 5]],
[[ 6, 7],
[ 8, 9],
[10, 11]]])
print('rank of a:', a.ndim) # rank of a:1
print('rank of b:', b.ndim) # rank of b:2
print('rank of c:', c.ndim) # rank of c:3
- ndarray.shape
返回一个元组表示数组的大小,即在各个维度上元素的个数。一维的向量的shape为(3,),不是(1,3)
print('shape of a:', a.shape) # shape of a: (3,)
print('shape of b:', b.shape) # shape of b: (2, 3)
print('shape of c:', c.shape) # shape of c: (2, 3, 2)
d = np.array([[1,2,3]])
print('shape of d:', d.shape) # shape of d: (1, 3)
- ndarray.size
即ndarray中所有元素的个数,等于shape元组中各个数相乘。
print('size of a:', a.size) # size of a: 3
print('size of b:', b.size) # size of b: 6
print('size of c:', c.size) # size of c: 12
- ndarray.dtype
即ndarray中元素的类型,ndarray中提供了 numpy.int64, numpy.int16, and numpy.float64等类型,默认整数类型为int64,默认浮点数类型为float64。可以在创建是指定其元素类型。
e = np.array([3.,4.,5.], dtype=np.float16)
print('dtype of e:',e.dtype) # dtype of e: float16
print('dtype of a:',a.dtype) # dtype of a: int64
- ndarray.itemsize
即数组中元素在内存中所占的字节数 - ndarray.T
数组的转置
print(b.T)
print(a.T)
#[[3 4]
# [2 5]
# [1 6]]
# [1 2 3]
注意,一维的数组没有转置。
创建数组
有若干种方法可以创建一个ndarray数组,下面就来介绍一下。
1. 使用array函数
array函数将一个列表转成ndarray数组,常使用dtype参数,其他参数及函数原型参见文档。
f = np.array([1,2,3])
这里要注意,必须使用一个列表作为参数,而不是一串数字,比如np.array(1,2,3)
是错误的用法。
在不指定类型的情况下,默认整数类型为int64,浮点数类型为float64,创建数组时,可以指定元素类型,所有元素均为同一类型。
g = np.array([[1,2],
[3,4]], dtype=np.float32)
h = np.array([1+2j, 7+6j],dtype=complex)
print(g, g.dtype) # [[ 1. 2.]
# [ 3. 4.]] float32
print(h, h.dtype) # [ 1.+2.j 7.+6.j] complex128
可以通过指定ndim参数来指定数组的维数,在将向量转为1*n的数组时,可以指定其维数为2,便可。
i = np.array([1, 2, 3], ndmin=2)
print(i, i.shape) #[[1 2 3]] (1, 3)
j = np.array([1, 2, 3], ndmin=3)
print(j, j.shape) #[[[1 2 3]]] (1, 1, 3)
2.使用函数创建其他特殊数组
zeros:传入一个元组或者整数,创造一个全0的数组。
k = np.zeros((2,3)) print(k) # [[ 0. 0. 0.] # [ 0. 0. 0.]] l = np.zeros(5) print(l) # [ 0. 0. 0. 0. 0.]
ones :创建一个全1数组
m = np.ones(5) print(m) # [ 1. 1. 1. 1. 1.] n = np.ones((2,3),dtype=int) print(n) # [[1 1 1] # [1 1 1]]
empty:创建一个未初始化的数组,其中的值随内存值变化。
o = np.empty((2,3)) print(o) # [[ 0. 0. 0.] # [ 0. 0. 0.]]
arange:创建一个序列,类似于生成列表的range函数,可以在区间内给定一个步长,按照步长生成元素。
p = np.arange(3) print(p) # [0 1 2] q = np.arange(3,9,3) print(q) # [3 6]
linspace :创建一个序列,是选定一个区间内生成给定个元素的序列。
np.linspace(2.0, 3.0, num=5) # array([ 2. , 2.25, 2.5 , 2.75, 3. ]) np.linspace(2.0, 3.0, num=5, endpoint=False) # array([ 2. , 2.2, 2.4, 2.6, 2.8])
random.rand:给定数组大小,生成随机元素的数组。
np.random.rand(3,2) # array([[ 0.14022471, 0.96360618], #random # [ 0.37601032, 0.25528411], #random # [ 0.49313049, 0.94909878]]) #random
random.randn :给定数组大小,生成满足均值为0,方差为1的高斯分布的元素的数组。若是需要生成满足方差为sigma^2,均值为mu的分布的数组,则只要sigma*random.randn(…) +mu即可。
2.5 * np.random.randn(2, 4) + 3 # array([[-4.49401501, 4.00950034, -1.81814867, 7.29718677], # [ 0.39924804, 4.68456316, 4.99394529, 4.84057254]]) # N(3,6.25)
ndarray运算
作为线性代数的函数库,支持线性代数的基本运算是必要的。
加减乘除,直接的对ndarray之间的加减乘除是对数组中的每个对应元素都进行运算。在两个ndarray之间加减乘除时要满足两个数组的大小是一样的。
a = np.array([10, 20, 30, 40, 50])
b = np.arange(5)
a + b # array([10, 21, 32, 43, 54])
a - b # array([10, 19, 28, 37, 46])
a * b # array([ 0, 20, 60, 120, 200])
a / b # array([inf, 20. , 15. , 13.33333333, 12.5 ])
a ** 2 # array([ 100, 400, 900, 1600, 2500])
a * 2 # array([ 20, 40, 60, 80, 100])
a - 2 # array([ 8, 18, 28, 38, 48])
a < 35 # array([ True, True, True, False, False], dtype=bool)
c = np.arange(6)
a - c # ValueError
矩阵乘法的实现方式有两种,一是使用np.dot函数,二是使用ndarray.dot()方法。
A = np.random.rand(2,3)
# array([[ 0.70822388, 0.71623896, 0.56450237],
# [ 0.92269883, 0.31688239, 0.94905132]])
B = np.random.rand(3,2)
# array([[ 0.89410537, 0.45311124],
# [ 0.9874477 , 0.45395624],
# [ 0.70770496, 0.74099156]])
np.dot(A, B)
# array([[ 1.73997642, 1.06433684],
# [ 1.80954309, 1.26517496]])
A.dot(B)
# array([[ 1.73997642, 1.06433684],
# [ 1.80954309, 1.26517496]])
除了基本的矩阵乘法之外,numpy还实现了众多的线性代数运算。在此不一一赘述。详情可查阅文档,重要的方法将会在以后补充。
Deep copy
python的变量赋值是修改引用指向对象,并不会新创建对象。故在某些情况下,改编某个变量,会导致另一个变量随之改变。
a = np.arange(12).reshape((3, 4))
b = a
b is a # True
b[0][0] = 1 # a[0][0]也会变为1
所以,numpy提供了deep copy的方式,会重新创建一个引用和对象。
b = a.copy()
b is a # False