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 ...
随机推荐
- python基础(8)python中is和==的区别详解
前置知识点 当我们创建一个对象时,我们要知道它内部干了些什么 1.创建了一个随机id,开辟了一片内存地址 2.自动声明了这个对象的类型type 3.给这个对象赋值value 小例子 a = 1 pri ...
- 如何在 C# 中使用 ArrayPool 和 MemoryPool
对资源的可复用是提升应用程序性能的一个非常重要的手段,比如本篇要分享的 ArrayPool 和 MemoryPool,它们就有效的减少了内存使用和对GC的压力,从而提升应用程序性能. 什么是 Arra ...
- frameset、frame和div 、iframe
框架一般应用于首页的界面排版工作.把一个网页切割成多个页面管理.frame文件一般只包含框架的布局信息,不会包含其他内容,所有的页面效果都是在各个frameset页面内显示.他们都从属于frame文件 ...
- YoloV3 记录
常用于目标检测,因为最近要从目标分类问题转到目标检测中去. tensoflow.Keras(大公司一般都用这个).pytorch(本次学习)------------------主要框架 程序设计模块规 ...
- 修改RedHat7的root用户密码
前言 前段时间由于长时间没有使用虚拟机里面的一个操作系统,导致密码记得不是太清,登录不进去.今天想起还是做个小记录,以便以后参考. 再一个是,当时网上也搜了很多解决问题的博客,但大部分都是同一个博客内 ...
- 常用开发库 - 告別BeanUtils拷贝,MapStruct工具库最全详解
常用开发库 - MapStruct工具库详解 MapStruct是一款非常实用Java工具,主要用于解决对象之间的拷贝问题,比如PO/DTO/VO/QueryParam之间的转换问题.区别于BeanU ...
- 从新建文件夹开始构建UtopiaEngine(1)
序言 在苦等了半年多之后,我终于开始了向往已久的实时NPR游戏引擎项目--Utopia Engine,这半年多一直为了构建这个引擎在做很多准备:多线程.动态链接库.脚本引擎.立即渲染GUI--统统吃了 ...
- python中zip函数的使用
zip(*iterables) zip可以将多个可迭代对象组合成一个迭代器对象,通过迭代取值,可以得到n个长度为m的元组.其中n为长度最短可迭代对象的元素个数,m为可迭代对象的个数.并且每个元组的第i ...
- 使用python的虚拟环境virtualenv
技术背景 在前面几篇博客中我们介绍了容器的使用(博客1.博客2.博客3.博客4.博客5),容器是一种系统级的隔离方案,更多的强调资源上的隔离.而这里我们要介绍的python的虚拟环境,更加强调的是依赖 ...
- 生产中使用ssh-copy-id复制公钥到多台服务器
在系统运维的时候,可能免密码通过ssh方式登录到远程主机,这时就首先需要将本机的公钥复制到远程主机,用 ssh-copy-id 命令可以轻松做到. 对于单台远程主机,直接使用命令就可以了 # 生成密钥 ...