NumPy和SciPy中的阶乘函数

81
我该如何分别从Numpy和Scipy中导入阶乘函数以查看哪个更快?
我已经通过“import math”从Python中导入了阶乘函数。但是,它对于Numpy和Scipy无效。
6个回答

99

你可以这样导入它们:

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


64

对于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循环更易于编码和更快速。

14
scipy.misc.factorial 的好处在于它仅对数组中最大的数计算一次阶乘,其余的阶乘作为副作用在该过程中计算。 - Antony Hatchkins
15
弃用警告:在scipy 1.0.0中,请使用scipy.special.factorial - lincolnfrias
2
如果需要的话,scipy.special.factorial 也可以使用伽马函数来估算值。 - Nathan Musoke

29

SciPy有函数scipy.special.factorial(原名scipy.misc.factorial

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

7
    from numpy import prod

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

或者使用operator模块中的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))

3

enter image description here

运行不同人编写的阶乘函数后,结果显示math.factorial是计算阶乘最快的。

请查看附图以获取各个函数的运行时间。


...最快计算一个“单一”值。在这种情况下,我认为这并不重要。但通常情况下,您希望对多个值进行计算,例如一个数组。也许可以重新运行基准测试,使用10^5个值或类似的数量。 - Mayou36

1
你可以将一些自制的阶乘函数保存在一个名为 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在另一篇帖子中提出的框架,寻找如何在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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接