web-dev-qa-db-fra.com

Relation entre SciPy et NumPy

SciPy semble fournir la plupart (mais pas la totalité [1]) des fonctions de NumPy dans son propre espace de noms. En d’autres termes, s’il existe une fonction nommée numpy.foo, il y a presque certainement un scipy.foo. La plupart du temps, les deux semblent être exactement les mêmes, pointant même parfois vers le même objet fonction.

Parfois, ils sont différents. Pour donner un exemple qui a été soulevé récemment:

  • numpy.log10 est un func qui renvoie les NaN pour les arguments négatifs;
  • scipy.log10 renvoie des valeurs complexes pour les arguments négatifs et ne semble pas être un ufunc.

On peut dire la même chose de log, log2 et logn, mais pas à propos de log1p [2].

D'autre part, numpy.exp et scipy.exp semblent être des noms différents pour le même ufunc. Ceci est également vrai de scipy.log1p et numpy.log1p.

Un autre exemple est numpy.linalg.solve contre scipy.linalg.solve. Ils sont similaires, mais le dernier offre des fonctionnalités supplémentaires sur le premier.

Pourquoi la duplication apparente? Si ceci est censé être une importation en gros de numpy dans l'espace de noms scipy, pourquoi les différences subtiles de comportement et les fonctions manquantes? Existe-t-il une logique globale qui aiderait à dissiper la confusion?

[1] numpy.min, numpy.max, numpy.abs et quelques autres n'ont pas d'équivalent dans l'espace de noms scipy.

[2] Testé avec NumPy 1.5.1 et SciPy 0.9.0rc2.

241
NPE

La dernière fois que j’ai vérifié, la méthode scipy __init__ exécute un

from numpy import *

de sorte que tout l’espace de noms numpy soit inclus dans scipy lors de l’importation du module scipy.

Le comportement log10 que vous décrivez est intéressant, car les deux les versions proviennent de numpy. L'un est un ufunc, l'autre est une fonction numpy.lib. Pourquoi scipy préfère la fonction de bibliothèque au ufunc, je ne le sais pas par coeur.


EDIT: En fait, je peux répondre à la question log10. En regardant dans la méthode scipy __init__, je vois ceci:

# 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 *

La fonction log10 que vous obtenez dans Scipy provient de numpy.lib.scimath. En regardant ce code, il est écrit:

"""
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.
"""

Il semble que le module se superpose à la base numpy ufuncs pour sqrt, log, log2, logn, log10, power, arccos, arcsin et arctanh. Cela explique le comportement que vous observez. La raison sous-jacente pour laquelle cela est fait est probablement enterrée quelque part dans une publication.

133
talonmies

Du Guide de référence SciPy:

... toutes les fonctions Numpy ont été incorporées dans l'espace de noms scipy afin qu'elles soient toutes disponibles sans importer Numpy en plus.

L'intention est que les utilisateurs n'aient pas à connaître la distinction entre les espaces de noms scipy et numpy, bien qu'apparemment vous ayez trouvé une exception.

52
John D. Cook

D'après la FAQ de SciPy , certaines fonctions de NumPy sont ici pour des raisons historiques, alors qu'elles ne devraient l'être que dans SciPy:

Quelle est la différence entre NumPy et SciPy?

Dans un monde idéal, NumPy ne contiendrait que le type de données tableau et les opérations les plus élémentaires: indexation, tri, refaçonnage, fonctions élémentaires élémentaires, etc. Tout code numérique résiderait dans SciPy. Cependant, l’un des objectifs importants de NumPy étant la compatibilité, NumPy essaie de conserver toutes les fonctionnalités prises en charge par l’un de ses prédécesseurs. Ainsi, NumPy contient des fonctions d’algèbre linéaire, même si celles-ci appartiennent plus exactement à SciPy. Dans tous les cas, SciPy contient des versions plus complètes des modules d'algèbre linéaire, ainsi que de nombreux autres algorithmes numériques. Si vous faites de l'informatique scientifique avec Python, vous devriez probablement installer à la fois NumPy et SciPy. La plupart des nouvelles fonctionnalités appartiennent à SciPy plutôt qu'à NumPy.

Cela explique pourquoi scipy.linalg.solve offre quelques fonctionnalités supplémentaires par rapport à numpy.linalg.solve.

Je n'ai pas vu la réponse de SethMMorton au question connexe

48
PhML

