Отношения между SciPy и NumPy

254

SciPy предоставляет большинство (но не все [1]) функций NumPy в своем собственном пространстве имен. Другими словами, если есть названная функция numpy.foo, почти наверняка есть scipy.foo. В большинстве случаев они выглядят совершенно одинаково, часто даже указывают на один и тот же функциональный объект.

Иногда они разные. Чтобы привести пример, который недавно появился:

  • numpy.log10является ufunc, который возвращает NaN для отрицательных аргументов;
  • scipy.log10 возвращает комплексные значения для отрицательных аргументов и, по-видимому, не является функцией ufunc.

То же самое можно сказать и о log, log2и logn, но не об log1p[2].

С другой стороны, numpy.expи, scipy.expкажется, разные имена для одного и того же ufunc. Это также верно scipy.log1pи для numpy.log1p.

Другим примером может служить numpy.linalg.solveпротив scipy.linalg.solve. Они похожи, но последний предлагает некоторые дополнительные функции по сравнению с первым.

Почему явное дублирование? Если это предназначено для оптового импорта numpyв scipyпространство имен, почему тонкие различия в поведении и отсутствующих функциях? Есть ли какая-то всеобъемлющая логика, которая поможет устранить путаницу?

[1] numpy.min, numpy.max, numpy.absи некоторые другие не имеют аналогов в scipyпространстве имен.

[2] Протестировано с использованием NumPy 1.5.1 и SciPy 0.9.0rc2.

NPE
источник
7
Я прочитал в ответах, all of those functions are available without additionally importing Numpyпотому что the intention is for users not to have to know the distinction between the scipy and numpy namespaces. Теперь я удивляюсь, потому что я немного слежу за сообщениями о numpy и scipy и использую это сам. И я почти всегда вижу, что numpy импортируется отдельно (как np). Так они провалились?
Йорис
8
есть некоторые различия между scipy и numpy в FFT, я однажды был укушен проблемой, которая в конечном итоге была прослежена до версии rfft для scipy и numpy, определяемой по-разному
wim
1
БПФ SciPy и NumPy различны. SciPy использует библиотеку Фортрана FFTPACK, отсюда и название scipy.fftpack. NumPy использует библиотеку C с именем fftpack_lite; он имеет меньше функций и поддерживает только двойную точность в NumPy. Enthought Inc. исправил их numpy.fft, чтобы использовать Intel MKL для FFT вместо fftpack_lite.
Стурла Молден
7
NumPy изначально назывался scipy.core. NumPy и SciPy являются тесно связанными проектами. Основная причина такого разделения заключается в том, чтобы библиотека массивов (NumPy) была скудной и средней, поскольку объем SciPy не всегда нужен. Кроме того, среди ученых было принято решение отказаться от числовых (MIT) и числовых (NASA) пакетов массивов в пользу scipy.core, и поэтому оно получило название NumPy. SciPy все еще не достиг 1.0, тогда как NumPy в настоящее время выпускается как 1.8.1. У NumPy есть некоторые возможности для БПФ и линейной алгебры, но не такие широкие, как у SciPy.
Стурла Молден
@SturlaMold хорошо знать об Enthought, знаете ли вы, если Anaconda оптимизирует оба или просто NumPy?
Дашеси

Ответы:

138

В последний раз, когда я проверял это, __init__метод scipy выполняет

from numpy import *

так что все пространство имен numpy будет включено в scipy при импорте модуля scipy.

log10Поведение вы описываете интересно, потому что обе версии идут от NumPy. Один - это ufunc, другой - это numpy.libфункция. Почему Сципи предпочитает библиотечную функцию ufunc, я не знаю, насколько это возможно.


РЕДАКТИРОВАТЬ: На самом деле я могу ответить на log10вопрос. Глядя в __init__метод scipy, я вижу это:

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

log10Функция , которую вы получите в SciPy происходит от numpy.lib.scimath. Глядя на этот код, он говорит:

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

Кажется , что модуль накладки базы Numpy ufuncs для sqrt, log, log2, logn, log10, power, arccos, arcsin, и arctanh. Это объясняет поведение, которое вы видите. Основная причина дизайна, почему это делается так, вероятно, где-то скрыта в посте списка рассылки.

