Зв'язок між SciPy та NumPy


254

Схоже, SciPy надає більшість (але не всі [1]) функцій NumPy у власному просторі імен. Іншими словами, якщо є названа функція numpy.foo, майже напевно є a scipy.foo. Більшу частину часу вони виявляються абсолютно однаковими, часто навіть вказують на один і той же об’єкт функції.

Іноді вони різні. Щоб навести приклад, який з’явився нещодавно:

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

Те ж саме можна сказати і про log, log2і logn, але не про log1p[2].

З іншого боку, numpy.expі, scipy.expсхоже, різні назви для одного і того ж нефункції. Це також стосується 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.


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 імпортується окремо (як np). Так вони провалилися?
joris

8
Є деякі відмінності між scipy та numpy в речах FFT, і мене одного разу покусало питання, яке врешті-решт простежило за версією rfft scipy та numpy, визначеними по-різному
wim

1
FFTs SciPy і NumPy різні. SciPy використовує бібліотеку Fortran FFTPACK, звідси і назва scipy.fftpack. NumPy використовує бібліотеку С під назвою fftpack_lite; він має менше функцій і підтримує лише подвійну точність у NumPy. Промислив вкл. зафіксував їх numpy.fft, щоб використовувати Intel MKL для FFT замість fftpack_lite.
Стурла Молден

7
NumPy спочатку був названий scipy.core. NumPy та SciPy тісно пов'язані між собою проекти. Основна причина поділу полягає в тому, щоб бібліотека масивів (NumPy) була худорлявою і середньою, оскільки основна частина SciPy не завжди потрібна. Крім того, серед вчених було прийнято рішення відмовитись від масивів пакетів числових (MIT) та numarray (NASA) на користь scipy.core, і таким чином він отримав назву NumPy. SciPy досі не досяг 1,0, тоді як NumPy наразі випущений як 1.8.1. NumPy має деякі можливості для FFT та лінійної алгебри, але не такі масштабні, як SciPy.
Стурла Молден

@SturlaMolden приємно знати про Eghtought, чи знаєш ти, чи Анаконда оптимізує обоє чи просто нудить?
тире

Відповіді:


138

Востаннє я перевірив це, __init__метод scipy виконує a

from numpy import *

таким чином, що весь імперський простір імен включається в scipy при імпорті модуля scipy.

log10Поведінка ви описуєте цікаво, тому що обидві версії йдуть від NumPy. Одне - це ufunc, інше - numpy.libфункція. Чому scipy вважає за краще функціонувати бібліотеку над ufunc, я не знаю вгорі голови.


EDIT: Насправді я можу відповісти на 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. Це пояснює поведінку, яку ви бачите. Основна причина дизайну, чому він робиться так, ймовірно, похований десь у поштовому списку.


10
Пропрацювавши повний робочий день з цими пакунками, ось таке відчуття я отримую з цього приводу: NumPy мається на увазі бути бібліотекою для числових масивів, яку повинен використовувати кожен, хто потребує такого об’єкта в Python. SciPy призначений для бібліотеки для науковців / інженерів, тому він спрямований на більш жорстку теоретичну математику (таким чином, включаючи складну числову версію log10 тощо). Основна плутанина пов'язана з тим, що NumPy зберігає багато старих підмодулів (які повинні були перейти в Scipy), які були включені в той час, коли розмежування між SciPy / NumPy було не таким чітким, як сьогодні.
PhilMacKay

@PhilMacKay Привіт Філе, я читав це та інше твоє повідомлення, характерне для цього питання з 2013 року. Моє запитання, якщо ваша думка все ще актуальна, як це було добре сказано у вашому коментарі вище? Я бачу, що плакат сказав, що є деякі нееквіваленти в scipy і перераховує abs, max та min як приклади, але я розумію, що abs - це лише псевдонім для numpy.absolute і є scipy.absolute, scipy.maximum та scipy . мінімум. Отже, з вашого досвіду до цього часу вам коли-небудь потрібно було імпортувати нуме, якщо вам вже потрібна наука?
Дан Бошен

@PhilMacKay Схоже, загальний консенсус полягає в тому, щоб використовувати бібліотеки підмодулів SciPy для відповідних випадків їх використання, а потім для основних операцій NumPy спеціально імпортувати NumPy (замість верхнього рівня SciPy, який інакше потрібно імпортувати ). Чомусь це заявляється іншими, а також сама документація SciPy як краща практика кодування, і я намагаюся зрозуміти, чому це має значення. Я припускаю, що це тому, що це питання конвенції і, отже, читабельності. Яка ваша сьогоднішня думка?
Дан Бошен

@DanBoschen Станом на листопад 2018 року я все ще стою свій коментар вище. Імпорт SciPy, коли потрібен лише NumPy, може бути трохи зайвим. З іншого боку, NumPy імпортується під час завантаження SciPy, тому немає необхідності імпортувати NumPy крім SciPy. Звичайно, є вагомі аргументи для дотримання документації, тому сміливо робіть те, що найбільш актуально у вашій ситуації.
PhilMacKay

@PhilMacKay Дякуємо за ваш внесок. Подумавши це, я думаю, чому пропонується імпортувати numpy (навіть якщо все можна зробити в scipy) - це питання конвенції, а отже, читабельності для спільного коду. Якщо весь специфічний код конкретно пов'язаний з бібліотекою numpy, він також може бути легше відірваний від прив'язки до більшої бібліотеки наукових досліджень, яка включає в себе набагато більше, що не завжди потрібно. Це сказало, що моя думка (для мого власного підходу) полягає в імпорті нуме, а потім НЕ імпортувати науку верхнього рівня, а лише імпортувати підпакети 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.

Я не побачив відповіді СетМмортона на відповідне питання


12

В кінці вступу до документації на SciPy є короткий коментар :

Ще одна корисна команда - це source. Якщо йому дано функцію, записану на Python, як аргумент, вона виводить список вихідного коду для цієї функції. Це може бути корисним у вивченні алгоритму або розумінні того, що функція робить з її аргументами. Також не забувайте про команду dir команди Python, яку можна використовувати для перегляду простору імен модуля чи пакета.

Я думаю, що це дозволить комусь, хто має достатньо знань щодо всіх пакетів, що займаються, виділити , які саме відмінності між деякими функціями 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))

Це також моя перша публікація, тож якщо я щось зміню тут, будь ласка, дайте мені знати.


Основні обгортки дуже різні. 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 забезпечує просту реалізацію багатьох загальних функцій лінійної алгебри, які часто досить хороші для багатьох цілей.


numpy 1.10 має гарний модуль dual: "Цей модуль слід використовувати для функцій як в numpy, так і в scipy, якщо ви хочете використовувати версію numpy, якщо вона доступна, але версія scipy в іншому випадку." Використання ---from numpy.dual import fft, inv
denis

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 може бути побудований для використання прискорених або іншим чином вдосконалених бібліотек для FFT, лінійної алгебри та спеціальних функцій. Цей модуль дозволяє розробникам прозоро підтримувати ці прискорені функції, коли SciPy доступний, але все ще підтримує користувачів, які встановили лише NumPy.

Для стислості це:

  • Лінійна алгебра
  • FFT
  • Функція Modified Bessel першого типу, порядку 0

Також з підручника SciPy :

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

Отже, для нових додатків вам слід віддати перевагу версії NumPy операцій масиву, що дублюються у верхньому рівні SciPy. Для перелічених вище доменів слід віддати перевагу тим, хто знаходиться в SciPy, і, якщо потрібно, перевірити сумісність у NumPy.

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.