NumPy中文文档搬砖(划掉)学习笔记(1)
前言
况下加速Python中的操作运行时。适用于快速数值运算的一个选项是NumPy,它当之无愧地将自己称为使用Python进行科学计算的基本软件包。
当然,很少有人将50微秒(百万分之五十秒)的东西归类为“慢”。然而,计算机可能会有所不同。运行50微秒(50微秒)的运行时属于微执行领域,可以松散地定义为运行时间在1微秒和1毫秒之间的运算。
为什么速度很重要?微观性能值得监控的原因是运行时的小差异会随着重复的函数调用而放大:增量50μs的开销,重复超过100万次函数调用,转换为50秒的增量运行时间。
在计算方面,实际上有三个概念为NumPy提供了强大的功能:
* 矢量化
* 广播
* 索引
进入状态:介绍NumPy数组
NumPy的基本对象是它的ndarray(或numpy.array),这是一个n维数组,它以某种形式出现在面相组织的语言中,如Fortran 90、R和MATLAB,以及以前的APL和J。
首先从一个包含36个元素的三维数组开始:
import numpy as np
arr = np.arange(36).reshape(3, 4, 3)
print(arr)

在二维中描述高维数组可能会比较困难。考虑到数组形状的一种直观方法是简单的“从左到右读取它”。arr就是一个 $3\times4\times3$的数组:
import numpy as np
arr = np.arange(36).reshape(3, 4, 3)
print(arr.shape)

在视觉上,arr可以被认为是三个$4 \times3 $ 网格(或矩形棱镜)的容器,看起来像是:

更高纬度的数组可能更难以用图像表达出来,但是他们仍然遵循这种“数组内的数组”模式。
什么是矢量化?
矢量化是NumPy中的一种强大功能,可以将操作表达为在整个数组上而不是在各个元素上发生。以下是Wes McKinney的简明定义:
这种用数组表达式替换显式循环的做法通常称为向量化。通常,矢量化数组操作通常比其纯Python等价物快一个或两个(或更多)数量级,在任何类型的数值计算中都具有最大的影响。
察看源码
在Python中循环数组或任何数据结构时,会涉及很多开销。 NumPy中的向量化操作将内部循环委托给高度优化的C和Fortran函数,从而实现更清晰,更快速的Python代码。
计数:简单的如:1,2,3...
作为示例,考虑一个True和False的一维向量,你要为其计算序列中“False to True”转换的数量:
np.random.seed(444)
x = np.random.choice([False, True], size=100000)
print(x)

使用python for循环,一种方法使成对的评估每个元素的真值以及紧随其后的元素:
import numpy as np
arr = np.arange(36).reshape(3, 4, 3)
np.random.seed(444)
x = np.random.choice([False, True], size=100000)
print(x)
def cout_transitions(x) -> int:
count = 0;
for i, j in zip(x[:-1], x[1:]):
if j and not i:
count += 1
return count
print(cout_transitions(x))

