Relation entre SciPy et NumPy

254

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 y a 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 souvent vers le même objet fonction.

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

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

La même chose peut être dit au sujet log, log2et logn, mais pas log1p[2].

D'autre part, numpy.expet scipy.expsemblent être des noms différents pour le même ufunc. Cela vaut également pour scipy.log1pet numpy.log1p.

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

Pourquoi cette duplication apparente? Si cela est censé être une importation en gros de numpydans l' scipyespace de noms, pourquoi les différences subtiles de comportement et les fonctions manquantes? Y a-t-il une logique globale qui aiderait à dissiper la confusion?

[1] numpy.min, numpy.max, numpy.abset quelques autres ont pas d' équivalent dans l' scipyespace de noms.

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

NPE
la source
7
J'ai lu les réponses all of those functions are available without additionally importing Numpyparce 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 articles sur numpy et scipy et que je l'utilise moi-même. Et je vois presque toujours numpy importé séparément (comme np). Alors ils ont échoué?
joris
8
il y a quelques différences entre scipy et numpy dans les trucs FFT, j'ai une fois été mordu par un problème qui a finalement été retracé à la version scipy et numpy de rfft définie différemment
wim
1
Les FFT de SciPy et NumPy sont différents. SciPy utilise la bibliothèque Fortran FFTPACK, d'où le nom scipy.fftpack. NumPy utilise une bibliothèque C appelée fftpack_lite; il a moins de fonctions et ne prend en charge que la double précision dans NumPy. Enthought inc. a corrigé leur numpy.fft pour utiliser Intel MKL pour les FFT au lieu de fftpack_lite.
Sturla Molden
7
NumPy s'appelait à l'origine scipy.core. NumPy et SciPy sont des projets étroitement liés. La principale raison de la séparation est de s'assurer que la bibliothèque de baies (NumPy) est légère et moyenne, car la majeure partie de SciPy n'est pas toujours nécessaire. En outre, les scientifiques ont décidé de retirer les packages de tableaux numériques (MIT) et numarray (NASA) en faveur de scipy.core, et il a donc obtenu le nom NumPy. SciPy n'a toujours pas atteint la version 1.0, tandis que NumPy est actuellement publié en tant que 1.8.1. NumPy possède certaines installations pour la FFT et l'algèbre linéaire, mais pas aussi étendue que SciPy.
Sturla Molden
@SturlaMolden bon à savoir sur Enthought, savez-vous si Anaconda optimise les deux ou tout simplement numpy?
Dashesy

Réponses:

138

La dernière fois que je l'ai vérifié, la __init__méthode scipy exécute un

from numpy import *

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

Le log10comportement que vous décrivez est intéressant, car les deux versions proviennent de numpy. L'un est un ufunc, l'autre est une numpy.libfonction. Pourquoi scipy préfère la fonction de bibliothèque à la ufunc, je ne sais pas du haut de ma tête.


EDIT: En fait, je peux répondre à la log10question. En regardant dans la __init__méthode scipy , 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 log10fonction que vous obtenez dans scipy vient de numpy.lib.scimath. En regardant ce code, il 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 les superpositions de module les ufuncs de numpy de base pour sqrt, log, log2, logn, log10, power, arccos, arcsinet arctanh. Cela explique le comportement que vous voyez. La raison sous-jacente de la conception pour laquelle cela est fait comme ça est probablement enfouie quelque part dans une liste de diffusion.

