Relação entre SciPy e NumPy

254

O SciPy parece fornecer a maioria (mas não todas [1]) das funções do NumPy em seu próprio espaço de nome. Em outras palavras, se houver uma função chamada numpy.foo, certamente haverá umascipy.foo . Na maioria das vezes, os dois parecem exatamente iguais, muitas vezes até apontando para o mesmo objeto de função.

Às vezes são diferentes. Para dar um exemplo que surgiu recentemente:

  • numpy.log10é um ufunc que retorna NaNs para argumentos negativos;
  • scipy.log10 retorna valores complexos para argumentos negativos e não parece ser um problema.

O mesmo pode ser dito sobre log, log2e logn, mas não sobrelog1p [2].

Por outro lado, numpy.expe scipy.expparecem ter nomes diferentes para o mesmo nome. Isto também é verdade scipy.log1penumpy.log1p .

Outro exemplo é numpy.linalg.solvevsscipy.linalg.solve . Eles são semelhantes, mas o último oferece alguns recursos adicionais sobre o primeiro.

Por que a aparente duplicação? Se isso é uma importação de atacado numpypara o scipyespaço para nome, por que as diferenças sutis de comportamento e as funções ausentes? Existe alguma lógica abrangente que ajudaria a esclarecer a confusão?

[1] numpy.min, numpy.max, numpy.abse alguns outros não têm contrapartida no scipynamespace.

[2] Testado usando o NumPy 1.5.1 e SciPy 0.9.0rc2.

NPE
fonte
7
Eu li nas respostas que all of those functions are available without additionally importing Numpyporque the intention is for users not to have to know the distinction between the scipy and numpy namespaces. Agora eu me pergunto, porque sigo um pouco as mensagens sobre entorpecido e covarde e o uso sozinho. E quase sempre vejo o numpy sendo importado separadamente (como np). Então eles falharam?
Joris
8
há algumas diferenças entre scipy e numpy é em coisas FFT, uma vez eu fui mordido por um problema que, eventualmente, rastreou a SciPy ea versão de numpy de rfft definido de forma diferente
Wim
1
As FFTs de SciPy e NumPy são diferentes. SciPy usa a biblioteca Fortran FFTPACK, daí o nome scipy.fftpack. O NumPy usa uma biblioteca C chamada fftpack_lite; possui menos funções e suporta apenas precisão dupla no NumPy. Enthought inc. corrigiu seu numpy.fft para usar o Intel MKL para FFTs em vez de fftpack_lite.
Sturla Molden 28/03
7
O NumPy foi originalmente chamado de scipy.core. NumPy e SciPy são projetos intimamente relacionados. O principal motivo da separação é garantir que a biblioteca de matrizes (NumPy) seja enxuta e média, pois a maior parte do SciPy nem sempre é necessária. Além disso, houve uma decisão entre os cientistas de aposentar os pacotes numéricos (MIT) e numarray (NASA) em favor do scipy.core e, portanto, recebeu o nome NumPy. O SciPy ainda não atingiu a versão 1.0, enquanto o NumPy é atualmente lançado como 1.8.1. O NumPy possui algumas facilidades para FFT e álgebra linear, mas não tão extensas quanto o SciPy.
Sturla Molden 28/03
@SturlaMolden é bom saber sobre a Enthought, você sabe se o Anaconda otimiza os dois ou apenas fica entorpecido?
Dashesy # 8/15

Respostas:

138

A última vez que o verifiquei, o __init__método scipy executa um

from numpy import *

para que todo o espaço para nome numpy seja incluído no scipy quando o módulo scipy for importado.

O log10comportamento que você está descrevendo é interessante, porque as duas versões são provenientes de numpy. Um é a ufunc, o outro é uma numpy.libfunção. Por que scipy está preferindo a função de biblioteca ao invés de ufunc, eu não sei de nada.


EDIT: Na verdade, eu posso responder à log10pergunta. Olhando no __init__método scipy , vejo o seguinte:

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

A log10função que você obtém no scipy vem numpy.lib.scimath. Olhando para esse código, ele diz:

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

Parece que o módulo sobrepõe as ufuncs base de numpy para sqrt, log, log2, logn, log10,power , arccos, arcsin, e arctanh. Isso explica o comportamento que você está vendo. A razão subjacente ao design por que isso é feito provavelmente está enterrada em uma postagem da lista de emails em algum lugar.

