268 votes

Relation entre SciPy et NumPy

SciPy semble fournir la plupart (mais pas toutes [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, et pointent même souvent vers le même objet de fonction.

Parfois, ils sont différents. Pour donner un exemple qui est apparu récemment :

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

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

D'un autre côté, numpy.exp y scipy.exp semblent être des noms différents pour la même ufunc. C'est également le cas pour scipy.log1p y numpy.log1p .

Un autre exemple est numpy.linalg.solve vs scipy.linalg.solve . Ils sont similaires, mais le second offre quelques fonctionnalités supplémentaires par rapport au premier.

Pourquoi ce double emploi apparent ? Si cela est censé être une importation en gros de numpy dans le scipy pourquoi les différences subtiles de comportement et les fonctions manquantes ? Existe-t-il une logique globale qui permettrait de dissiper la confusion ?

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

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

8 votes

J'ai lu dans les réponses que all of those functions are available without additionally importing Numpy parce que the intention is for users not to have to know the distinction between the scipy and numpy namespaces . Maintenant je me demande, parce que je suis un peu les posts sur numpy et scipy et je les utilise moi-même. Et je vois presque toujours numpy être importé séparément (comme np). Alors ils ont échoué ?

8 votes

Il y a quelques différences entre scipy et numpy dans les trucs de FFT, j'ai une fois été confronté à un problème qui s'est avéré être dû à une définition différente de la version de rfft de scipy et numpy.

1 votes

Les FFT de SciPy et NumPy sont différentes. SciPy utilise la bibliothèque Fortran FFTPACK, d'où le nom scipy.fftpack. NumPy utilise une bibliothèque C appelée fftpack_lite ; elle possède moins de fonctions et ne prend en charge que la double précision dans NumPy. Enthought inc. a corrigé son numpy.fft pour utiliser Intel MKL pour les FFT au lieu de fftpack_lite.

145voto

talonmies Points 41460

La dernière fois que je l'ai vérifié, le scipy __init__ exécute une méthode

from numpy import *

afin que l'espace de noms numpy entier soit inclus dans scipy lorsque le module scipy est importé.

El log10 Le comportement que vous décrivez est intéressant, car les deux proviennent de numpy. L'une est un ufunc l'autre est un numpy.lib fonction. Pourquoi scipy préfère la fonction de la bibliothèque à celle de l'utilisateur ? ufunc Je ne sais pas de mémoire.


EDIT : En fait, je peux répondre au log10 question. En regardant dans le fichier scipy __init__ méthode que je vois :

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

El log10 que vous obtenez dans scipy provient de numpy.lib.scimath . En regardant ce code, il est dit :

"""
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 ce module recouvre les ufuncs de base de numpy pour sqrt , log , log2 , logn , log10 , power , arccos , arcsin y arctanh . Cela explique le comportement que vous observez. La raison de la conception sous-jacente qui explique ce comportement est probablement cachée dans un message de liste de diffusion quelque part.

10 votes

Après avoir travaillé à temps plein avec ces paquets pendant un certain temps, voici le sentiment que j'en retire : NumPy est censé être une bibliothèque pour les tableaux numériques, à utiliser par quiconque a besoin d'un tel objet en Python. SciPy est censé être une bibliothèque pour les scientifiques/ingénieurs, et vise donc des mathématiques théoriques plus rigoureuses (incluant donc des versions de log10 en nombres complexes et autres). La principale confusion vient du fait que NumPy conserve de nombreux anciens sous-modules (qui auraient dû aller dans Scipy) qui ont été inclus à l'époque où la démarcation entre SciPy/NumPy n'était pas aussi claire qu'aujourd'hui.

0 votes

@PhilMacKay Salut Phil, j'ai lu ce post et votre autre post spécifique à cette question numpy/scipy de 2013. Ma question est de savoir si votre opinion est toujours d'actualité, comme bien indiqué dans votre commentaire ci-dessus ? Je vois que le poster dit qu'il y a quelques non-équivalents dans scipy et cite abs, max et min comme exemples, mais je comprends que abs est juste un alias pour numpy.absolute et qu'il y a un scipy.absolute, scipy.maximum et scipy.minimum. Donc, dans votre expérience jusqu'à présent, avez-vous déjà eu besoin d'importer numpy si vous avez déjà besoin de scipy ?

0 votes

Il semble que le consensus général soit d'utiliser les bibliothèques de sous-modules de SciPy pour les cas d'utilisation pertinents, et ensuite, pour les opérations de base de NumPy, d'importer spécifiquement NumPy (au lieu du niveau supérieur de SciPy que vous devriez autrement importer). Pour une raison quelconque, d'autres personnes ainsi que la documentation SciPy elle-même considèrent qu'il s'agit d'une meilleure pratique de codage et j'essaie de comprendre pourquoi cela est important. Je suppose que c'est parce que c'est une question de convention et donc de lisibilité. Quelle est votre opinion actuelle ?

56voto

John D. Cook Points 19036

Extrait du guide de référence SciPy :

... toutes les fonctions de Numpy ont été ont été subsumées dans le scipy de sorte que toutes ces fonctions sont disponibles sans sans importer Numpy en plus.

L'objectif est de faire en sorte que les utilisateurs n'aient pas à connaître la distinction entre les éléments suivants scipy y numpy des espaces de noms, bien qu'apparemment vous ayez trouvé une exception.

54voto

PhML Points 320

Il semble, d'après le FAQ SciPy que certaines fonctions de NumPy sont ici pour des raisons historiques alors qu'elles devraient être uniquement dans SciPy :

Quelle est la différence entre NumPy et SciPy ?

Dans un monde idéal, NumPy ne contiendrait rien d'autre que le type de données tableau et les opérations les plus basiques : indexation, tri, remodelage, gestion des fonctions élémentaires, et cetera. Tout le code numérique résiderait dans SciPy. Cependant, l'un des objectifs importants de NumPy est la compatibilité, donc NumPy essaie de conserver toutes les fonctions prises en charge par l'un ou l'autre de ses prédécesseurs. Ainsi, Ainsi, NumPy contient certaines fonctions d'algèbre linéaire, même si celles-ci appartiennent plutôt à SciPy. Quoi qu'il en soit, SciPy contient des fonctions plus complètes que la modules d'algèbre linéaire, ainsi que de nombreux autres algorithmes numériques. algorithmes numériques. Si vous faites du calcul scientifique avec python, vous devriez probablement 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 à la question Question connexe

13voto

dshort Points 81

Il y a un court commentaire à la fin de l'article. introduction à SciPy documentation :

Une autre commande utile est source . Lorsqu'on lui donne comme argument une fonction écrite en Python, il imprime une liste du code source de cette fonction. Cela peut être utile pour apprendre un algorithme ou comprendre exactement ce qu'une fonction fait avec ses arguments. fait avec ses arguments. N'oubliez pas non plus la commande Python dir qui peut être qui permet de consulter l'espace de noms d'un module ou d'un paquetage.

Je pense que cela permettra à quelqu'un ayant une connaissance suffisante de tous les paquets concernés de distinguer exactement les différences entre un peu de les fonctions scipy et numpy (cela ne m'a pas du tout aidé pour la question log10). Je n'ai certainement pas ces connaissances mais source indique que scipy.linalg.solve y numpy.linalg.solve interagissent 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))

Il s'agit également de mon premier message, donc si je dois changer quelque chose ici, faites-le moi savoir.

0 votes

Les enveloppes sous-jacentes sont très différentes. NumPy utilise une couche fine écrite en C. SciPy utilise une couche autogénérée par f2py. SciPy est toujours lié à une bibliothèque LAPACK externe. NumPy utilise sa propre lapack_lite f2c'd dans le cas où une LAPACK externe n'est pas trouvée.

8voto

Mu Mind Points 5142

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

Le code Numeric a été adapté pour le rendre plus facile à maintenir et plus souple suffisamment flexible pour implémenter les nouvelles fonctionnalités de Numarray. Ce nouveau projet faisait partie de SciPy. Pour éviter d'installer un paquet entier paquet juste pour obtenir un objet tableau, ce nouveau paquet a été séparé et appelé NumPy.

scipy dépend de numpy et importe de nombreux numpy dans son espace de noms pour plus de commodité.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X