SciPy似乎在它自己的命名空间中提供了NumPy的大部分(但不是所有[1])函数。换句话说,如果有一个名为numpy的函数。Foo,几乎可以肯定有一个sciy。Foo。大多数情况下,两者看起来完全相同,甚至经常指向相同的函数对象。

有时候,它们是不同的。举一个最近出现的例子:

numpy。log10是一个返回负参数nan的ufunc; scipy。Log10返回负参数的复杂值,并且看起来不是一个ufunc。

对于log、log2和logn也是如此,但对于log1p[2]则不然。

另一方面,numpy。Exp和scipy。Exp似乎是同一个ufunc的不同名称。scipy也是如此。Log1p和numpy.log1p。

另一个例子是numpy.linalg.solve vs scipy.linalg.solve。它们很相似,但后者比前者提供了一些额外的功能。

为什么会出现明显的重复?如果这意味着将numpy大量导入到scipy名称空间中,那么为什么会出现行为上的细微差异和缺少函数呢?是否有一些总体逻辑可以帮助理清混乱?

[1] numpy。分钟,numpy。马克斯,numpy。Abs和其他一些名称在scipy名称空间中没有对应的名称。

[2]使用NumPy 1.5.1和SciPy 0.9.0rc2测试。


当前回答

Regarding the linalg package - the scipy functions will call lapack and blas, which are available in highly optimised versions on many platforms and offer very good performance, particularly for operations on reasonably large dense matrices. On the other hand, they are not easy libraries to compile, requiring a fortran compiler and many platform specific tweaks to get full performance. Therefore, numpy provides simple implementations of many common linear algebra functions which are often good enough for many purposes.

其他回答

Regarding the linalg package - the scipy functions will call lapack and blas, which are available in highly optimised versions on many platforms and offer very good performance, particularly for operations on reasonably large dense matrices. On the other hand, they are not easy libraries to compile, requiring a fortran compiler and many platform specific tweaks to get full performance. Therefore, numpy provides simple implementations of many common linear algebra functions which are often good enough for many purposes.