talonmies
fonte
10
Depois de trabalhar em tempo integral com esses pacotes por um tempo, eis a seguinte sensação: o NumPy deve ser uma biblioteca de matrizes numéricas, para ser usada por qualquer pessoa que precise de um objeto desse tipo em Python. O SciPy é destinado a ser uma biblioteca para cientistas / engenheiros, portanto, visa uma matemática teórica mais rigorosa (incluindo, portanto, uma versão complexa de números do log10 e similares). A principal confusão vem do fato de o NumPy reter muitos submódulos antigos (que deveriam ter entrado no Scipy) que foram incluídos no momento em que a demarcação entre o SciPy / NumPy não era tão clara como é hoje.
22414 PhilMacKay
@PhilMacKay Olá Phil, eu li este e seu outro post específico para esta pergunta entorpecente / scipy de 2013. Minha pergunta é se a sua opinião ainda é atual, como indicado no seu comentário acima? Eu vejo o cartaz dizendo que existem alguns não equivalentes no scipy e lista abs, max e min como exemplos, mas eu entendo que o abs é apenas um alias para numpy.absolute e há um scipy.absolute, scipy.maximum e scipy .mínimo. Então, em sua experiência até agora, você já precisou importar numpy se você já está precisando de scipy?
Dan Boschen 18/11/19
@PhilMacKay Parece que o consenso geral é usar as bibliotecas de submódulos do SciPy para seus casos de uso relevantes e, em seguida, para que as operações principais do NumPy importem o NumPy especificamente (em vez do nível superior do SciPy que você precisaria importar ) Por alguma razão, isso é afirmado por outros, bem como pela própria documentação SciPy, como uma melhor prática de codificação e estou tentando entender por que isso importaria. Presumo que é porque é uma questão de convenção e, portanto, legibilidade. Qual a sua opinião atual?
Dan Boschen
@DanBoschen Em novembro de 2018, continuo mantendo meu comentário acima. A importação do SciPy quando apenas o NumPy é necessário pode ser um pouco exagerado. Por outro lado, o NumPy é importado quando o SciPy é carregado, portanto, não é necessário importar o NumPy além do SciPy. Obviamente, existem bons argumentos para seguir a documentação; portanto, fique à vontade para fazer o que for mais relevante em sua própria situação.
PhilMacKay
@PhilMacKay Obrigado pela sua contribuição. Tendo pensado no meu palpite sobre por que é sugerido importar numpy (mesmo que tudo possa ser feito de maneira cintilante) é uma questão de convenção e, portanto, legibilidade para código compartilhado. Se todo o código específico numpy estiver vinculado à biblioteca numpy especificamente, ele também poderá ser mais facilmente interrompido por ser vinculado à biblioteca scipy maior, que inclui muito mais que nem sempre é necessário. Dito isso, meu pensamento (para minha própria abordagem) é importar numpy e depois NÃO importar o scipy de nível superior, mas apenas importar os subpacotes scipy, conforme necessário.
Dan Boschen 23/11/19
52

No Guia de Referência SciPy:

... todas as funções do Numpy foram incluídas no scipy espaço de nomes para que todas essas funções estejam disponíveis sem a importação adicional do Numpy.

A intenção é que os usuários não precisem saber a distinção entre os namespaces scipye numpy, embora aparentemente você tenha encontrado uma exceção.

John D. Cook
fonte
50

Parece que, nas perguntas frequentes do SciPy, algumas funções do NumPy estão aqui por razões históricas, enquanto deveriam estar apenas no SciPy:

Qual é a diferença entre NumPy e SciPy?

Em um mundo ideal, o NumPy não conteria nada além do tipo de dados da matriz e das operações mais básicas: indexação, classificação, remodelagem, funções básicas dos elementos, etc. Todo o código numérico residiria no SciPy. No entanto, um dos objetivos importantes do NumPy é a compatibilidade; portanto, o NumPy tenta manter todos os recursos suportados por qualquer um dos seus antecessores. Assim, o NumPy contém algumas funções de álgebra linear, mesmo que estas pertençam mais adequadamente ao SciPy. De qualquer forma, o SciPy contém versões mais completas dos módulos de álgebra linear, além de muitos outros algoritmos numéricos. Se você está fazendo computação científica com python, provavelmente deve instalar o NumPy e o SciPy. A maioria dos novos recursos pertence ao SciPy e não ao NumPy.

Isso explica por que scipy.linalg.solveoferece alguns recursos adicionais numpy.linalg.solve.

Não vi a resposta de SethMMorton para a pergunta relacionada

PhML
fonte
12

Há um breve comentário no final da introdução à documentação do SciPy :

Outro comando útil é source. Quando recebe uma função escrita em Python como argumento, ela imprime uma lista do código-fonte dessa função. Isso pode ser útil para aprender sobre um algoritmo ou entender exatamente o que uma função está fazendo com seus argumentos. Também não se esqueça do comando Python dir, que pode ser usado para examinar o espaço para nome de um módulo ou pacote.

