[Machine Learning]Numpy

Numpy:

numpy提供两种基本的对象:ndarray和ufunc,ndarray是存储单一数据类型的多为数组,ufunc是能够对数组进行操作的函数。

1.ndarray对象

创建数组:

a = numpy.array([1, 2, 3, 4])

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

数组的形状可以通过其shape属性获得,它是一个描述数组各个轴长度的元组:

1 a.shape
2 # 结果: (4,)
3 b.shape
4 # 结果: (2, 4)

在保持数组元素个数不变的情况下,可以通过改变数组shape属性,改变数组每个轴的大小:(数组元素在内存中的位置不变)

1 b.shape = 4,2
2 #结果
3 #array([[1, 2],
4 #       [3, 4],
5 #      [4, 5],
6 #       [6, 7]])

当设置某个轴的元素个数为-1时,将自动计算此轴的长度。使用reshape()方法可以创建指定形状的新数组,原数组保持不变,新数组和原数组是共享存储空间的,修改会相互影响:

1 c = b.reshape(2, 4)
2 #结果
3 #array([[1, 2, 3, 4],
4 #      [4, 5, 6, 7]])

数组元素的类型可以通过dtype属性获得:

c.dtype
#结果
# dtype('int64')

可以用dtype参数在创建数组时指定元素类型,float是64bit的双精度浮点类型,complex是128bit的双精度复数类型:

1 numpy.array([1,2,3,4], dtype=np.float)

Numpy的完整的类型列表存储在typeDict字典中,可以将其转换为集合来查看:

{numpy.bool_,
 numpy.object_,
 numpy.string_,
 numpy.unicode_,
 numpy.void,
 numpy.int8,
 numpy.int16,
 numpy.int32,
 numpy.int64,
 numpy.int64,
 numpy.uint8,
 numpy.uint16,
 numpy.uint32,
 numpy.uint64,
 numpy.uint64,
 numpy.float16,
 numpy.float32,
 numpy.float64,
 numpy.float128,
 numpy.datetime64,
 numpy.timedelta64,
 numpy.complex64,
 numpy.complex128,
 numpy.complex256}

arange()通过指定开始值,终止值和步长创建表示等差数列的一位数组(不包括终止值):

1 numpy.arange(0, 1, 0.1)
2 #结果
3 #array([ 0. ,  0.1,  0.2,  0.3,  0.4,  0.5,  0.6,  0.7,  0.8,  0.9])

linspace()通过指定开始值,终止值和元素个数创建等差数列的一维数组:

1 numpy.linspace(0, 1, 10) #步长1/9
2 #结果
3 #array([ 0.        ,  0.11111111,  0.22222222,  0.33333333,  #0.44444444,
4 #        0.55555556,  0.66666667,  0.77777778,  0.88888889,  1.])
5 
6 numpy.linspace(0, 1, 10, endpoint=False) #步长1/10
7 #结果
8 #array([ 0. ,  0.1,  0.2,  0.3,  0.4,  0.5,  0.6,  0.7,  0.8,  0.9])

 logspace()用于创建等比数列。

zeros(), ones, empty()可以创建指定形状和类型的数组, zeros_like(),ones_like(), empty_like()可以用来创建数组的形状及类型相同, 例如zeros_like(a) 和 zeros(a.shape, a.dtype):

numpy.empty((2, 3), numpy.int) #只分配类型,不初始化
#结果
#array([[-5764607523034234880,  6917537799820997240,           4327211011],
#      [          4327214544,           4327214608,      844424930131968]])

numpy.zeros(4, numpy.float) #元素被初始化为0,默认类型numpy.float
#结果:
#array([ 0.,  0.,  0.,  0.])

frombuffer(),fromstring()和fromfile()等可以从字节序列或文件创建数组:

 1 s = "abcdefg"
 2 numpy.fromstring(s, dtype=numpy.int8)
 3 #结果:
 4 #array([ 97,  98,  99, 100, 101, 102, 103], dtype=int8)
 5 
 6 s = "abcdef"
 7 numpy.fromstring(s, dtype=numpy.int16)
 8 #结果
 9 #array([25185, 25699, 26213], dtype=int16)
10 # 其中每个元素等于两个字节表示一个整数,98 * 256 + 97

 还可以定义一个从下标计算数值的函数,然后使用fromfunction()创建数组:

def func(i):
    return i % 4 + 1

numpy.fromfunction(func, (10, ))
#结果
#array([ 1.,  2.,  3.,  4.,  1.,  2.,  3.,  4.,  1.,  2.])

 存取元素:

a = numpy.arange(10)
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

a[5] #用整数作为下标可以获取数组中的某个元素
#结果:5

a[3 : 5] #用切片作为下标获取数组一部分,不包括a[5]
#结果:array([3, 4])

a[2:4]=100,101 #用下标来修改元素的值
#结果:array([  0,   1, 100, 101,   4,   5,   6,   7,   8,   9])

 通过切片获取的新数组是原数组的一个数组,它与原始数组共享同一数据空间。

使用整数列表对数组元素进行存取时,得到的新数组不和原始数组共享数据,整数数组和布尔数组类似:

1 x = numpy.arange(10, 1, -1)
2 #array([10,  9,  8,  7,  6,  5,  4,  3,  2])
3 
4 x[[3, 3, 1, 8]] #获取数组中下标为3, 3, 1, 8的四个元素,组成一个新的数组

多维数组

Numpy用元组作为数组下标,创建二维数组:

a = numpy.arange(0, 60, 10).reshape(-1, 1) + numpy.arange(0, 6)
#结果
#array([[ 0,  1,  2,  3,  4,  5],
       [10, 11, 12, 13, 14, 15],
       [20, 21, 22, 23, 24, 25],
       [30, 31, 32, 33, 34, 35],
       [40, 41, 42, 43, 44, 45],
       [50, 51, 52, 53, 54, 55]])

数据元素存取,第0个元素和数组的第0轴(纵轴)相对应,第1个元素与数组的第1轴(横轴)对应:

1 a[0, 3:5]
2 #结果:array([3, 4])
3 
4 a[4:, 4:]
5 #array([[44, 45],
6        [54, 55]])

可以通过创建下标元组,用同一元组存取多个数组:

1 idx = slice(None, None, 2), slice(2, None)
2 a[idx] #和a[::2, 2:]相同
3 #结果
4 #array([[ 2,  3,  4,  5],
5        [22, 23, 24, 25],
6        [42, 43, 44, 45]])
 1 1. a[(0, 1, 2, 3), (1, 2, 3, 4)] #类似a[0, 1], a[1, 2], a[2, 3], a[3, 4]
 2 #结果:array([ 1, 12, 23, 34])
 3 
 4 2. a[3:, [0, 2,5]] # 第0轴是个切片,选取第三行后的所有行,第1轴选取0, 2, 5列
 5 #结果:
 6 #array([[30, 32, 35],
 7        [40, 42, 45],
 8        [50, 52, 55]])
 9 
10 
11 3. mask = numpy.array([1, 0, 1, 0, 0, 1], dtype=numpy.bool)
12 a[mask, 2] #第0轴是个布尔数组选取0,2,5, 第1轴选取第2列
13 #结果array([ 2, 22, 52])
14 #注意:如果mask不是布尔数组,而是整数数组,列表或者元组,按照1运算

 当所有轴用形状相同的整数数组作为下标,得到的数组和下标数组的维数相同:

1 x = numpy.array([[0 ,1], [2, 3]])
2 y = numpy.array([[-1, -2], [-3, -4]])
3 a[x, y]
4 #结果:
5 # array([[ 5, 14],
6        [23, 32]])
7 
8 #类似于
9 a[(0, 1, 2, 3), (-1, -2, -3, -4)].reshape(2, 2)

 结构数组:

1 persontype = numpy.dtype({
2    ....: "names" : ["name", "age", "weight"], #每个字段名
3    ....: "formats" : ['S32', 'i', 'f']}, align = True) #每个字段的类型
4 
5 a = numpy.array([("zhang", 32, 75.5), ("wang", 24, 65.2)], dtype=persontype)

 2. ufunc运算

ufunc是universal function的缩写,它是一种能对数组中每个元素进行操作的函数。

x = numpy.linspace(0, 2 * numpy.pi, 10)
y = numpy.sin(x) #numpy.sin()就是一个ufunc函数

数组提供了item()方法用来获取数组中的单个元素,并直接返回标准的Python数值类型:

1 a = numpy.arange(6.0).reshape(2, 3)
2 a.item(1, 2) #和a[1,2]类似
3 type(a.item(1, 2))
4 #结果:float
5 
6 type(a[1,2])
7 #结果:numpy.float64

四则运算

a = numpy.arange(0, 4)
b = numpy.arange(1, 5)
numpy.add(a, b)
#结果array([1, 3, 5, 7])

#可以通过指定第三个参数,保存结果
numpy.add(a, b, a) #等价于a+=b
a
#结果array([1, 3, 5, 7]) 