talonmies
источник
10
Поработав некоторое время с этими пакетами, у меня возникает ощущение, что NumPy - это библиотека для числовых массивов, которая может использоваться любым, кому нужен такой объект в Python. SciPy призван стать библиотекой для ученых / инженеров, поэтому он нацелен на более сложную теоретическую математику (таким образом, включая комплексную версию log10 и тому подобное). Основная путаница связана с тем, что NumPy сохраняет много старых субмодулей (которые должны были войти в Scipy), которые были включены в то время, когда разграничение между SciPy / NumPy было не таким четким, как сегодня.
PhilMacKay
@PhilMacKay Привет, Фил, я прочитал этот и другой твой пост, посвященный этому тупому / непристойному вопросу 2013 года. Мой вопрос, если твое мнение все еще актуально, как хорошо сказано в твоем комментарии выше? я вижу, как на плакате сказано, что в scipy есть некоторые неэквиваленты, и перечисляет abs, max и min в качестве примеров, но я понимаю, что abs это просто псевдоним для numpy.absolute, и есть scipy.absolute, scipy.maximum и scipy. .minimum. Так по вашему опыту до сих пор вам когда-нибудь нужно было импортировать numpy, если вы уже нуждаетесь в scipy?
Дэн Бошен
@PhilMacKay Похоже, что общий консенсус заключается в том, чтобы использовать библиотеки подмодулей SciPy для их соответствующих вариантов использования, а затем для основных операций NumPy специально импортировать NumPy (вместо верхнего уровня SciPy, который в противном случае вам нужно было бы импортировать). ). По какой-то причине это утверждается другими, а также самой документацией SciPy как лучшая практика кодирования, и я пытаюсь понять, почему это важно. Я предполагаю, что это потому, что это вопрос соглашения и, следовательно, удобочитаемости. Каково ваше текущее мнение?
Дэн Бошен
@DanBoschen По состоянию на ноябрь 2018 года я все еще поддерживаю мой комментарий выше. Импорт SciPy, когда требуется только NumPy, может быть немного излишним. С другой стороны, NumPy импортируется при загрузке SciPy, поэтому нет необходимости импортировать NumPy в дополнение к SciPy. Конечно, есть веские аргументы для следования документации, поэтому не стесняйтесь делать то, что наиболее актуально в вашей собственной ситуации.
PhilMacKay
@PhilMacKay Спасибо за ваш вклад. Подумав об этом, я думаю, почему предлагается импортировать numpy (даже если все можно сделать в scipy), это вопрос соглашения и, следовательно, удобочитаемости для общего кода. Если весь код, специфичный для numpy, специально связан с библиотекой numpy, его также легче оторвать от привязки к более крупной библиотеке scipy, которая включает в себя намного больше, что может быть не всегда необходимо. Тем не менее, моя мысль (для моего собственного подхода) состоит в том, чтобы импортировать numpy, а затем НЕ импортировать scipy верхнего уровня, а импортировать только подпакеты scipy по мере необходимости.
Дэн Бошен
52

Из Справочного руководства SciPy:

... все функции Numpy включены в scipy пространство имен, так что все эти функции доступны без дополнительного импорта Numpy.

Намерение пользователям не нужно знать различие между scipyи numpyпространствами имен, хотя , по- видимому вы нашли исключение.

Джон Д. Кук
источник
50

Из FAQ по SciPy видно, что некоторые функции из NumPy есть здесь по историческим причинам, хотя это должно быть только в SciPy:

В чем разница между NumPy и SciPy?

В идеальном мире NumPy не содержит ничего, кроме типа данных массива и самых основных операций: индексация, сортировка, изменение формы, базовые поэлементные функции и так далее. Весь числовой код будет находиться в SciPy. Однако одной из важных целей NumPy является совместимость, поэтому NumPy пытается сохранить все функции, поддерживаемые любым из его предшественников. Таким образом, NumPy содержит некоторые функции линейной алгебры, хотя они более правильно принадлежат SciPy. В любом случае, SciPy содержит более полнофункциональные версии модулей линейной алгебры, а также многие другие численные алгоритмы. Если вы занимаетесь научными вычислениями на python, вам, вероятно, следует установить и NumPy, и SciPy. Большинство новых функций принадлежат SciPy, а не NumPy.

Это объясняет, почему scipy.linalg.solveпредлагает некоторые дополнительные функции numpy.linalg.solve.

Я не видел ответа SethMMorton на связанный вопрос

PhML
источник
12

В конце введения в документацию SciPy есть небольшой комментарий :

Еще одна полезная команда source. Когда в качестве аргумента передается функция, написанная на Python, она выводит список исходного кода этой функции. Это может быть полезно для изучения алгоритма или точного понимания того, что функция делает со своими аргументами. Также не забывайте о команде Python dir, которую можно использовать для просмотра пространства имен модуля или пакета.

