python累乘函数_【十分钟Python知识点】NumPy 高频使用函数

1 Numpy更高效

使用Python的地方,就能看到Numpy,尤其是需要数值计算的地方,Numpy的高性能更是体现的淋漓尽致。

它基于Python,提供远高于Python的高性能向量、矩阵和更高维度的数据结构。之所以性能高是由于它在密集型计算任务中,向量化操作是用C和Fortran代码实现。

2 导入Numpy

只需要一行代码就能导入:

from numpy import *

在numpy包中,描述向量,矩阵和更高维度的数据集使用的术语是array.

3 生成numpy数组

有许多方法能初始化一个新的numpy数组,例如:arange, linspace等,从文件中读入数据,从python的lists等都能生成新的向量和矩阵数组。例:

In [1]: from numpy import *

In [2]: v = array([1,2,3,4])

In [3]: v

Out[3]: array([1, 2, 3, 4])

In [4]: m = array([[1,2],[3,4]])

In [5]: m

Out[5]:

array([[1, 2],

[3, 4]])

v和m的类型都是ndarray,这是numpy中最主要的数据结构之一

In [6]: type(v),type(m)

Out[6]: (numpy.ndarray, numpy.ndarray)

v和m的不同仅仅是它们的形状(shape), 我们能通过ndarray.shape属性发现它们的形状信息,shape属性很有用,尤其在深度学习模型调试中:

In [7]: shape(v),shape(m)

Out[7]: ((4,), (2, 2))

numpy中获取元素个数通过size:

In [8]: size(v),size(m)

Out[8]: (4, 4)

4 为什么要用numpy?

到此,numpy.ndarray看起来非常像Python的list, 那我们为什么不用Python的list计算,干嘛非要创造一个新的数组(array)类型呢?

有多个原因:Python的list是一个通用结构。Python的list能包括任意类型的对象,并且是动态类型, 它们不支持一些数学函数,比如矩阵的点乘,实现如此的函数对于Python的list而言,不会高效,因为它是动态类型

Numpy的array是静态类型和同质的,当array被创建时,元素的类型就确定

Numpy的array更节省内存

由于是静态类型,一些数学函数实现起来会更快,例如array间的加减乘除能够用C和Fortran实现

使用ndarray.dtype, 我们能看到一个数组内元素的类型:

In [9]: m.dtype

Out[9]: dtype('int32')

如果我们尝试用str类型赋值给m,会报错:

In [10]: m[0,0]='hello'

---------------------------------------------------------------------------

ValueError Traceback (most recent call last)

in

----> 1 m[0,0]='hello'

ValueError: invalid literal for int() with base 10: 'hello'

创建数组时,能指定类型,通过为dtype赋值:

In [11]: mc = array([[1,2,],[3,4]],dtype=complex)

In [12]: mc

Out[12]:

array([[1.+0.j, 2.+0.j],

[3.+0.j, 4.+0.j]])

dtype更多取值:int, float, complex, bool, object, 我们还可以显示的定义数据位数的类型,如:int64, int16, float128, complex128

5 通过函数生成数组

对于更大的数组,手动初始化数据是不现实的,比如使用python的list. 我们得用numpy提供的函数才能生成不同形式的数组。比如更通用的:

arange 函数:起始点,终点,步长;不包括终点

In [2]: x = arange(0,10,1)

In [3]: x

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

In [4]: x = arange(-1, 1, 0.1)

In [5]: x

Out[5]:

array([-1.00000000e+00, -9.00000000e-01, -8.00000000e-01, -7.00000000e-01,

-6.00000000e-01, -5.00000000e-01, -4.00000000e-01, -3.00000000e-01,

-2.00000000e-01, -1.00000000e-01, -2.22044605e-16, 1.00000000e-01,

2.00000000e-01, 3.00000000e-01, 4.00000000e-01, 5.00000000e-01,

6.00000000e-01, 7.00000000e-01, 8.00000000e-01, 9.00000000e-01])

linspace 函数:起始点,终点,分割份数;包括终点

In [5]: linspace(0,10,5)

Out[5]: array([ 0. , 2.5, 5. , 7.5, 10. ])

