Beziehung zwischen SciPy und NumPy


254

SciPy scheint die meisten (aber nicht alle [1]) Funktionen von NumPy in einem eigenen Namespace bereitzustellen. Mit anderen Worten, wenn es eine Funktion mit dem Namen numpy.foogibt, gibt es mit ziemlicher Sicherheit eine scipy.foo. Meistens scheinen die beiden genau gleich zu sein und zeigen oft sogar auf dasselbe Funktionsobjekt.

Manchmal sind sie anders. Um ein Beispiel zu nennen, das kürzlich aufgetaucht ist:

  • numpy.log10ist ein Ufunc , der NaNs für negative Argumente zurückgibt;
  • scipy.log10 Gibt komplexe Werte für negative Argumente zurück und scheint kein Ufunc zu sein.

Das gleiche kann man über gesagt werden log, log2und logn, aber nicht über log1p[2].

Auf der anderen Seite numpy.expund scipy.expscheinen unterschiedliche Namen für die gleiche Ufunc zu sein. Dies gilt auch für scipy.log1pund numpy.log1p.

Ein weiteres Beispiel ist numpy.linalg.solvevs scipy.linalg.solve. Sie sind ähnlich, aber das letztere bietet einige zusätzliche Funktionen gegenüber dem ersteren.

Warum die offensichtliche Verdoppelung? Wenn dies ein Großhandelsimport numpyin den scipyNamespace sein soll, warum dann die subtilen Unterschiede im Verhalten und die fehlenden Funktionen? Gibt es eine übergreifende Logik, die helfen würde, die Verwirrung zu beseitigen?

[1] numpy.min, numpy.max, numpy.absund ein paar andere haben keine Entsprechungen im scipyNamespace.

[2] Getestet mit NumPy 1.5.1 und SciPy 0.9.0rc2.


7
Ich habe in den Antworten gelesen, dass all of those functions are available without additionally importing Numpyweil the intention is for users not to have to know the distinction between the scipy and numpy namespaces. Jetzt frage ich mich, weil ich den Posts über Numpy und Scipy ein bisschen folge und sie selbst benutze. Und ich sehe fast immer, dass Numpy separat importiert wird (als np). Also haben sie versagt?
Joris

8
Es gibt einige Unterschiede zwischen scipy und numpy in FFT-Sachen. Ich wurde einmal von einem Problem gebissen, das schließlich auf scipy und numpys Version von rfft zurückgeführt wurde, die anders definiert waren
wim

1
Die FFTs von SciPy und NumPy sind unterschiedlich. SciPy verwendet die Fortran-Bibliothek FFTPACK, daher der Name scipy.fftpack. NumPy verwendet eine C-Bibliothek namens fftpack_lite. Es hat weniger Funktionen und unterstützt nur die doppelte Genauigkeit in NumPy. Enthought inc. hat ihre numpy.fft gepatcht, um Intel MKL für FFTs anstelle von fftpack_lite zu verwenden.
Sturla Molden

7
NumPy wurde ursprünglich scipy.core genannt. NumPy und SciPy sind eng verwandte Projekte. Der Hauptgrund für die Trennung besteht darin, sicherzustellen, dass die Array-Bibliothek (NumPy) schlank und gemein ist, da der Großteil von SciPy nicht immer benötigt wird. Außerdem gab es unter Wissenschaftlern die Entscheidung, die Array-Pakete numeric (MIT) und numarray (NASA) zugunsten von scipy.core einzustellen, und so erhielt es den Namen NumPy. SciPy hat noch nicht 1.0 erreicht, während NumPy derzeit als 1.8.1 veröffentlicht wird. NumPy bietet einige Funktionen für FFT und lineare Algebra, ist jedoch nicht so umfangreich wie SciPy.
Sturla Molden

@SturlaMolden gut über Enthought zu wissen, wissen Sie, ob Anaconda beide optimiert oder nur numpy?
Bindestrich

Antworten:


138

Als ich es das letzte Mal überprüft habe, führt die scipy- __init__Methode a aus

from numpy import *

Damit wird der gesamte Numpy-Namespace in scipy aufgenommen, wenn das scipy-Modul importiert wird.