Eu acho que isso permitirá que alguém com conhecimento suficiente de todos os pacotes envolvidos escolha exatamente quais são as diferenças entre algumas funções enganosas e numpy (isso não me ajudou em nada com a pergunta log10). Definitivamente não tenho esse conhecimento, mas sourceindica isso scipy.linalg.solvee numpy.linalg.solveinterajo com o lapack de maneiras diferentes;

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

Este também é o meu primeiro post, por isso, se eu mudar alguma coisa aqui, por favor me avise.

dshort
fonte
Os wrappers subjacentes são muito diferentes. O NumPy usa uma camada fina escrita em C. O SciPy usa uma camada gerada automaticamente pelo f2py. O SciPy sempre se vincula a uma biblioteca externa do LAPACK. O NumPy usa possui seu próprio lapack_lite f2c'd, caso um LAPACK externo não seja encontrado.
Sturla Molden 28/03
8

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

O código numérico foi adaptado para torná-lo mais sustentável e flexível o suficiente para implementar os novos recursos do Numarray. Este novo projeto fazia parte do SciPy. Para evitar a instalação de um pacote inteiro apenas para obter um objeto de matriz, esse novo pacote foi separado e chamado NumPy.

scipydepende numpye importa muitas numpyfunções para seu espaço de nome por conveniência.

Mu Mind
fonte
4

Em relação ao pacote linalg - as funções scipy chamarão lapack e blas, que estão disponíveis em versões altamente otimizadas em muitas plataformas e oferecem desempenho muito bom, principalmente para operações em matrizes densas razoavelmente grandes. Por outro lado, não são fáceis de compilar bibliotecas, exigindo um compilador fortran e muitos ajustes específicos da plataforma para obter desempenho total. Portanto, o numpy fornece implementações simples de muitas funções comuns de álgebra linear, que geralmente são boas o suficiente para muitos propósitos.

DaveP
fonte
o numpy 1.10 possui um módulo agradável dual: "Este módulo deve ser usado para funções tanto em numpy quanto em scipy, se você quiser usar a versão numpy, se disponível, mas a versão scipy, caso contrário." Uso ---from numpy.dual import fft, inv
denis
1

Das palestras sobre ' Economia Quantitativa '

O SciPy é um pacote que contém várias ferramentas criadas sobre o NumPy, usando seu tipo de dados de matriz e funcionalidade relacionada

De fato, quando importamos o SciPy, também obtemos o NumPy, como pode ser visto no arquivo de inicialização do 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')

No entanto, é mais comum e melhor prática usar a funcionalidade NumPy explicitamente

import numpy as np

a = np.identity(3)

O que é útil no SciPy é a funcionalidade em seus subpacotes

  • scipy.optimize, scipy.integrate, scipy.stats etc.
Vlad Bezden
fonte
1
Vejo seu comentário de que é uma prática melhor usar explicitamente a funcionalidade NumPy e vejo isso ecoado em outros lugares, inclusive no tutorial SciPy, mas por que essa prática é melhor? Ninguém parece responder isso. Se você já está importando o SciPy e inclui a funcionalidade NumPy, por que é melhor ainda importar o NumPy? Será que, quando importamos um subpacote no SciPy, NÃO estamos importando o nível superior e, portanto, em vez de darmos o passo de importar o SciPy especificamente, devemos importar o Numpy para essas funções de processamento da matriz principal?
Dan Boschen
1

Além das perguntas frequentes sobre o SciPy, que descrevem a duplicação principalmente para compatibilidade com versões anteriores, é esclarecido na documentação do NumPy que

Rotinas opcionalmente aceleradas pelo SciPy (numpy.dual)

Aliases para funções que podem ser aceleradas pelo Scipy.

O SciPy pode ser construído para usar bibliotecas aceleradas ou melhoradas para FFTs, álgebra linear e funções especiais. Este módulo permite que os desenvolvedores ofereçam suporte transparente a essas funções aceleradas quando o SciPy está disponível, mas ainda suportam usuários que instalaram apenas o NumPy.

Por uma questão de brevidade, são eles:

  • Álgebra Linear
  • FFT
  • A função Modificado de Bessel do primeiro tipo, ordem 0

Além disso, no Tutorial SciPy :

O nível superior do SciPy também contém funções de NumPy e numpy.lib.scimath. No entanto, é melhor usá-los diretamente do módulo NumPy.

Portanto, para novos aplicativos, você deve preferir a versão NumPy das operações da matriz duplicadas no nível superior do SciPy. Para os domínios listados acima, você deve preferir os do SciPy e verificar a compatibilidade com versões anteriores, se necessário, no NumPy.

Na minha experiência pessoal, a maioria das funções de matriz que utilizo existe no nível superior do NumPy (exceto por random). No entanto, todas as rotinas específicas de domínio existem nos subpacotes do SciPy, portanto, raramente uso algo do nível superior do SciPy.

jbbiomed
fonte