Relazione tra SciPy e NumPy


254

SciPy sembra fornire la maggior parte (ma non tutte [1]) delle funzioni di NumPy nel proprio spazio dei nomi. In altre parole, se c'è una funzione chiamata numpy.foo, c'è quasi sicuramente una scipy.foo. Il più delle volte, i due sembrano essere esattamente gli stessi, spesso anche puntando allo stesso oggetto funzione.

A volte sono diversi. Per fare un esempio che è venuto fuori di recente:

  • numpy.log10è un ufunc che restituisce NaNs per argomenti negativi;
  • scipy.log10 restituisce valori complessi per argomenti negativi e non sembra essere un ufunc.

Lo stesso si può dire di log, log2e logn, ma non di log1p[2].

D'altra parte, numpy.expe scipy.expsembrano essere nomi diversi per lo stesso ufunc. Questo vale anche per scipy.log1pe numpy.log1p.

Un altro esempio è numpy.linalg.solvecontro scipy.linalg.solve. Sono simili, ma quest'ultimo offre alcune funzionalità aggiuntive rispetto al primo.

Perché l'apparente duplicazione? Se questo vuole essere un'importazione all'ingrosso numpynello scipyspazio dei nomi, perché le sottili differenze nel comportamento e le funzioni mancanti? C'è qualche logica generale che aiuterebbe a chiarire la confusione?

[1] numpy.min, numpy.max, numpy.abse pochi altri non hanno controparti nel scipynamespace.

[2] Testato usando NumPy 1.5.1 e SciPy 0.9.0rc2.


7
Ho letto nelle risposte che all of those functions are available without additionally importing Numpyperché the intention is for users not to have to know the distinction between the scipy and numpy namespaces. Ora mi chiedo, perché seguo un po 'i post su intorpidimento e scipy e lo uso da solo. E vedo quasi sempre che il numpy viene importato separatamente (come np). Quindi hanno fallito?
joris,

8
ci sono alcune differenze tra scipy e numpy è nelle cose FFT, una volta sono stato morso da un problema che alla fine è stato rintracciato in scipy e la versione di rfft numpy definita in modo diverso
wim

1
Le FFT di SciPy e NumPy sono diverse. SciPy utilizza la libreria Fortran FFTPACK, da cui il nome scipy.fftpack. NumPy usa una libreria C chiamata fftpack_lite; ha meno funzioni e supporta solo la doppia precisione in NumPy. Enthought inc. ha patchato numpy.fft per usare Intel MKL per FFT invece di fftpack_lite.
Sturla Molden,

7
NumPy era originariamente chiamato scipy.core. NumPy e SciPy sono progetti strettamente correlati. Il motivo principale della separazione è garantire che la libreria di array (NumPy) sia snella e media, poiché la maggior parte di SciPy non è sempre necessaria. Inoltre, gli scienziati hanno deciso di ritirare i pacchetti di array numerici (MIT) e numarray (NASA) a favore di scipy.core, ottenendo così il nome NumPy. SciPy non ha ancora raggiunto 1.0, mentre NumPy è attualmente rilasciato come 1.8.1. NumPy ha alcune strutture per FFT e algebra lineare, ma non così ampia come SciPy.
Sturla Molden,

@SturlaMolden buono a sapersi su Enthought, sai se Anaconda ottimizza entrambi o semplicemente intorpidisce?
dashesy

Risposte:


138

L'ultima volta che l'ho verificato, il __init__metodo scipy esegue un

from numpy import *

in modo che l'intero spazio dei nomi numpy sia incluso in scipy quando viene importato il modulo scipy.

Il log10comportamento che stai descrivendo è interessante, perché entrambe le versioni provengono da intorpidimento. Uno è un ufunc, l'altro è una numpy.libfunzione. Perché scipy preferisce la funzione di libreria a quella ufunc, non lo so dalla cima della mia testa.


EDIT: In effetti, posso rispondere alla log10domanda. Osservando il __init__metodo scipy vedo questo:

# 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 log10funzione che ottieni in scipy viene da numpy.lib.scimath. Guardando quel codice, dice:

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

Sembra che le sovrapposizioni dei moduli i ufuncs di base NumPy per sqrt, log, log2, logn, log10, power, arccos, arcsin, e arctanh. Questo spiega il comportamento che stai vedendo. Il motivo progettuale alla base del fatto che sia fatto in quel modo è probabilmente sepolto da qualche parte in una mailing list.


10
Dopo aver lavorato a tempo pieno con questi pacchetti per un po ', ecco la sensazione che mi viene in mente: NumPy è pensato per essere una libreria di array numerici, da usare per chiunque abbia bisogno di un tale oggetto in Python. SciPy è pensato per essere una biblioteca per scienziati / ingegneri, quindi mira a una matematica teorica più rigorosa (includendo quindi la versione numerica complessa di log10 e simili). La principale confusione deriva dal fatto che NumPy conserva molti vecchi sottomoduli (che avrebbero dovuto entrare in Scipy) che erano inclusi nel momento in cui la demarcazione tra SciPy / NumPy non era così chiara come lo è oggi.
PhilMacKay,

