【NumPy】官方文档详解(一)什么是NumPy?

一、什么是NumPy?

NumPy(Numerical Python)是Python中的科学计算基础包,它提供了多维数据对象各种派生对象(如屏蔽数组masked arrays和矩阵)、用于在数组上快速计算的各种例程(包括数值计算、逻辑运算、形状操作、排序、选择、I/O、离散傅里叶变换、基本线性代数、基本统计运算、随机模拟等等)。

NumPy库的核心是ndarray对象,它封装了由相同类型数据组成的n维数组,许多操作在编译代码中执行以提高性能。下面是NumPy数组和标准Python序列的一些重要区别:

  • NumPy数组的大小是固定的,一经创建则不可改变,改变ndarray的大小将会删除原始数组而创建一个新的数组。而Python的列表可以动态生长。
  • NumPy数组的元素必须是同样的数据类型,因此它们在内存中占有相同的大小。例外的情况是:可以有(Python,包括NumPy)对象的数组,从而允许不同大小的元素的数组。
  • 越来越多的基于Python的科学和数学包正在使用NumPy数组;虽然这些通常支持Python序列输入,但它们在处理之前将此类输入转换为NumPy数组,并且它们通常输出NumPy数组。换句话说,为了有效地使用当今许多(甚至可能是大多数)基于Python的科学/数学软件,仅仅知道如何使用Python的内置序列类型是不够的,还需要知道如何使用NumPy数组。

关于序列大小和速度的要点在科学计算中尤其重要。作一个简单的示例,考虑将一维序列中的每个元素与另一个长度相同的序列中的相应元素相乘的情况。如果数据存储在两个Python列表中,我们可以使用for循环迭代每个元素,使对应元素相乘。这无疑会产生正确的结果,但如果每个序列都包含数百万个数字,效率就会非常低。

a=[1,2,3,4,5]
b=[1,2,3,4,5]
c=[]
for i in range(0,len(a)):
    c.append(a[i]*b[i])
print(c)

结果:[1, 4, 9, 16, 25]

用C语言可以更快的完成相同的任务,这节省了解释Python代码和操作Python对象所涉及的开销,但代价是牺牲了在Python中编码所获得的好处。此外,所需的编码工作随着数据维度的增加而增加。

//一维数组
for(i=0;i<rows;i++)
{
	c[i]=a[i]*b[i];
}

//二维数组
for(i = 0; i < rows; i++) 
{
  for (j = 0; j < columns; j++) 
  {
    c[i][j] = a[i][j]*b[i][j]; 
  }
}

NumPy为我们提供了两全其美的方式:当涉及ndarray时,逐个元素的操作是"默认模式",但逐个元素的操作是由预编译的C代码快速执行的。在 NumPy 中,相同的工作可以有一行简洁的代码来完成:

c = a * b

这个例子也说明了NumPy的两个功能,它们是其大部分功能的基础:矢量化广播


二、为什么NumPy很快?

先用一个实例来展示速度差异,从结果中可以看到,用列表循环所需的时间约为numpy的一百多倍:

import numpy as np
from time import *

a1=[]
b1=[]
c1=[]
# 生成长度为1000000的两个数组,用于后续计算演示
for i in range(0,1000000):
    a1.append(i)
    b1.append(i)

begin_time=time()             # 计时开始
for i in range(0,len(a1)):    # 利用for循环计算对应元素相乘
    c1.append(a1[i]*b1[i])
end_time=time()               # 计时结束
run_time=end_time-begin_time  # 计算时间差
print("python列表循环所需要的时间{:.12f}".format(run_time))

a2=np.array(a1)   # 将列表转换为numpy的ndarray对象
b2=np.array(b1)
begin_time=time()
c2=a2*b2          # 利用numpy计算对应元素相乘
end_time=time()
run_time=end_time-begin_time
print("numpy所需要的时间{:.12f}".format(run_time))
python列表循环所需要的时间0.440948247910
numpy所需要的时间0.002974748611

矢量化描述了代码中没有任何显式循环、索引等,这些事情是在优化的、预编译的C代码中发生的。矢量化具有许多优点,其中包括:

  • 矢量化代码更简洁,更易于阅读
  • 更少的代码行通常意味着更少的错误
  • 代码更接近于标准数学符号
  • 矢量化导致更多的"Pythonic"代码。如果没有矢量化,我们的代码将充斥着低效且难以阅读的循环

广播 是用于描述隐式的逐个元素的操作行为的术语,一般来说,在NumPy中,所有操作,不仅仅是算术运算,而是逻辑,位,函数等,都以这种隐式逐个元素的方式运行。此外,在上面的示例中,可以是相同形状的多维数组,也可以是标量和数组,甚至是两个具有不同形状的数组,前提是较小的数组可以"扩展"为较大形状的形状,从而使生成的广播是明确的。


小结

NumPy是Python非常重要且常用的科学基础计算包,它的核心是ndarray对象和与之相关的各种操作。

ndarray与标准的python序列(列表)有几个重要的不同点:

  • ndarray大小不可变,元素的数据类型相同
  • 标准python序列可动态变化,可由不同类型的数据组成

此外,很多的python工具包虽然支持传统序列的输入,但实际上也是将其转化为ndarray后再进行运算的,并最终返回ndarray。

使用Numpy的很大的好处,一方面运算速度快,这是因为其很多功能是在优化的预编译的C代码中发生的,另一方面使代码简洁易读,更"Pythonic"。

NumPy中两个重要功能,也是其他很多功能的基础——矢量化和广播。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值