Das von log10Ihnen beschriebene Verhalten ist interessant, da beide Versionen von numpy stammen. Einer ist eine ufunc, der andere ist eine numpy.libFunktion. Warum scipy die Bibliotheksfunktion der vorzieht ufunc, weiß ich nicht genau.


EDIT: In der Tat kann ich die log10Frage beantworten . Wenn __init__ich in die Scipy- Methode schaue , sehe ich Folgendes :

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

Die log10Funktion, die Sie in scipy erhalten, kommt von numpy.lib.scimath. Wenn man sich diesen Code ansieht, heißt es:

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

Es scheint , dass Modul - Overlays die Basis numpy ufuncs für sqrt, log, log2, logn, log10, power, arccos, arcsin, und arctanh. Das erklärt das Verhalten, das Sie sehen. Der zugrunde liegende Designgrund, warum es so gemacht wird, ist wahrscheinlich irgendwo in einem Mailinglistenbeitrag vergraben.


10
Nachdem ich eine Weile Vollzeit mit diesen Paketen gearbeitet habe, habe ich das Gefühl, dass NumPy eine Bibliothek für numerische Arrays ist, die von jedem verwendet werden kann, der ein solches Objekt in Python benötigt. SciPy ist als Bibliothek für Wissenschaftler / Ingenieure gedacht und zielt daher auf eine strengere theoretische Mathematik ab (einschließlich der komplexen Zahlenversion von log10 und dergleichen). Die Hauptverwirrung ergibt sich aus der Tatsache, dass NumPy viele alte Submodule (die in Scipy hätten enthalten sein sollen) enthält, die zu der Zeit enthalten waren, als die Abgrenzung zwischen SciPy / NumPy nicht so klar war wie heute.
PhilMacKay

@PhilMacKay Hallo Phil, ich habe diesen und Ihren anderen Beitrag speziell für diese Numpy / Scipy-Frage aus dem Jahr 2013 gelesen. Meine Frage ist, ob Ihre Meinung noch aktuell ist, wie in Ihrem obigen Kommentar angegeben? Ich sehe auf dem Poster, dass es einige Nicht-Äquivalente in scipy gibt und abs, max und min als Beispiele auflistet, aber ich verstehe, dass abs nur ein Alias ​​für numpy.absolute ist und es ein scipy.absolute, scipy.maximum und scipy gibt .Minimum. Mussten Sie nach Ihrer bisherigen Erfahrung jemals numpy importieren, wenn Sie bereits scipy benötigen?
Dan Boschen

@PhilMacKay Es scheint, dass der allgemeine Konsens darin besteht, die Submodulbibliotheken von SciPy für ihre relevanten Anwendungsfälle zu verwenden und dann für die Kernoperationen von NumPy NumPy spezifisch zu importieren (anstelle der obersten Ebene von SciPy, die Sie sonst importieren müssten ). Aus irgendeinem Grund wird dies von anderen sowie der SciPy-Dokumentation selbst als bessere Codierungspraxis angegeben, und ich versuche zu verstehen, warum dies wichtig ist. Ich gehe davon aus, dass dies eine Frage der Konvention und damit der Lesbarkeit ist. Was ist Ihre aktuelle Meinung?
Dan Boschen

@DanBoschen Ab November 2018 stehe ich immer noch zu meinem obigen Kommentar. Das Importieren von SciPy, wenn nur NumPy benötigt wird, ist möglicherweise etwas übertrieben. Auf der anderen Seite wird NumPy beim Laden von SciPy importiert, sodass NumPy nicht zusätzlich zu SciPy importiert werden muss. Natürlich gibt es gute Argumente, um der Dokumentation zu folgen. Sie können also gerne das tun, was in Ihrer eigenen Situation am relevantesten ist.
PhilMacKay

@PhilMacKay Danke für deine Eingabe. Nachdem ich mir überlegt habe, warum es vorgeschlagen wird, numpy zu importieren (obwohl alles in scipy ausgeführt werden kann), ist dies eine Frage der Konvention und daher der Lesbarkeit für gemeinsam genutzten Code. Wenn der gesamte numpy-spezifische Code spezifisch an die numpy-Bibliothek gebunden ist, kann er auch leichter von der Bindung an die größere scipy-Bibliothek abgebrochen werden, die viel mehr enthält, was möglicherweise nicht immer benötigt wird. Das heißt, mein Gedanke (für meinen eigenen Ansatz) ist es, numpy zu importieren und dann NICHT das scipy der obersten Ebene zu importieren, sondern nur die scipy-Unterpakete nach Bedarf zu importieren.
Dan Boschen

