SciPy和NumPy的关系

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

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

  • numpy.log10是一个返回负参数nan的ufunc;
  • scipy.log10返回负参数的复杂值,并且似乎不是一个ufunc。

对于loglog2logn也是如此,但对于log1p[2]则不然。

另一方面,numpy.expscipy.exp似乎是同一个ufunc的不同名称。scipy.log1pnumpy.log1p也是如此。

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

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

[1] numpy.minnumpy.maxnumpy.abs和其他一些在scipy命名空间中没有对应的对象。

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

55669 次浏览

SciPy参考指南:

< p >…所有Numpy函数都有 被包含在scipy中 命名空间,所有这些 函数不需要 额外导入Numpy.

这样做的目的是让用户不必知道scipynumpy名称空间之间的区别,尽管显然你已经发现了一个例外。

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

from numpy import *

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

你描述的log10行为很有趣,因为这两个版本来自numpy。一个是ufunc函数,另一个是numpy.lib函数。为什么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.
"""

该模块似乎覆盖了sqrtloglog2lognlog10powerarccosarcsinarctanh的基本numpy ufuncs。这就解释了你所看到的行为。这样做的潜在设计原因可能隐藏在某个邮件列表帖子中。

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

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

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

关于linalg包- scipy函数将调用lapack和blas,它们在许多平台上都有高度优化的版本,并提供非常好的性能,特别是在相当大的密集矩阵上的操作。另一方面,它们不是容易编译的库,需要fortran编译器和许多特定于平台的调整才能获得完整的性能。因此,numpy提供了许多常见线性代数函数的简单实现,这些函数通常足以满足许多目的。

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

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

我认为这将允许对所有涉及的包有足够知识的人准确地区分一些 scipy和numpy函数之间的区别(它根本没有帮助我回答log10问题)。我肯定没有这方面的知识,但source确实表明scipy.linalg.solvenumpy.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))

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

SciPy常见问题解答来看,NumPy中的一些函数是由于历史原因而出现在这里的,而这是应该的 只有在SciPy:

NumPy和SciPy的区别是什么?

在理想情况下,NumPy只包含数组数据类型和 最基本的操作:索引,排序,重塑,基本 Elementwise函数,等等。所有数字代码都将驻留在 SciPy。然而,NumPy的重要目标之一是兼容性,因此NumPy 尝试保留其前任版本所支持的所有特性。因此 NumPy包含一些线性代数函数,尽管这些函数 完全属于SciPy。在任何情况下,SciPy包含更全面的功能 版本的线性代数模块,以及其他许多数值 算法。如果你正在使用python进行科学计算,你应该这样做 可能同时安装NumPy和SciPy。大多数新特性都属于SciPy 而不是NumPy.

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

我没有看到SethMMorton对相关的问题的答案

除了SciPy常见问题解答描述复制主要是为了向后兼容外,在NumPy文档中进一步澄清说

可选的scipy加速例程(numpy.dual)

可由Scipy加速的函数的别名。

可以构建SciPy以使用加速或其他改进的库 FFTs,线性代数和特殊函数。这个模块允许 开发人员透明地支持这些加速功能时 SciPy是可用的,但仍然支持只安装了SciPy的用户 NumPy . < / p >

为了简单起见,这些是:

  • 线性代数
  • FFT
  • 一类改进的0阶贝塞尔函数

同样,从SciPy教程:

SciPy的顶层还包含NumPy和 numpy.lib.scimath。但是,最好直接从

因此,对于新的应用程序,您应该更喜欢使用在SciPy顶层复制的NumPy版本的数组操作。对于上面列出的域,您应该选择SciPy中的域,并在必要时检查NumPy中的向后兼容性。

根据我个人的经验,我使用的大多数数组函数都存在于NumPy的顶层(random除外)。然而,所有特定于领域的例程都存在于SciPy的子包中,因此我很少使用来自SciPy顶层的任何东西。

选自'数量经济'讲座

SciPy是一个包,它包含各种构建在NumPy之上的工具,使用NumPy的数组数据类型和相关功能

事实上,当我们导入SciPy时,我们也得到了NumPy,这可以从SciPy初始化文件中看到

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


__all__  = []
__all__ += _num.__all__
__all__ += ['randn', 'rand', 'fft', 'ifft']


del _num
# Remove the linalg imported from numpy so that the scipy.linalg package can be
# imported.
del linalg
__all__.remove('linalg')

但是,显式地使用NumPy功能是更常见和更好的实践

import numpy as np


a = np.identity(3)

SciPy中有用的是其子包中的功能吗

  • scipy。优化,scipy,整合,scipy。统计数据等。