在矢量化形式中,没有明确的for循环或直接引用各个元素:
np.count_nonzero(x[:-1] < x[1:])
在这种特殊情况下,向量化的NumPy调用胜出约70倍
技术细节:另一个术语是矢量处理器,它与计算机的硬件有关。 当我在这里谈论矢量化时,我指的是用数组表达式替换显式for循环的概念,在这种情况下,可以使用低级语言在内部计算。
买低,卖高
这是另一个激发你胃口的例子。考虑以下经典技术面试问题:
假定一只股票的历史价格是一个序列,假设你只允许进行一次购买和一次出售,那么可以获得的最大利润是多少?例如,假设价格=(20,18,14,17,20,21,15),最大利润将是7,从14买到21卖。
(对所有金融界人士说:不,卖空是不允许的。)
存在具有n平方时间复杂度的解决方案,其包括采用两个价格的每个组合,其中第二价格“在第一个之后”并且确定最大差异。
然而,还有一个O(n)解决方案,它包括迭代序列一次,找出每个价格和运行最小值之间的差异。 它是这样的:
def profit(prices):
max_px = 0
min_px = prices[0]
for px in prices[1:]:
min_px = min(min_px, px)
max_px = max(px - min_px, max_px)
return max_px
prices = (20, 18, 14, 17, 20, 21, 15)
print(profit(prices))
结果为7
这可以用NumPy实现吗?行!没问题。但首先,让我们构建一个准现实的例子:
# Create mostly NaN array with a few 'turning points' (local min/max).
prices = np.full(100, fill_value=np.nan)
prices[[0, 25, 60, -1]] = [80., 30., 75., 50.]
# Linearly interpolate the missing values and add some noise.
x = np.arange(len(prices))
is_valid = ~np.isnan(prices)
prices = np.interp(x=x, xp=x[is_valid], fp=prices[is_valid])
prices += np.random.randn(len(prices)) * 2
下面是matplotlib的示例。俗话说:买低(绿),卖高(红):
import matplotlib.pyplot as plt
# Warning! This isn't a fully correct solution, but it works for now.
# If the absolute min came after the absolute max, you'd have trouble.
mn = np.argmin(prices)
mx = mn + np.argmax(prices[mn:])
kwargs = {'markersize': 12, 'linestyle': ''}
fig, ax = plt.subplots()
ax.plot(prices)
ax.set_title('Price History')
ax.set_xlabel('Time')
ax.set_ylabel('Price')
ax.plot(mn, prices[mn], color='green', **kwargs)
ax.plot(mx, prices[mx], color='red', **kwargs)