52

Aus dem SciPy-Referenzhandbuch:

... alle Numpy-Funktionen wurden in den scipy Namespace aufgenommen, sodass alle diese Funktionen verfügbar sind, ohne Numpy zusätzlich zu importieren.

Benutzer sollen die Unterscheidung zwischen scipyund numpyNamespaces nicht kennen müssen, obwohl Sie anscheinend eine Ausnahme gefunden haben.


50

Aus den SciPy-FAQ geht hervor, dass einige Funktionen von NumPy aus historischen Gründen hier sind, während sie nur in SciPy verfügbar sein sollten:

Was ist der Unterschied zwischen NumPy und SciPy?

In einer idealen Welt würde NumPy nur den Array-Datentyp und die grundlegendsten Operationen enthalten: Indizieren, Sortieren, Umformen, grundlegende elementweise Funktionen usw. Der gesamte numerische Code würde sich in SciPy befinden. Eines der wichtigsten Ziele von NumPy ist jedoch die Kompatibilität. Daher versucht NumPy, alle von seinen Vorgängern unterstützten Funktionen beizubehalten. Daher enthält NumPy einige lineare Algebra-Funktionen, obwohl diese besser zu SciPy gehören. In jedem Fall enthält SciPy umfassendere Versionen der linearen Algebra-Module sowie viele andere numerische Algorithmen. Wenn Sie wissenschaftliches Rechnen mit Python betreiben, sollten Sie wahrscheinlich sowohl NumPy als auch SciPy installieren. Die meisten neuen Funktionen gehören eher zu SciPy als zu NumPy.

Das erklärt, warum scipy.linalg.solveeinige zusätzliche Funktionen angeboten werden numpy.linalg.solve.

Ich habe die Antwort von SethMMorton auf die entsprechende Frage nicht gesehen


12

Am Ende der Einführung in die SciPy- Dokumentation befindet sich ein kurzer Kommentar :

Ein weiterer nützlicher Befehl ist source. Wenn eine in Python als Argument geschriebene Funktion angegeben wird, wird eine Liste des Quellcodes für diese Funktion gedruckt. Dies kann hilfreich sein, um einen Algorithmus kennenzulernen oder genau zu verstehen, was eine Funktion mit ihren Argumenten tut. Vergessen Sie auch nicht das Python-Befehlsverzeichnis, mit dem Sie den Namespace eines Moduls oder Pakets anzeigen können.

Ich denke, dies wird es jemandem mit ausreichendem Wissen über alle beteiligten Pakete ermöglichen, genau herauszufinden , was die Unterschiede zwischen einigen Scipy- und Numpy-Funktionen sind (es hat mir bei der log10-Frage überhaupt nicht geholfen). Ich habe dieses Wissen definitiv nicht, zeige es aber sourcean scipy.linalg.solveund numpy.linalg.solveinteragiere auf unterschiedliche Weise mit 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))

Dies ist auch mein erster Beitrag. Wenn ich hier etwas ändern sollte, lass es mich wissen.


Die zugrunde liegenden Wrapper sind sehr unterschiedlich. NumPy verwendet eine in C geschriebene dünne Schicht. SciPy verwendet eine von f2py automatisch generierte Schicht. SciPy verbindet sich immer mit einer externen LAPACK-Bibliothek. NumPy verwendet ein eigenes f2c-lapack_lite, falls kein externes LAPACK gefunden wird.
Sturla Molden

8

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

Der numerische Code wurde angepasst, um ihn wartbarer und flexibler genug zu machen, um die neuartigen Funktionen von Numarray zu implementieren. Dieses neue Projekt war Teil von SciPy. Um zu vermeiden, dass ein ganzes Paket installiert wird, nur um ein Array-Objekt zu erhalten, wurde dieses neue Paket getrennt und NumPy genannt.

scipyhängt von numpyvielen numpyFunktionen ab und importiert sie zur Vereinfachung in seinen Namespace.


4