@PhilMacKay Ciao Phil, ho letto questo e altri tuoi post specifici per questa domanda insensibile / scipy del 2013. La mia domanda è se la tua opinione è ancora attuale, come affermato bene nel tuo commento sopra? vedo il poster che dice che ci sono alcuni non equivalenti in scipy ed elenca abs, max e min come esempi, ma capisco che abs è solo un alias per numpy.absolute e che c'è scipy.absolute, scipy.maxim e scipy .minimo. Quindi nella tua esperienza fino ad ora hai mai avuto bisogno di importare numpy se hai già bisogno di scipy?
Dan Boschen,

@PhilMacKay Sembra che il consenso generale sia quello di utilizzare le librerie dei sottomoduli di SciPy per i loro casi d'uso pertinenti, e quindi per le operazioni principali di NumPy di ​​importare in modo specifico NumPy (invece del livello superiore di SciPy che altrimenti dovresti importare ). Per qualche motivo questo è affermato da altri, così come la stessa documentazione di SciPy come migliore pratica di codifica e sto cercando di capire perché sia ​​importante. Suppongo sia perché è una questione di convenzione e quindi di leggibilità. Qual è la tua opinione attuale?
Dan Boschen,

@DanBoschen A novembre 2018, continuo a sostenere il mio commento sopra. L'importazione di SciPy quando è necessario solo NumPy potrebbe essere un po 'eccessiva. D'altra parte, NumPy viene importato quando SciPy viene caricato, quindi non è necessario importare NumPy oltre a SciPy. Ovviamente, ci sono buoni argomenti per seguire la documentazione, quindi sentiti libero di fare ciò che è più rilevante nella tua situazione.
PhilMacKay,

@PhilMacKay Grazie per il tuo contributo. Avendo pensato attraverso la mia ipotesi perché si suggerisce di importare numpy (anche se tutto può essere fatto in scipy) è una questione di convenzione e quindi leggibilità per il codice condiviso. Se tutto il codice specifico del numpy è legato in modo specifico alla libreria numpy, può anche essere più facilmente interrotto dall'essere legato alla libreria scipy più grande che include molto di più che potrebbe non essere sempre necessario. Detto questo, il mio pensiero (per il mio approccio) è quello di importare numpy e quindi NON importare lo scipy di livello superiore, ma importare solo i sotto-pacchetti scipy secondo necessità.
Dan Boschen,

52

Dalla guida di riferimento di SciPy:

... tutte le funzioni di Numpy sono state inserite nello scipy spazio dei nomi in modo che tutte quelle funzioni siano disponibili senza importare ulteriormente Numpy.

L'intenzione è che gli utenti non debbano conoscere la distinzione tra gli spazi dei nomi scipye numpy, sebbene apparentemente tu abbia trovato un'eccezione.


50

Dalle FAQ di SciPy sembra che alcune funzioni di NumPy siano qui per motivi storici mentre dovrebbe essere solo in SciPy:

Qual è la differenza tra NumPy e SciPy?

In un mondo ideale, NumPy non contiene altro che il tipo di dati dell'array e le operazioni più basilari: indicizzazione, ordinamento, rimodellamento, funzioni elementali di base, eccetera. Tutto il codice numerico risiederebbe in SciPy. Tuttavia, uno degli obiettivi importanti di NumPy è la compatibilità, quindi NumPy cerca di mantenere tutte le funzionalità supportate da uno dei suoi predecessori. Quindi NumPy contiene alcune funzioni di algebra lineare, anche se queste appartengono più correttamente a SciPy. In ogni caso, SciPy contiene versioni più complete dei moduli di algebra lineare, così come molti altri algoritmi numerici. Se stai facendo un calcolo scientifico con Python, probabilmente dovresti installare sia NumPy che SciPy. La maggior parte delle nuove funzionalità appartiene a SciPy piuttosto che a NumPy.

Questo spiega perché scipy.linalg.solveoffre alcune funzionalità aggiuntive numpy.linalg.solve.

Non ho visto la risposta di SethMMorton alla domanda correlata


12

C'è un breve commento alla fine dell'introduzione alla documentazione di SciPy :

Un altro comando utile è source. Quando viene data una funzione scritta in Python come argomento, stampa un elenco del codice sorgente per quella funzione. Questo può essere utile per conoscere un algoritmo o capire esattamente cosa sta facendo una funzione con i suoi argomenti. Inoltre, non dimenticare il comando Python dir che può essere usato per guardare lo spazio dei nomi di un modulo o pacchetto.