talonmies
la source
10
Après avoir travaillé à temps plein avec ces packages pendant un certain temps, voici le sentiment que j'y ai: NumPy est destiné à être une bibliothèque de 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, il vise donc à des mathématiques théoriques plus rigoureuses (incluant ainsi une version numérique complexe de log10 et similaires). La principale confusion vient du fait que NumPy conserve de nombreux anciens sous-modules (qui auraient dû être intégrés à Scipy) qui étaient inclus au moment où la démarcation entre SciPy / NumPy n'était pas aussi claire qu'aujourd'hui.
PhilMacKay
@PhilMacKay Salut Phil, j'ai lu ceci et votre autre message spécifique à cette question numpy / scipy de 2013. Ma question est de savoir si votre opinion est toujours actuelle, comme indiqué bien dans votre commentaire ci-dessus? je vois que l'affiche dit qu'il y a des non-équivalents dans scipy et répertorie abs, max et min comme exemples, mais je comprends que abs est juste un alias pour numpy.absolute et il y a scipy.absolute, scipy.maximum et scipy .le minimum. Donc, d'après votre expérience, avez-vous déjà eu besoin d'importer numpy si vous avez déjà besoin de scipy?
Dan Boschen
@PhilMacKay Il semble que le consensus général soit d'utiliser les bibliothèques de sous-modules de SciPy pour leurs cas d'utilisation pertinents, puis pour les opérations de base de NumPy d'importer spécifiquement NumPy (au lieu du niveau supérieur de SciPy que vous auriez dû autrement importer ). Pour une raison quelconque, cela est indiqué par d'autres ainsi que la documentation SciPy elle-même comme une meilleure pratique de codage et j'essaie de comprendre pourquoi cela importerait. Je suppose que c'est parce que c'est une question de convention et donc de lisibilité. Quelle est votre opinion actuelle?
Dan Boschen
@DanBoschen En novembre 2018, je maintiens toujours mon commentaire ci-dessus. L'importation de SciPy lorsque seul NumPy est nécessaire peut être un peu exagéré. D'un autre côté, NumPy est importé lorsque SciPy est chargé, il n'est donc pas nécessaire d'importer NumPy en plus de SciPy. Bien sûr, il existe de bons arguments pour suivre la documentation, alors n'hésitez pas à faire ce qui est le plus pertinent dans votre propre situation.
PhilMacKay
@PhilMacKay Merci pour votre contribution. Après avoir réfléchi à ma raison pourquoi il est suggéré d'importer numpy (même si tout peut être fait en scipy) est une question de convention et donc de lisibilité pour le code partagé. Si tout le code spécifique à numpy est lié à la bibliothèque numpy en particulier, il peut également être plus facilement interrompu d'être lié à la bibliothèque scipy plus grande qui comprend beaucoup plus qui ne sont pas toujours nécessaires. Cela dit, ma pensée (pour ma propre approche) est d'importer numpy, puis de ne PAS importer le scipy de niveau supérieur, mais d'importer uniquement les sous-paquets scipy selon les besoins.
Dan Boschen
52

Dans le Guide de référence SciPy:

... toutes les fonctions Numpy ont été intégrées dans l' scipy espace de noms afin que toutes ces fonctions soient disponibles sans importer Numpy en plus.

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

John D. Cook
la source
50

Il semble d'après la FAQ SciPy que certaines fonctions de NumPy sont là 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 du tableau et les opérations les plus élémentaires: indexation, tri, remodelage, fonctions élémentaires de base, et cetera. Tout le code numérique résiderait dans SciPy. Cependant, l'un des objectifs importants de NumPy est la compatibilité, de sorte que 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 elles appartiennent plus correctement à 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 du calcul scientifique avec python, vous devriez probablement installer NumPy et SciPy. La plupart des nouvelles fonctionnalités appartiennent à SciPy plutôt qu'à NumPy.

Cela explique pourquoi scipy.linalg.solvepropose quelques fonctionnalités supplémentaires numpy.linalg.solve.

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

PhML
la source
12

Il y a un petit commentaire à la fin de l' introduction de la documentation SciPy :

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

Je pense que cela permettra à quelqu'un ayant suffisamment de connaissances de tous les packages impliqués de choisir exactement les différences entre certaines fonctions scipy et numpy (cela ne m'a pas du tout aidé avec la question log10). Je n'ai certainement pas cette connaissance mais l' sourceindique scipy.linalg.solveet numpy.linalg.solveinteragis 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))