Il y a un court commentaire à la fin de la documentation introduction à SciPy :

Une autre commande utile est source. Lorsqu'une fonction écrite en argument Python), elle affiche une liste du code source de cette fonction. Cela peut être utile pour en savoir plus sur un algorithme ou pour comprendre exactement ce que fait une fonction. avec ses arguments. N'oubliez pas non plus le répertoire de commande Python qui peut être utilisé pour examiner l’espace de noms d’un module ou d’un package.

Je pense que cela permettra à une personne ayant une connaissance suffisante de tous les paquetages impliqués de distinguer exactement quelles sont les différences entre certaines fonctions scipy et numpy t m'aide pas du tout avec la question log10). Je n'ai certainement pas cette connaissance mais source indique que scipy.linalg.solve et numpy.linalg.solve interagir avec lapack de différentes manières;

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))

Ceci est également mon premier message, donc si je devais changer quelque chose ici, faites-le-moi savoir.

12
dshort

De Wikipedia ( http://en.wikipedia.org/wiki/NumPy#History ):

Le code numérique a été adapté pour le rendre plus facile à gérer et suffisamment souple pour mettre en œuvre les nouvelles fonctionnalités de Numarray. Ce nouveau projet faisait partie de SciPy. Pour éviter d'installer un paquet entier juste pour obtenir un objet tableau, ce nouveau paquet a été séparé et appelé NumPy.

scipy dépend de numpy et importe de nombreuses fonctions numpy dans son espace de noms par commodité.

7
Mu Mind

En ce qui concerne le paquetage linalg, les fonctions scipy appellent lapack et blas, disponibles dans des versions hautement optimisées sur de nombreuses plates-formes et offrent de très bonnes performances, en particulier pour les opérations sur des matrices denses assez grandes. D'autre part, ce ne sont pas des bibliothèques faciles à compiler, nécessitant un compilateur fortran et de nombreux réglages spécifiques à la plate-forme pour obtenir des performances optimales. Par conséquent, numpy fournit des implémentations simples de nombreuses fonctions d’algèbre linéaire communes, qui sont souvent suffisantes à de nombreuses fins.

4
DaveP

En plus de SciPy FAQ , la description de la duplication est principalement destinée à la compatibilité ascendante. Elle est également clarifiée dans le documentation de NumPy pour dire que

Éventuellement des routines accélérées par SciPy (numpy.dual)

Alias ​​de fonctions pouvant être accélérées par Scipy.

SciPy peut être construit pour utiliser des bibliothèques accélérées ou améliorées pour les FFT, l'algèbre linéaire et les fonctions spéciales. Ce module permet aux développeurs de prendre en charge de manière transparente ces fonctions accélérées lorsque SciPy est disponible, tout en prenant en charge les utilisateurs qui n’ont installé que NumPy.

Pour abréger, ce sont:

  • Algèbre linéaire
  • FFT
  • La fonction de Bessel modifiée du premier type, ordre 0

En outre, à partir du tutoriel SciPy :

Le niveau supérieur de SciPy contient également des fonctions de NumPy et numpy.lib.scimath. Cependant, il est préférable de les utiliser directement à partir du module NumPy.

Ainsi, pour les nouvelles applications, vous devriez préférer la version NumPy des opérations de tableau dupliquées au niveau supérieur de SciPy. Pour les domaines répertoriés ci-dessus, préférez ceux de SciPy et vérifiez la compatibilité en amont si nécessaire dans NumPy.

D'après mon expérience personnelle, la plupart des fonctions de tableau que j'utilise existent au plus haut niveau de NumPy (à l'exception de random). Cependant, toutes les routines spécifiques à un domaine existent dans les sous-packages de SciPy, aussi n'utilise-t-il que très rarement le niveau supérieur de SciPy.

1
jbbiomed

De conférences sur ' économie quantitative '

SciPy est un paquet contenant divers outils construits sur NumPy, utilisant son type de données de matrice et ses fonctionnalités associées.

En fait, lorsque nous importons SciPy, nous obtenons également NumPy, comme l’indique le fichier d’initialisation 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')

Cependant, il est plus courant et plus courant d’utiliser explicitement la fonctionnalité NumPy.

import numpy as np

a = np.identity(3)

Ce qui est utile dans SciPy est la fonctionnalité de ses sous-paquets

  • scipy.optimize, scipy.integrate, scipy.stats, etc.
1
Vlad Bezden