Penso che questo consentirà a qualcuno con una conoscenza sufficiente di tutti i pacchetti coinvolti di distinguere esattamente quali sono le differenze tra alcune funzioni scipy e numpy (non mi ha aiutato affatto con la domanda log10). Sicuramente non ho questa conoscenza, ma sourcelo indica scipy.linalg.solvee numpy.linalg.solveinteragisce con Lapack in diversi modi;

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

Questo è anche il mio primo post, quindi se dovessi cambiare qualcosa qui per favore fatemelo sapere.


I wrapper sottostanti sono molto diversi. NumPy utilizza un livello sottile scritto in C. SciPy utilizza un livello generato automaticamente da f2py. SciPy si collega sempre a una libreria LAPACK esterna. NumPy utilizza ha il proprio lapack_lite f2c nel caso in cui non venga trovato un LAPACK esterno.
Sturla Molden,

8

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

Il codice numerico è stato adattato per renderlo più gestibile e abbastanza flessibile da implementare le nuove funzionalità di Numarray. Questo nuovo progetto faceva parte di SciPy. Per evitare l'installazione di un intero pacchetto solo per ottenere un oggetto array, questo nuovo pacchetto è stato separato e chiamato NumPy.

scipydipende numpye importa molte numpyfunzioni nel suo spazio dei nomi per comodità.


4

Per quanto riguarda il pacchetto linalg - le funzioni di scipy chiameranno lapack e blas, che sono disponibili in versioni altamente ottimizzate su molte piattaforme e offrono ottime prestazioni, in particolare per operazioni su matrici densamente ragionevolmente grandi. D'altra parte, non sono librerie facili da compilare, che richiedono un compilatore fortran e molte modifiche specifiche della piattaforma per ottenere prestazioni complete. Pertanto, numpy fornisce semplici implementazioni di molte comuni funzioni di algebra lineare che spesso sono abbastanza buone per molti scopi.


numpy 1.10 ha un bel modulo dual: "Questo modulo dovrebbe essere usato per funzioni sia in numpy che in scipy se vuoi usare la versione numpy se disponibile ma la versione scipy altrimenti". Uso ---from numpy.dual import fft, inv
denis

1

Dalle lezioni su " Economia quantitativa "

SciPy è un pacchetto che contiene vari strumenti basati su NumPy, usando il suo tipo di dati array e le relative funzionalità

Infatti, quando importiamo SciPy otteniamo anche NumPy, come si può vedere dal file di inizializzazione di 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')

Tuttavia, è prassi più comune e migliore utilizzare esplicitamente la funzionalità NumPy

import numpy as np

a = np.identity(3)

Ciò che è utile in SciPy è la funzionalità nei suoi pacchetti secondari

  • scipy.optimize, scipy.integrate, scipy.stats, ecc.

1
Vedo il tuo commento secondo cui è meglio usare esplicitamente la funzionalità NumPy e lo vedo echeggiato altrove, incluso il tutorial di SciPy, ma perché è questa pratica migliore? Nessuno sembra rispondere a questo. Se stai già importando SciPy e include la funzionalità NumPy, perché è meglio importare ancora NumPy? Quando importiamo un subpackage in SciPy, NON importiamo il livello più alto, e quindi invece di fare il passo per importare SciPy in modo specifico, dovremmo semplicemente importare Numpy per quelle funzioni di elaborazione dell'array core?
Dan Boschen,

1

Oltre alle FAQ di SciPy che descrivono la duplicazione è principalmente per la compatibilità con le versioni precedenti, nella documentazione di NumPy viene ulteriormente chiarito che

Opzionali routine accelerate da SciPy (numpy.dual)

Alias ​​per funzioni che possono essere accelerate da Scipy.

SciPy può essere costruito per utilizzare librerie accelerate o comunque migliorate per FFT, algebra lineare e funzioni speciali. Questo modulo consente agli sviluppatori di supportare in modo trasparente queste funzioni accelerate quando SciPy è disponibile ma supportano comunque gli utenti che hanno installato solo NumPy.

Per brevità, questi sono:

  • Algebra lineare
  • FFT
  • La funzione di Bessel modificata del primo tipo, ordina 0

Inoltre, dal tutorial di SciPy :

Il livello superiore di SciPy contiene anche funzioni di NumPy e numpy.lib.scimath. Tuttavia, è preferibile utilizzarli direttamente dal modulo NumPy.

Quindi, per le nuove applicazioni, dovresti preferire la versione NumPy delle operazioni dell'array che sono duplicate nel livello superiore di SciPy. Per i domini sopra elencati, dovresti preferire quelli in SciPy e verificare la compatibilità con le versioni precedenti se necessario in NumPy.

Nella mia esperienza personale, la maggior parte delle funzioni di array che utilizzo esistono al livello più alto di NumPy (tranne per random). Tuttavia, tutte le routine specifiche del dominio esistono nei pacchetti secondari di SciPy, quindi raramente utilizzo qualsiasi cosa dal livello più alto di SciPy.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.