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 ...
随机推荐
- 使用nodejs进行了简单的文件分卷工具
关键词:node fs readline generator (在这之前需要声明的是这篇博客的应用范围应该算是相当狭隘,写出来主要也就是给自己记录一下临时兴起写的一个小工具,仅从功能需求上来说我相信是 ...
- python 常用库收集
读者您好.今天我将介绍20个属于我常用工具的Python库,我相信你看完之后也会觉得离不开它们.他们是: Requests.Kenneth Reitz写的最富盛名的http库.每个Python程序员都 ...
- 创建ortools的Dockerfile
技术背景 基于已有的Docker容器镜像,去创建一个本地的镜像,有两种方法:一种是在之前的博客中提到过的,使用docker commit的方案,也就是先进去基础系统镜像内部完成所需的修改,然后comm ...
- (十四--十五)数据库查询优化Part I
(十四--十五)数据库查询优化Part I 如果理解的有问题.欢迎大家指出.这也是我在看课记得笔记..可能会有很多问题 查询优化的重要性 请记住用户只会告诉DMBS他们想要什么样的结果,而不会告诉他们 ...
- Git基础知识之内部状态管理系统
本文主要来介绍一下 Git 的内部状态管理系统.它利用基于节点和指针的数据结构来跟踪及管理编辑操作的时间线. 对本地项目而言,任一时刻,Git 处于三种状态中的一种:工作区状态.暂存区状态和提交区状态 ...
- 写个小程序01 | 注册微信小程序
出于兴趣和学习目的,我想自己做一个基于"子弹笔记(Bullet Journal)"的小程序.由于个人开发经验很有限,只在课程作业中写过 web 前端,所以也不知道多久能写出来(逃) ...
- var=value?export前后差在哪?-- Shell十三问<第五问>
var=value?export前后差在哪?-- Shell十三问<第五问> 这次让我们暂时丢开 command line ,先来了解一下 bash 变量(variable)吧.所谓的 变 ...
- [模拟]P1046 陶陶摘苹果
陶陶摘苹果 ## 题目描述 陶陶家的院子里有一棵苹果树,每到秋天树上就会结出10个苹果.苹果成熟的时候,陶陶就会跑去摘苹果.陶陶有个30厘米高的板凳,当她不能直接用手摘到苹果的时候,就会踩到板凳上再试 ...
- ionic3 清除navpush的堆栈 (android真机返回键bug)
清除navpush的堆栈可以使用 方法一:ionic3文档 this.navCtrl.popToRoot(); //直接返回根组件 方法二: push 后再删除之前页面即可. this.navCtrl ...
- 如何在IDEA中进行时序图分析
方法一: 使用插件 SequenceDiagram (系统自动生成) 使用方法: 下载插件,我们可以在 Plugins 中找到 选中线程方法名,然后右键就可以创建此方法的时序图了 参数设置 生成效果以 ...