Я думаю, что это позволит человеку, обладающему достаточными знаниями обо всех задействованных пакетах, точно разобрать, в чем разница между некоторыми функциями scipy и numpy (это совсем не помогло мне с вопросом log10). Я определенно не обладаю этим знанием, но sourceдействительно указываю на это scipy.linalg.solveи numpy.linalg.solveвзаимодействую с Лапаком по-разному;

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

Это также мой первый пост, поэтому, если я должен что-то изменить здесь, пожалуйста, дайте мне знать.

dshort
источник
Основные обертки очень разные. NumPy использует тонкий слой, написанный на C. SciPy использует слой, автоматически сгенерированный f2py. SciPy всегда связывается с внешней библиотекой LAPACK. NumPy использует свой собственный f2c'd lapack_lite на случай, если внешний LAPACK не найден.
Стурла Молден
8

Из Википедии ( http://en.wikipedia.org/wiki/NumPy#History ):

Числовой код был адаптирован, чтобы сделать его более удобным для обслуживания и достаточно гибким для реализации новых функций Numarray. Этот новый проект был частью SciPy. Чтобы избежать установки всего пакета просто для получения объекта массива, этот новый пакет был отделен и назван NumPy.

scipyзависит от numpyи импортирует многие numpyфункции в свое пространство имен для удобства.

Му Разум
источник
4

Что касается пакета linalg - функции scipy будут вызывать lapack и blas, которые доступны в высокооптимизированных версиях на многих платформах и предлагают очень хорошую производительность, особенно для операций с достаточно большими плотными матрицами. С другой стороны, это непростые библиотеки для компиляции, требующие компилятора fortran и множества настроек для конкретной платформы, чтобы получить полную производительность. Следовательно, numpy предоставляет простые реализации многих общих функций линейной алгебры, которые часто достаточно хороши для многих целей.

DaveP
источник
У numpy 1.10 есть хороший модуль dual: «Этот модуль следует использовать для функций как в numpy, так и в scipy, если вы хотите использовать версию numpy, если она доступна, но версию scipy в противном случае». Использование ---from numpy.dual import fft, inv
Денис
1

Из лекций на тему « Количественная экономика »

SciPy - это пакет, который содержит различные инструменты, созданные на основе NumPy, с использованием его типа данных массива и соответствующей функциональности.

Фактически, когда мы импортируем SciPy, мы также получаем NumPy, как видно из файла инициализации 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')

Тем не менее, более распространенным явлением является использование явных функций NumPy.

import numpy as np

a = np.identity(3)

Что полезно в SciPy, так это функциональность его подпакетов.

  • scipy.optimize, scipy.integrate, scipy.stats и т. д.
Влад Безден
источник
1
Я вижу ваш комментарий о том, что лучше использовать явную функциональность NumPy, и я вижу, что это отражено в другом месте, в том числе в учебнике по SciPy, но почему это лучше? Кажется, никто не отвечает на это. Если вы уже импортируете SciPy и он включает в себя функциональность NumPy, почему лучше все же импортировать NumPy? Неужели когда мы импортируем подпакет в SciPy, мы НЕ импортируем верхний уровень, и поэтому вместо того, чтобы предпринимать шаги по импорту SciPy специально, мы должны просто импортировать Numpy для этих функций обработки массива ядра?
Дэн Бошен
1

В дополнение к часто задаваемым вопросам SciPy, описывающим дублирование, в основном для обратной совместимости, в документации NumPy дополнительно разъясняется , что

Опционально SciPy-ускоренные подпрограммы (numpy.dual)

Псевдонимы для функций, которые могут быть ускорены Scipy.

SciPy может быть построен для использования ускоренных или иным образом улучшенных библиотек для БПФ, линейной алгебры и специальных функций. Этот модуль позволяет разработчикам прозрачно поддерживать эти ускоренные функции, когда SciPy доступен, но все еще поддерживает пользователей, которые только установили NumPy.

Для краткости это:

  • Линейная алгебра
  • FFT
  • Модифицированная функция Бесселя первого рода, порядок 0

Также из учебника SciPy :

Верхний уровень SciPy также содержит функции из NumPy и numpy.lib.scimath. Однако лучше использовать их непосредственно из модуля NumPy.

Таким образом, для новых приложений вы должны предпочесть версию операций с массивами, которые дублируются на верхнем уровне SciPy. Для доменов, перечисленных выше, вы должны предпочесть те из них, которые есть в SciPy, и при необходимости проверить обратную совместимость в NumPy.

По моему личному опыту, большинство функций массива, которые я использую, существуют на верхнем уровне NumPy (за исключением random). Тем не менее, все специфичные для домена подпрограммы существуют в подпакетах SciPy, поэтому я редко использую что-либо из верхнего уровня SciPy.

jbbiomed
источник