比较和布尔运算

使用"==",">"等比较运算符对两个数组进行比较,将返回一个布尔数组,该数组的每个元素值都是两个数组对于元素的比较结果:

1 numpy.array([1, 2, 3]) < numpy.array([3, 2, 1])
2 #结果array([ True, False, False], dtype=bool)

数组中的布尔运算只能通过相应的ufunc函数进行,这些函数以"logical_开头, 使用and, or, not将抛出异常":

1 numpy.logical_and  numpy.logical_not  numpy.logical_or   numpy.logical_xor
 1 a = numpy.arange(5)
 2 b = numpy.arange(4, -1, -1)
 3 a == b
 4 #结果:array([False, False,  True, False, False], dtype=bool)
 5 
 6 a > b
 7 #结果:array([False, False, False,  True,  True], dtype=bool)
 8 
 9 numpy.logical_or(a > b, a ==b)
10 #结果:array([False, False,  True,  True,  True], dtype=bool)

 位运算符可以使用&,|, ~等,也可是使用以bitwise_开头的比特运算符:

numpy.bitwise_and  numpy.bitwise_not  numpy.bitwise_or   numpy.bitwise_xor

注意位运算符优先级高于布尔运算符, 注意括号的使用:

1 (a == b) | (a > b)

自定义ufunc运算:

用frompyfunc()将一个计算单个元素的函数转换成ufunc函数, frompyfunc()的调用格式:

1 frompyfunc(func, nin, nout)

其中:func是计算单个元素的函数,nin是func输入参数的个数,nout是func返回值的个数。

 1 def triangle_wave(x, c, c0, hc):
 2     x = x - int(x)
 3     if x >= c: r= 0.0 
 4     elif x < c0: r = x/ c0 * hc
 5     else: r = (c - x) / (c - c0) * hc
 6     return r
 7 
 8 x = numpy.linspace(0, 2, 1000)
 9 #func对象
10 triangle_ufunc1 = numpy.frompyfunc(triangle_wave, 4, 1)
11 #使用
12 y2 = triangle_ufunc1(x, 0.6, 0.4, 1.0)

注意此时func返回数组的元素类型是object,可以用astype()进行转换

1 y2.dtype
2 #结果:dtype('O')
3 
4 y2 = y2.astype(numpy.float)

可以使用vectorize()实现和frompyfunc()相同的功能,但该函数可以通过otypes指定返回类型。

 广播

使用ufunc对两个数组进行运算时,要求两个数组的形状相同,如果不同,则进行广播,规则如下:

1. 让所有输入数组都向其中维数最多的数组看齐,shape属性中不足的部分通过在前面加1补齐;

2. 输出数组的shape属性是输入数组的shape属性在各轴上的最大值;

3. 如果输入数组的某个轴长度为1或与输出数组对应轴的长度相同,这个数组就能用来计算,否则出错;

4. 当输入数组的某个轴长度为1时,沿着此轴运算时都用此轴上的第一组值。

 1 a = numpy.arange(0, 60, 10).reshape(-1, 1)
 2 #结果:
 3 #array([[ 0],
 4        [10],
 5        [20],
 6        [30],
 7        [40],
 8        [50]])
 9 
10 a.shape
11 #结果:(6, 1)
12 
13 b = numpy.arange(0, 5)
14 b.shape
15 #结果 (5,)
16 
17 c = a + b
18 #结果
19 #array([[ 0,  1,  2,  3,  4],
20        [10, 11, 12, 13, 14],
21        [20, 21, 22, 23, 24],
22        [30, 31, 32, 33, 34],
23        [40, 41, 42, 43, 44],
24        [50, 51, 52, 53, 54]])
25 c.shape
26 #结果:(6, 5)

Numpy提供了快速产生能进行广播运算的数组的ogrid对象:

 1 x, y = numpy.ogrid[:5, :5]
 2 x
 3 #结果
 4 #array([[0],
 5        [1],
 6        [2],
 7        [3],
 8        [4]])
 9 y
10 #结果
11 #array([[0, 1, 2, 3, 4]])
12 
13 x + y
14 #结果
15 #array([[0, 1, 2, 3, 4],
16        [1, 2, 3, 4, 5],
17        [2, 3, 4, 5, 6],
18        [3, 4, 5, 6, 7],
19        [4, 5, 6, 7, 8]])

 多维数组:

待续。。。。。。。

原文地址:https://www.cnblogs.com/skycore/p/4952824.html