NumPy实现是什么样的? 虽然没有np.cummin() “直接”,但NumPy的通用函数(ufuncs)都有一个accumulate()方法,它的名字暗示了:
cummin = np.minimum.accumulate
从纯Python示例扩展逻辑,你可以找到每个价格和运行最小值(元素方面)之间的差异,然后获取此序列的最大值:
def profit_with_numpy(prices):
"""Price minus cumulative minimum price, element-wise."""
prices = np.asarray(prices)
return np.max(prices - cummin(prices))
print(profit_with_numpy(prices))
print(np.allclose(profit_with_numpy(prices), profit(prices)))
结果为:
44.2487532293278
True
这两个具有相同理论时间复杂度的操作如何在实际运行时进行比较? 首先,让我们采取更长的序列。(此时不一定需要是股票价格的时间序列)
seq = np.random.randint(0, 100, size=100000)
现在,对于一个有点不公平的比较:
setup = ('from __main__ import profit_with_numpy, profit, seq;'
' import numpy as np')
num = 250
pytime = timeit('profit(seq)', setup=setup, number=num)
nptime = timeit('profit_with_numpy(seq)', setup=setup, number=num)
print('Speed difference: {:0.1f}x'.format(pytime / nptime))
结果为:Speed difference: 76.0x
在上面,将profit_with_numpy() 视为伪代码(不考虑NumPy的底层机制),实际上有三个遍历序列:
* cummin(prices) 具有O(n)时间复杂度
* prices - cummin(prices) 是 O(n)的时间复杂度
* max(...) 是O(n)的时间复杂度
这就减少到O(n),因为O(3n)只剩下O(n)-当n接近无穷大时,n “占主导地位”。
因此,这两个函数具有等价的最坏情况时间复杂度。(不过,顺便提一下,NumPy函数的空间复杂度要高得多。)。但这可能是最不重要的内容。这里我们有一个教训是:虽然理论上的时间复杂性是一个重要的考虑因素,运行时机制也可以发挥很大的作用。NumPy不仅可以委托给C,而且通过一些元素操作和线性代数,它还可以利用多线程中的计算。但是这里有很多因素在起作用,包括所使用的底层库(BLAS/LAPACK/Atlas),而这些细节完全是另一篇文章的全部内容。
NumPy中文文档搬砖(划掉)学习笔记(1)的更多相关文章
- Kotlin 中文文档
Kotlin 中文文档 标签: Kotlinkotlin中文文档 2017-02-14 18:14 4673人阅读 评论(0) 收藏 举报 分类: kotlin 转载地址:http://www.tu ...
- Phoenix综述(史上最全Phoenix中文文档)
个人主页:http://www.linbingdong.com 简书地址:http://www.jianshu.com/users/6cb45a00b49c/latest_articles 网上关于P ...
- jQuery 3.1 API中文文档
jQuery 3.1 API中文文档 一.核心 1.1 核心函数 jQuery([selector,[context]]) 接收一个包含 CSS 选择器的字符串,然后用这个字符串去匹配一组元素. jQ ...
- 【Chromium中文文档】线程
线程 转载请注明出处:https://ahangchen.gitbooks.io/chromium_doc_zh/content/zh//General_Architecture/Threading. ...
- 【Chromium中文文档】插件架构
插件架构 转载请注明出处:https://ahangchen.gitbooks.io/chromium_doc_zh/content/zh//General_Architecture/Plugin_A ...
- HYBControllerTransitions中文文档
中文文档 HYBControllerTransitions是自定义围场动画API封装类库,使用简便.使用者不需要了解太多转场动画知识,即可轻松接入项目使用. 这是一个给开发者们提供自定义push.po ...
- 【scikit-learn 0.19 中文文档 】安装 scikit-learn | ApacheCN
中文文档: http://sklearn.apachecn.org/cn/0.19.0/tutorial/basic/tutorial.html 英文文档: http://sklearn.apache ...
- phantomjs 中文文档
phantomjs 中文文档 转载 入门教程:转载 http://www.cnblogs.com/front-Thinking/p/4321720.html 1.介绍 简介 PhantomJS是一 ...
- IdentityServer4 中文文档 -14- (快速入门)使用 ASP.NET Core Identity
IdentityServer4 中文文档 -14- (快速入门)使用 ASP.NET Core Identity 原文:http://docs.identityserver.io/en/release ...
随机推荐
- 一起来学习LiteOS中断模块的源代码
摘要:本文带领大家一起剖析了LiteOS中断模块的源代码. 本文我们来一起学习下LiteOS中断模块的源代码,文中所涉及的源代码,均可以在LiteOS开源站点https://gitee.com/Lit ...
- Servlet原理解析&使用指南
Servlet(Server Applet)全称Java Servlet,是用Java编写的服务器端程序.广义上指任何实现了Server接口的类,主要功能在于交互式地浏览和生成数据,生成动态Web内容 ...
- Elasticsearch 复合查询——多字符串多字段查询
前言 有时我们在搜索电影的时候,包含了多个条件,比如主演是周星驰,打分8分以上,上映时间是1990年~2001年的,那么Elasticsearch又该如何帮我们做查询呢?这里我们可以用 bool 查询 ...
- 剑指 Offer 03. 数组中重复的数字
剑指 Offer 03. 数组中重复的数字 找出数组中重复的数字. 在一个长度为 n 的数组 nums 里的所有数字都在 0-n-1 的范围内.数组中某些数字是重复的,但不知道有几个数字重复了,也不知 ...
- 优化 ASP.NET Core Docker 镜像的大小
在这容器化的世界里,我们已经很少直接通过文件发布来运行asp.net core程序了.现在大多数情况下,我们都会使用docker来运行程序.在使用docker之前,我们往往需要打包我们的应用程序.as ...
- ElasticSearch实战系列十: ElasticSearch冷热分离架构
前言 本文主要介绍ElasticSearch冷热分离架构以及实现. 冷热分离架构介绍 冷热分离是目前ES非常火的一个架构,它充分的利用的集群机器的优劣来实现资源的调度分配.ES集群的索引写入及查询速度 ...
- 1.设置和验证MySQL数据库的隔离级别
登录数据库 mysql -u root - p 新建用户,各启动一个事物,用于同时操作数据库表中数据 create user tom identified by 'tom'; 然后同时再用该用户启动M ...
- 简单的介绍一下Java设计模式:解释器模式
目录 定义 意图 主要解决问题 优缺点 结构 示例 适用情况 定义 解释器模式是类的行为型模式,给定一个语言之后,解释器模式可以定义出其文法的一种表示,并同时提供一个解释器,客户端可以使用这个解释器来 ...
- C++ 内存模型之单独编译
单独编译得意义 将一个程序分成多个文件按保存,如果过对程序修改,找到要修改得文件进行修改后重新编译,则可以之重新编译该文件,然后后将他于其他文件得编译版本链接,是的大程序得管理更加高效便捷. 将单文件 ...
- Message Decoding UVA - 213
Some message encoding schemes require that an encoded message be sent in two parts. The fifirst par ...