有什么方法可以在不使用For‘s in NumPy的情况下实现循环吗?
将np.add
与out
关键字配合使用使用dtype="int"
import numpy as np
N = 100
fib = np.zeros(N, dtype=np.int)
fib[:2] = 1.
np.add(fib[:-2], fib[1:-1], out=fib[2:])
print(fib[:10])
输出:[ 1 1 2 3 5 8 13 21 34 55]
但是,如果dtype
更改为np.Float
import numpy as np
N = 100
fib = np.zeros(N, dtype=np.float)
fib[:2] = 1.
np.add(fib[:-2], fib[1:-1], out=fib[2:])
print(fib[:10])
输出:[ 1. 1. 2. 1. 3. 1. 4. 1. 5. 1.]
有人能告诉我为什么吗?或者其他进行递归的方法?
4条答案
按热度按时间mcdcgff01#
您的
add
适用于此计算,但必须重复应用,以便传播非零值。我不明白您的计算是如何生成[ 1. 1. 2. 1. 3. 1. 4. 1. 5. 1.]
的。(编辑-请注意,第一个
np.add
的作用就像它是完全缓冲的一样。将**处的结果与对象数组和浮点数组进行比较。我在Py3上使用的是1.13.1版。)或者突出每个阶段的好的价值
fib[2:] = fib[:-2]+fib[1:-1]
做同样的事情。正如
ufunc.at
的文档中所讨论的,像np.add
这样的操作使用缓冲,即使使用out
参数也是如此。因此,尽管它们在C
级别代码中迭代,但它们不会累加;也就是说,ith
步骤的结果不会在i+1
步骤中使用。add.at
可用于执行无缓冲的a[i] += b
。当索引包含DUPICATE时,这很方便。但它不允许从更改后的a
值反馈到b
。所以它在这里没有用处。也是
add.accumulate
(也称为np.cumsum
),对于某些迭代定义很方便。但在一般情况下很难适用。cumprod
(乘法累加)可以使用qmatrix
方法Numpy's matrix_power function giving wrong results for large exponents
使用
np.matrix
定义qmatrix
,因此*
乘法表示矩阵乘积(而不是元素乘积):用指向该矩阵的副本(实际上是指针)填充对象矩阵。
应用
cumprod
,并从每个矩阵中提取一个元素。链接答案使用
numpy.linalg.matrix_power
,它也做重复的矩阵乘积。对于单个电源,matrix_power
更快,但对于整个电源范围,cumprod
更快。fwzugrvs2#
以下是使用Scipy过滤器的一种相当有效的方法:
(请注意,我们不能使用
lfilter
,因为在信号处理方面,lfilter
是一个不稳定的过滤器,会导致Python解释器崩溃,因此我们必须转换为二阶部分形式。)过滤方法的问题是,我不确定它是否可以推广到解决一个ODE的实际问题。
另一种解决方案是简单地用Python编写循环,并使用JIT compiler加速它:
JIT方法的优点是您可以实现所有花哨的东西,但如果您坚持使用简单的循环和分支,而不调用任何(非JIT)的Python函数,那么它工作得最好。
计时结果:
Scipy Filter方法比纯Python循环快,但比JITted循环慢。我猜Filter函数是相对通用的,它做了我们在这里不需要的事情,而JITted循环被编译成一个非常小的循环。
mw3dktmi3#
一个可能不是超级有效但有趣的解决方案是像这样滥用
scipy.linalg.solve_banded
它的工作原理是我们写成F_0,F_1,F_2…作为一个向量F和恒等式-F_{i-1}-F_i+F{i+1}=0作为一个很好的带状矩阵,然后求F。请注意,这可以适用于其他类似的递推。
7kjnsjlb4#
由于线性递归有解析解(这里是斐波那契),另一种快速的方法是:
运行:
您可以将其调整为任何线性方程。