C'est aussi mon premier article, donc si je devais changer quelque chose ici, faites le moi savoir.

dshort
la source
Les wrappers sous-jacents sont très différents. NumPy utilise une couche mince écrite en C. SciPy utilise une couche générée automatiquement par f2py. SciPy est toujours lié à une bibliothèque LAPACK externe. NumPy utilise son propre f2c'd lapack_lite au cas où un LAPACK externe ne serait pas trouvé.
Sturla Molden
8

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

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

scipydépend numpyet importe de nombreuses numpyfonctions dans son espace de noms pour plus de commodité.

Mu Mind
la source
4

Concernant le paquet linalg - les fonctions scipy appellent lapack et blas, qui sont disponibles en versions hautement optimisées sur de nombreuses plateformes et offrent de très bonnes performances, en particulier pour les opérations sur des matrices denses assez grandes. D'un autre côté, ce ne sont pas des bibliothèques faciles à compiler, nécessitant un compilateur fortran et de nombreux ajustements spécifiques à la plate-forme pour obtenir des performances complètes. Par conséquent, numpy fournit des implémentations simples de nombreuses fonctions d'algèbre linéaire communes qui sont souvent assez bonnes pour de nombreuses applications.

DaveP
la source
numpy 1.10 a un joli module dual: "Ce module devrait être utilisé pour les fonctions à la fois dans numpy et scipy si vous voulez utiliser la version numpy si disponible mais la version scipy sinon." Utilisation ---from numpy.dual import fft, inv
denis
1

Tiré de conférences sur « l'économie quantitative »

SciPy est un package qui contient divers outils qui sont construits au-dessus de NumPy, en utilisant son type de données de tableau et les fonctionnalités associées

En fait, lorsque nous importons SciPy, nous obtenons également NumPy, comme le montre 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 préférable d'utiliser explicitement la fonctionnalité NumPy

import numpy as np

a = np.identity(3)

Ce qui est utile dans SciPy, c'est la fonctionnalité de ses sous-packages

  • scipy.optimize, scipy.integrate, scipy.stats, etc.
Vlad Bezden
la source
1
Je vois votre commentaire selon lequel il est préférable d'utiliser explicitement la fonctionnalité NumPy, et je vois cela en écho ailleurs, y compris dans le didacticiel SciPy, mais pourquoi est-ce une meilleure pratique? Personne ne semble répondre à cela. Si vous importez déjà SciPy et qu'il inclut la fonctionnalité NumPy, pourquoi est-il préférable d'importer toujours NumPy? Est-ce que lorsque nous importons un sous-package dans SciPy, nous n'importons PAS le niveau supérieur, et par conséquent, au lieu de prendre la décision d'importer SciPy spécifiquement, nous devons simplement importer Numpy pour ces fonctions de traitement de tableau de base?
Dan Boschen
1

En plus de la FAQ SciPy décrivant la duplication est principalement pour la compatibilité descendante, il est précisé dans la documentation NumPy pour dire que

Routines accélérées en option par SciPy (numpy.dual)

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

SciPy peut être conçu pour utiliser des bibliothèques accélérées ou autrement 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.

Par souci de concision, ce sont:

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

En outre, à partir du didacticiel 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 la baie qui sont dupliquées au niveau supérieur de SciPy. Pour les domaines répertoriés ci-dessus, vous devriez préférer ceux de SciPy et vérifier la compatibilité descendante si nécessaire dans NumPy.

D'après mon expérience personnelle, la plupart des fonctions de tableau que j'utilise existent au niveau supérieur de NumPy (à l'exception de random). Cependant, toutes les routines spécifiques au domaine existent dans des sous-packages de SciPy, donc j'utilise rarement quoi que ce soit du niveau supérieur de SciPy.

jbbiomed
la source