logspace 函数:如下例子,各项分别为 e^1,e^2, e^3,…e^10

In [17]: logspace(1, 10, 10, base=e)

Out[17]:

array([2.71828183e+00, 7.38905610e+00, 2.00855369e+01, 5.45981500e+01,

1.48413159e+02, 4.03428793e+02, 1.09663316e+03, 2.98095799e+03,

8.10308393e+03, 2.20264658e+04])

mgrid 函数,实际工作中也很有用,在这里我列举一个

In [18]: x,y = mgrid[0:5,0:5]

In [19]: x

Out[19]:

array([[0, 0, 0, 0, 0],

[1, 1, 1, 1, 1],

[2, 2, 2, 2, 2],

[3, 3, 3, 3, 3],

[4, 4, 4, 4, 4]])

In [20]: y

Out[20]:

array([[0, 1, 2, 3, 4],

[0, 1, 2, 3, 4],

[0, 1, 2, 3, 4],

[0, 1, 2, 3, 4],

[0, 1, 2, 3, 4]])

这是基本用法,完全看不出干啥。如果我有10个点,想要得出这10个点的两两间距离:

x,y = mgrid[0:5,0:5]

In [28]: list(map(lambda xe,ye: [(ex,ey) for ex, ey in zip(xe, ye)], x,y))

Out[28]:

[[(0, 0), (0, 1), (0, 2), (0, 3), (0, 4)],

[(1, 0), (1, 1), (1, 2), (1, 3), (1, 4)],

[(2, 0), (2, 1), (2, 2), (2, 3), (2, 4)],

[(3, 0), (3, 1), (3, 2), (3, 3), (3, 4)],

[(4, 0), (4, 1), (4, 2), (4, 3), (4, 4)]]

特殊点的矩阵,对角阵:

In [22]: diag([1,2,3])

Out[22]:

array([[1, 0, 0],

[0, 2, 0],

[0, 0, 3]])

主对角线偏移1的矩阵:

In [23]: diag([1,2,3],k=1)

Out[23]:

array([[0, 1, 0, 0],

[0, 0, 2, 0],

[0, 0, 0, 3],

[0, 0, 0, 0]])

零阵:

In [24]: zeros((3,3))

Out[24]:

array([[0., 0., 0.],

[0., 0., 0.],

[0., 0., 0.]])

1阵:

In [25]: ones((3,3))

Out[25]:

array([[1., 1., 1.],

[1., 1., 1.],

[1., 1., 1.]])

6 随机函数

Numpy提供的random使用起来更友好,如下:

获得取值(0,1)上的均匀分布,生成shape为(1,2,3)的三维数组:

In [36]: random.rand(1,2,3)

Out[36]:

array([[[0.22120906, 0.80388812, 0.52726328],

[0.37277153, 0.88388754, 0.76586961]]])

满足均值为0,方差为1的高斯分布得到随机数据,生成shape为(5,)的一维数组:

In [38]: random.randn(5)

Out[38]: array([ 0.51924157, 1.05994257, -0.492707 , 0.87205736, -0.14581919])

7 主要属性

生成1个三维数组:

In [32]: M = random.rand(2,3,4)

In [33]: M

Out[33]:

array([[[0.92362312, 0.68582456, 0.95927478, 0.40126712],

[0.13534077, 0.42983011, 0.72604572, 0.64202846],

[0.96822191, 0.8332197 , 0.64065175, 0.8979606 ]],

[[0.62970371, 0.22183503, 0.58752818, 0.20008916],

[0.21533794, 0.20558915, 0.751807 , 0.07743367],

[0.09854002, 0.55408343, 0.8663579 , 0.150306 ]]])

每个元素的字节数:

In [28]: M.itemsize

Out[28]: 8

M的总字节数:

In [30]: M.nbytes

Out[30]: 192

M的维数:

In [29]: M.ndim

Out[29]: 3

8 索引数组

索引数组的元素,可以使用方括号和下标,M是三维,下标索引的方法:

In [38]: M[1,1,2]

Out[38]: 0.7518069979719579

使用 :表示全部此维度的所有元素都要获取:

In [41]: M[0,:,:]

Out[41]:

array([[0.92362312, 0.68582456, 0.95927478, 0.40126712],

[0.13534077, 0.42983011, 0.72604572, 0.64202846],

[0.96822191, 0.8332197 , 0.64065175, 0.8979606 ]])

也可方便的切片:

In [47]: M[:,:2,1:3]

Out[47]:

array([[[1. , 0.95927478],

[1. , 0.72604572]],

[[0.22183503, 0.58752818],

[0.20558915, 0.751807 ]]])

直接赋值:

In [43]: M[0,:,1]=1.0

In [44]: M

Out[44]:

array([[[0.92362312, 1. , 0.95927478, 0.40126712],

[0.13534077, 1. , 0.72604572, 0.64202846],

[0.96822191, 1. , 0.64065175, 0.8979606 ]],

[[0.62970371, 0.22183503, 0.58752818, 0.20008916],

[0.21533794, 0.20558915, 0.751807 , 0.07743367],

[0.09854002, 0.55408343, 0.8663579 , 0.150306 ]]])

更有用的掩码索引,对应一个bool类型的数组:

In [49]: M[0,:,[False,True,True,False]]

Out[49]:

array([[1. , 1. , 1. ],

[0.95927478, 0.72604572, 0.64065175]])

M的维数:2*3*4,结果维度预期:1*3*2,但是实际结果维度:1*2*3

掩码索引,这一特性对于带条件的选取元素很重要。例如,使用arange生成一维数组x:

In [51]: x

Out[51]:

array([0. , 0.5, 1. , 1.5, 2. , 2.5, 3. , 3.5, 4. , 4.5, 5. , 5.5, 6. ,

6.5, 7. , 7.5, 8. , 8.5, 9. , 9.5])

判断x 中哪些元素大于5 呢

In [52]: x>5

结果返回的一堆:True, False:

Out[52]:

array([False, False, False, False, False, False, False, False, False,

False, False, True, True, True, True, True, True, True,

True, True])

然而有时候,我们想知道x 中哪些位置的元素大于5,此时要借助 where :

In [53]: where(x>5)

Out[53]: (array([11, 12, 13, 14, 15, 16, 17, 18, 19], dtype=int64),)

9 元素级操作

NumPy中两个数组加减乘除等,默认都是对应元素的操作:

In [55]: v1

Out[55]: array([0, 1, 2, 3, 4])

v1+2:

In [57]: v1+2

Out[57]: array([2, 3, 4, 5, 6])

v1 * v1:

In [58]: v1 * v1

Out[58]: array([ 0, 1, 4, 9, 16])

10 矩阵运算

线性代数中,矩阵的相乘操作在NumPy 中怎么实现,两种方法:dot函数 和 包装为matrix对象。

dot 操作:

# 数值[1,10)内,生成shape为(5,2)的随机整数数组

v2 = random.randint(1,10,(5,2))

In [77]: v2

Out[77]:

array([[8, 6],

[9, 4],

[4, 6],

[1, 3],

[2, 1]])

# v1:1行5列,v2:5行2列,结果1行2列

In [78]: dot(v1,v2)

Out[78]: array([28, 29])

另一种方法包装为matrix类:

In [81]: matrix(v1)*matrix(v2)

Out[81]: matrix([[28, 29]])

经过包装后,shape取值也会变得更符合线代中的常识:

In [83]: matrix(v1).shape

Out[83]: (1, 5)

而在没有包装前:

In [84]: v1.shape

Out[84]: (5,)

求矩阵的行列式,要求数组的最后两个维度相等,因此重新构造一个矩阵:

In [88]: v3 = random.randint(0,10,(3,3))

In [89]: v3

Out[89]:

array([[6, 5, 8],

[8, 4, 0],

[3, 8, 1]])

In [90]: v3m = matrix(v3)

In [91]: v3m

Out[91]:

matrix([[6, 5, 8],

[8, 4, 0],

[3, 8, 1]])

In [92]: linalg.det(v3m)

Out[92]: 399.9999999999999

11 统计变量

求平均值:

In [93]: v3

Out[93]:

array([[6, 5, 8],

[8, 4, 0],

[3, 8, 1]])

In [94]: v3.mean()

Out[94]: 4.777777777777778

In [95]: v3.mean(axis=1)

Out[95]: array([6.33333333, 4. , 4. ])

求标准差:

In [97]: v3.std()

Out[97]: 2.8588178511708016

求方差:

In [98]: v3.var()

Out[98]: 8.17283950617284

求最大值:

In [99]: v3.max(axis=1)

Out[99]: array([8, 8, 8])

求最小值:

In [106]: v3.min(axis=1)

Out[106]: array([5, 0, 1])

求和:

In [107]: v3.sum(axis=1)

Out[107]: array([19, 12, 12])

求累乘:

In [108]: v3.cumprod(axis=1)

Out[108]:

array([[ 6, 30, 240],

[ 8, 32, 0],

[ 3, 24, 24]], dtype=int32)

求累和:

In [109]: v3.cumsum(axis=1)

Out[109]:

array([[ 6, 11, 19],

[ 8, 12, 12],

[ 3, 11, 12]], dtype=int32)

求迹:

In [111]: v3.trace()

Out[111]: 11

In [112]: diag(v3).sum()

Out[112]: 11

12 改变Shape

NumPy数组的shape 被修改而无需复制原有数据,这使它更为高效。

In [117]: v4 = v3.reshape((1,9))

In [118]: v4

Out[118]: array([[6, 5, 8, 8, 4, 0, 3, 8, 1]])

我们验证下v4 是否真的没有被复制:

# 修改v4的第一行第2列的元素5,为10

In [120]: v4[0,1]=10

In [121]: v4

Out[121]: array([[ 6, 10, 8, 8, 4, 0, 3, 8, 1]])

# 查看v3,发现对应元素也变为10

In [122]: v3

Out[122]:

array([[ 6, 10, 8],

[ 8, 4, 0],

[ 3, 8, 1]])

所以验证得出:v4仅仅是v3的视图,未发生复制。

NumPy 提供的flatten 函数也有改变shape 的能力,将高维数组变为向量。但是,值得注意的是它会发生数组复制行为,因此不是高效的

有时,我们需要增加维度,此时可使用newaxis,它会插入1个维度,如下在第三个维度插入,v5的shape变为: [3,3,1]

In [128]: v5 = v3[:,:,newaxis]

In [129]: v5

Out[129]:

array([[[ 6],

[10],

[ 8]],

[[ 8],

[ 4],

[ 0]],

[[ 3],

[ 8],

[ 1]]])

13 数组由小变大

NumPy中的函数 repeat, tile, vstack, hstack, 和concatenate 具备变换小数组为大数组的能力。

repeat复制元素

In [132]: a = array([[1,2],[3,4]])

In [137]: repeat(a,2,axis=1)

Out[137]:

array([[1, 1, 2, 2],

[3, 3, 4, 4]])

In [138]: repeat(a,2,axis=0)

Out[138]:

array([[1, 2],

[1, 2],

[3, 4],

[3, 4]])

tile 复制块:

In [5]: tile(a,2)

Out[5]:

array([[1, 2, 1, 2],

[3, 4, 3, 4]])

In [6]: tile(a,(2,3))

Out[6]:

array([[1, 2, 1, 2, 1, 2],

[3, 4, 3, 4, 3, 4],

[1, 2, 1, 2, 1, 2],

[3, 4, 3, 4, 3, 4]])

vstack竖直方向合并数组:

In [18]: c = array([[-1,-2]])

Out[20]:

array([[ 1, 2],

[ 3, 4],

[-1, -2]])

hstack 水平方向合并数组:

b = array([[40],[12]])

hstack((a,b))

array([[ 1, 2, 40],

[ 3, 4, 12]])

concatenate指定在哪个轴向上合作数组:

In [26]: concatenate((a,c),axis=0) # 效果等于vstack

Out[26]:

array([[ 1, 2],

[ 3, 4],

[-1, -2]])

In [27]: concatenate((a,b),axis=1) # 效果等于hstack

Out[27]:

array([[ 1, 2, 40],

[ 3, 4, 12]])

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值