numpy 和 scipy 中的阶乘

Posted

技术标签:

【中文标题】numpy 和 scipy 中的阶乘【英文标题】:Factorial in numpy and scipy 【发布时间】:2014-03-12 07:23:17 【问题描述】:

如何分别从 numpy 和 scipy 导入阶乘函数以查看哪个更快?

我已经通过 import math 从 python 本身导入了阶乘。但是,它不适用于 numpy 和 scipy。

【问题讨论】:

【参考方案1】:

您可以像这样导入它们:

In [7]: import scipy, numpy, math                                                          

In [8]: scipy.math.factorial, numpy.math.factorial, math.factorial
Out[8]: 
(<function math.factorial>,                                                                
 <function math.factorial>,                                                                
 <function math.factorial>)

scipy.math.factorialnumpy.math.factorial 似乎只是math.factorial 的别名/引用,即scipy.math.factorial is math.factorialnumpy.math.factorial is math.factorial 都应该给出True

【讨论】:

【参考方案2】:

Ashwini 的答案很好,指出 scipy.math.factorialnumpy.math.factorialmath.factorial 是相同的功能。但是,我建议使用 Janne 提到的那个,scipy.special.factorial 是不同的。来自 scipy 的可以将np.ndarray 作为输入,而其他的则不能。

In [12]: import scipy.special

In [13]: temp = np.arange(10) # temp is an np.ndarray

In [14]: math.factorial(temp) # This won't work
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-14-039ec0734458> in <module>()
----> 1 math.factorial(temp)

TypeError: only length-1 arrays can be converted to Python scalars

In [15]: scipy.special.factorial(temp) # This works!
Out[15]: 
array([  1.00000000e+00,   1.00000000e+00,   2.00000000e+00,
         6.00000000e+00,   2.40000000e+01,   1.20000000e+02,
         7.20000000e+02,   5.04000000e+03,   4.03200000e+04,
         3.62880000e+05])

因此,如果您对 np.ndarray 进行阶乘,那么来自 scipy 的那个将比执行 for 循环更容易编码和更快。

【讨论】:

scipy.misc.factorial 的好处是它只计算一次阶乘——对于数组中的最大数。所有其他都被计算为过程中的副作用。 弃用警告:在 scipy 1.0.0.使用scipy.special.factorial 如果需要,scipy.special.factorial 还可以使用 gamma 函数估计值。【参考方案3】:

SciPy 有函数scipy.special.factorial(以前的scipy.misc.factorial

>>> import math
>>> import scipy.special
>>> math.factorial(6)
720
>>> scipy.special.factorial(6)
array(720.0)

【讨论】:

【参考方案4】:
    from numpy import prod

    def factorial(n):
        print prod(range(1,n+1))

或使用运算符的 mul:

    from operator import mul

    def factorial(n):
        print reduce(mul,range(1,n+1))

或完全没有帮助:

    def factorial(n):
        print reduce((lambda x,y: x*y),range(1,n+1))

【讨论】:

【参考方案5】:

在不同的人对阶乘运行不同的上述函数后,结果证明 math.factorial 是计算阶乘的最快速度。

在附图中查找不同功能的运行时间

【讨论】:

【参考方案6】:

您可以将一些自制的阶乘函数保存在单独的模块 utils.py 中,然后导入它们并使用 timeit 在 scipy、numpy 和 math 中将其性能与预定义的函数进行比较。 在这种情况下,我使用了 Stefan Gruenwald 最后提出的外部方法:

import numpy as np


def factorial(n):
    return reduce((lambda x,y: x*y),range(1,n+1))

主要代码(我在另一篇文章中使用了 JoshAdel 提出的框架,查找 how-can-i-get-an-array-of-alternating-values-in-python):

from timeit import Timer
from utils import factorial
import scipy

    n = 100

    # test the time for the factorial function obtained in different ways:

    if __name__ == '__main__':

        setupstr="""
    import scipy, numpy, math
    from utils import factorial
    n = 100
    """

        method1="""
    factorial(n)
    """

        method2="""
    scipy.math.factorial(n)  # same algo as numpy.math.factorial, math.factorial
    """

        nl = 1000
        t1 = Timer(method1, setupstr).timeit(nl)
        t2 = Timer(method2, setupstr).timeit(nl)

        print 'method1', t1
        print 'method2', t2

        print factorial(n)
        print scipy.math.factorial(n)

提供:

method1 0.0195569992065
method2 0.00638914108276

93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000
93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000


Process finished with exit code 0

【讨论】:

以上是关于numpy 和 scipy 中的阶乘的主要内容,如果未能解决你的问题,请参考以下文章

如何检查 NumPy 和 SciPy 中的 BLAS/LAPACK 链接?

使用 scipy 和 numpy 中的函数计算 z 分数

numpy/scipy 中的平方差总和 (SSD)

Matlab 中的 FFT 和 numpy / scipy 给出不同的结果

N点与numpy/scipy中的参考之间的有效距离计算

如何删除 NumPy/SciPy 中的一些变量?