In Bezug auf das Linalg-Paket rufen die Scipy-Funktionen Lapack und Blas auf, die in hochoptimierten Versionen auf vielen Plattformen verfügbar sind und eine sehr gute Leistung bieten, insbesondere für Operationen mit relativ großen, dichten Matrizen. Andererseits sind sie nicht einfach zu kompilieren, da ein fortran-Compiler und viele plattformspezifische Optimierungen erforderlich sind, um die volle Leistung zu erzielen. Daher bietet numpy einfache Implementierungen vieler gängiger linearer Algebra-Funktionen, die für viele Zwecke oft gut genug sind.


numpy 1.10 hat ein nettes Modul dual: "Dieses Modul sollte für Funktionen sowohl in numpy als auch in scipy verwendet werden, wenn Sie die numpy-Version verwenden möchten, falls verfügbar, aber ansonsten die scipy-Version." Verwendung ---from numpy.dual import fft, inv
Denis

1

Aus Vorlesungen über ' Quantitative Economics '

SciPy ist ein Paket, das verschiedene Tools enthält, die auf NumPy aufbauen und den Array-Datentyp und die zugehörigen Funktionen verwenden

Tatsächlich erhalten wir beim Importieren von SciPy auch NumPy, wie aus der SciPy-Initialisierungsdatei hervorgeht

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

Es ist jedoch üblicher und besser, die NumPy-Funktionalität explizit zu verwenden

import numpy as np

a = np.identity(3)

Was in SciPy nützlich ist, ist die Funktionalität in seinen Unterpaketen

  • scipy.optimize, scipy.integrate, scipy.stats usw.

1
Ich sehe Ihren Kommentar, dass es besser ist, die NumPy-Funktionalität explizit zu verwenden, und ich sehe, dass dies an anderer Stelle wiederholt wird, einschließlich im SciPy-Tutorial, aber warum ist dies eine bessere Praxis? Niemand scheint darauf zu antworten. Wenn Sie SciPy bereits importieren und es die NumPy-Funktionalität enthält, warum ist es besser, NumPy weiterhin zu importieren? Ist es so, dass wir beim Importieren eines Unterpakets in SciPy NICHT die oberste Ebene importieren und daher, anstatt den Schritt zum spezifischen Importieren von SciPy zu unternehmen, nur Numpy für diese zentralen Array-Verarbeitungsfunktionen importieren sollten?
Dan Boschen

1

Neben dem SciPy FAQ die Duplizierung beschreibt , ist in erster Linie für die Abwärtskompatibilität ist es weiter in der geklärten NumPy Dokumentation zu sagen , dass

Optional SciPy-beschleunigte Routinen (numpy.dual)

Aliase für Funktionen, die von Scipy beschleunigt werden können.

SciPy kann so erstellt werden, dass beschleunigte oder auf andere Weise verbesserte Bibliotheken für FFTs, lineare Algebra und spezielle Funktionen verwendet werden. Mit diesem Modul können Entwickler diese beschleunigten Funktionen transparent unterstützen, wenn SciPy verfügbar ist, aber weiterhin Benutzer unterstützen, die nur NumPy installiert haben.

Der Kürze halber sind dies:

  • Lineare Algebra
  • FFT
  • Die modifizierte Bessel-Funktion der ersten Art, Ordnung 0

Auch aus dem SciPy-Tutorial :

Die oberste Ebene von SciPy enthält auch Funktionen von NumPy und numpy.lib.scimath. Es ist jedoch besser, sie stattdessen direkt vom NumPy-Modul aus zu verwenden.

Für neue Anwendungen sollten Sie daher die NumPy-Version der Array-Operationen bevorzugen, die in der obersten Ebene von SciPy dupliziert werden. Für die oben aufgeführten Domänen sollten Sie die in SciPy bevorzugten Domänen bevorzugen und gegebenenfalls die Abwärtskompatibilität in NumPy überprüfen.

Nach meiner persönlichen Erfahrung befinden sich die meisten von mir verwendeten Array-Funktionen in der obersten Ebene von NumPy (mit Ausnahme von random). Alle domänenspezifischen Routinen sind jedoch in Unterpaketen von SciPy vorhanden, sodass ich selten etwas von der obersten Ebene von SciPy verwende.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.