来自维基百科(http://en.wikipedia.org/wiki/NumPy#History):

数字代码被用来制造 它更易于维护和灵活 足以实现新功能 Numarray。这个新项目是 SciPy。避免安装整体 来获取一个数组对象, 这个新包裹被分开了 叫NumPy。

Scipy依赖于numpy,为了方便起见,它将许多numpy函数导入到它的命名空间中。

上次检查时,scipy __init__方法执行了一个

from numpy import *

以便在导入scipy模块时将整个numpy名称空间包含到scipy中。

您描述的log10行为很有趣,因为两个版本都来自numpy。一个是ufunc,另一个是numpy。自由的功能。为什么scipy更喜欢库函数而不是ufunc,我不知道在我的头顶上。


编辑:事实上,我可以回答log10的问题。在scipy __init__方法中,我看到了以下内容:

# Import numpy symbols to scipy name space
import numpy as _num
from numpy import oldnumeric
from numpy import *
from numpy.random import rand, randn
from numpy.fft import fft, ifft
from numpy.lib.scimath import *

在scipy中获得的log10函数来自numpy.lib.scimath。看看这段代码,它说:

"""
Wrapper functions to more user-friendly calling of certain math functions
whose output data-type is different than the input data-type in certain
domains of the input.

For example, for functions like log() with branch cuts, the versions in this
module provide the mathematically valid answers in the complex plane:

>>> import math
>>> from numpy.lib import scimath
>>> scimath.log(-math.exp(1)) == (1+1j*math.pi)
True

Similarly, sqrt(), other base logarithms, power() and trig functions are
correctly handled.  See their respective docstrings for specific examples.
"""

该模块似乎覆盖了sqrt, log, log2, logn, log10, power, arccos, arcsin和arctanh的基本numpy ufuncs。这就解释了你所看到的行为。这样做的潜在设计原因可能隐藏在某个邮件列表帖子中。

从SciPy FAQ来看,NumPy的一些函数是由于历史原因而出现的,而这是应该的 只有在SciPy:

What is the difference between NumPy and SciPy? In an ideal world, NumPy would contain nothing but the array data type and the most basic operations: indexing, sorting, reshaping, basic elementwise functions, et cetera. All numerical code would reside in SciPy. However, one of NumPy’s important goals is compatibility, so NumPy tries to retain all features supported by either of its predecessors. Thus NumPy contains some linear algebra functions, even though these more properly belong in SciPy. In any case, SciPy contains more fully-featured versions of the linear algebra modules, as well as many other numerical algorithms. If you are doing scientific computing with python, you should probably install both NumPy and SciPy. Most new features belong in SciPy rather than NumPy.

这就解释了为什么scipy.linalg.solve比numpy.linalg.solve提供了一些额外的特性。

我没有看到塞瑟姆·莫顿对相关问题的回答

在SciPy文档介绍的末尾有一个简短的注释:

另一个有用的命令是source。当给出一个用Python编写的函数作为参数时,它会打印出该函数的源代码列表。这对于学习算法或准确理解函数是什么很有帮助 处理它的参数。此外,不要忘记Python命令dir 用于查看模块或包的名称空间。

我认为这将允许对所涉及的所有包有足够知识的人准确地区分一些scipy和numpy函数之间的差异(这对我回答log10问题完全没有帮助)。我肯定没有这方面的知识,但来源确实表明scipy.linalg.solve和numpy.linalg.solve以不同的方式与lapack交互;

Python 2.4.3 (#1, May  5 2011, 18:44:23) 
[GCC 4.1.2 20080704 (Red Hat 4.1.2-50)] on linux2
>>> import scipy
>>> import scipy.linalg
>>> import numpy
>>> scipy.source(scipy.linalg.solve)
In file: /usr/lib64/python2.4/site-packages/scipy/linalg/basic.py

def solve(a, b, sym_pos=0, lower=0, overwrite_a=0, overwrite_b=0,
          debug = 0):
    """ solve(a, b, sym_pos=0, lower=0, overwrite_a=0, overwrite_b=0) -> x

    Solve a linear system of equations a * x = b for x.

    Inputs:

      a -- An N x N matrix.
      b -- An N x nrhs matrix or N vector.
      sym_pos -- Assume a is symmetric and positive definite.
      lower -- Assume a is lower triangular, otherwise upper one.
               Only used if sym_pos is true.
      overwrite_y - Discard data in y, where y is a or b.

    Outputs:

      x -- The solution to the system a * x = b
    """
    a1, b1 = map(asarray_chkfinite,(a,b))
    if len(a1.shape) != 2 or a1.shape[0] != a1.shape[1]:
        raise ValueError, 'expected square matrix'
    if a1.shape[0] != b1.shape[0]:
        raise ValueError, 'incompatible dimensions'
    overwrite_a = overwrite_a or (a1 is not a and not hasattr(a,'__array__'))
    overwrite_b = overwrite_b or (b1 is not b and not hasattr(b,'__array__'))
    if debug:
        print 'solve:overwrite_a=',overwrite_a
        print 'solve:overwrite_b=',overwrite_b
    if sym_pos:
        posv, = get_lapack_funcs(('posv',),(a1,b1))
        c,x,info = posv(a1,b1,
                        lower = lower,
                        overwrite_a=overwrite_a,
                        overwrite_b=overwrite_b)
    else:
        gesv, = get_lapack_funcs(('gesv',),(a1,b1))
        lu,piv,x,info = gesv(a1,b1,
                             overwrite_a=overwrite_a,
                             overwrite_b=overwrite_b)

    if info==0:
        return x
    if info>0:
        raise LinAlgError, "singular matrix"
    raise ValueError,\
          'illegal value in %-th argument of internal gesv|posv'%(-info)

>>> scipy.source(numpy.linalg.solve)
In file: /usr/lib64/python2.4/site-packages/numpy/linalg/linalg.py

def solve(a, b):
    """
    Solve the equation ``a x = b`` for ``x``.

    Parameters
    ----------
    a : array_like, shape (M, M)
        Input equation coefficients.
    b : array_like, shape (M,)
        Equation target values.

    Returns
    -------
    x : array, shape (M,)

    Raises
    ------
    LinAlgError
        If `a` is singular or not square.

    Examples
    --------
    Solve the system of equations ``3 * x0 + x1 = 9`` and ``x0 + 2 * x1 = 8``:

    >>> a = np.array([[3,1], [1,2]])
    >>> b = np.array([9,8])
    >>> x = np.linalg.solve(a, b)
    >>> x
    array([ 2.,  3.])

    Check that the solution is correct:

    >>> (np.dot(a, x) == b).all()
    True

    """
    a, _ = _makearray(a)
    b, wrap = _makearray(b)
    one_eq = len(b.shape) == 1
    if one_eq:
        b = b[:, newaxis]
    _assertRank2(a, b)
    _assertSquareness(a)
    n_eq = a.shape[0]
    n_rhs = b.shape[1]
    if n_eq != b.shape[0]:
        raise LinAlgError, 'Incompatible dimensions'
    t, result_t = _commonType(a, b)
#    lapack_routine = _findLapackRoutine('gesv', t)
    if isComplexType(t):
        lapack_routine = lapack_lite.zgesv
    else:
        lapack_routine = lapack_lite.dgesv
    a, b = _fastCopyAndTranspose(t, a, b)
    pivots = zeros(n_eq, fortran_int)
    results = lapack_routine(n_eq, n_rhs, a, n_eq, pivots, b, n_eq, 0)
    if results['info'] > 0:
        raise LinAlgError, 'Singular matrix'
    if one_eq:
        return wrap(b.ravel().astype(result_t))
    else:
        return wrap(b.transpose().astype(result_t))

这也是我的第一个帖子,所以如果我应该改变什么,请告诉我。