SciPyとNumPyの関係


254

SciPyは、NumPyの機能のほとんど(すべてではない)を独自の名前空間で提供しているようです。つまり、という関数がある場合numpy.foo、ほぼ確実にがありscipy.fooます。ほとんどの場合、2つはまったく同じに見え、多くの場合、同じ関数オブジェクトを指しています。

時々、彼らは異なっています。最近登場した例を挙げましょう。

  • numpy.log10あるufunc負の引数の返しNaNをそれは。
  • scipy.log10 負の引数に対して複雑な値を返し、ufuncではないようです。

同じことはについて語ったことができloglog2かつlogn、しかしないことについてlog1p[2]。

一方、numpy.expおよびscipy.exp同じufuncのための別の名前であるように思われます。これはまた真実であるscipy.log1pnumpy.log1p

別の例はnumpy.linalg.solvevs scipy.linalg.solveです。それらは似ていますが、後者は前者にいくつかの追加機能を提供します。

なぜ明白な重複ですか?これが名前空間numpyへの大規模なインポートであることを意図している場合scipy、なぜ動作の微妙な違いと不足している関数があるのでしょうか?混乱を解消するのに役立つ包括的なロジックはありますか?

[1] 、、numpy.min およびいくつかの他にはには対応していない名前空間を。numpy.maxnumpy.absscipy

[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とscipyに関する投稿を少しフォローして自分で使用しているので、疑問に思います。そして私はほとんどいつもnumpyが(npとして)別々にインポートされているのを見ます。それで彼らは失敗したのですか?
ジョリス

8
scipyのダウンロードとnumpyの間にいくつかの違いがFFTのもので、私は一度、最終的にscipyのダウンロードとRFFTのnumpyののバージョンが異なって定義するには、下に追跡することを問題に噛まれてしまっているがあります
WIM

1
SciPyとNumPyのFFTは異なります。SciPyはFortranライブラリFFTPACKを使用するため、scipy.fftpackという名前になります。NumPyは、fftpack_liteと呼ばれるCライブラリを使用します。機能が少なく、NumPyで倍精度のみをサポートします。Enthought Inc. fftpack_liteの代わりにFFTにIntel MKLを使用するようにnumpy.fftにパッチを適用しました。
Sturla Molden 14年

7
NumPyはもともとscipy.coreという名前でした。NumPyとSciPyは密接に関連するプロジェクトです。分離の主な理由は、SciPyの大部分が常に必要とされるわけではないため、配列ライブラリ(NumPy)が無駄のない意味を持つことを保証するためです。また、科学者の間で、scipy.coreを優先して数値(MIT)および数値配列(NASA)の配列パッケージを廃止するという決定があり、そのため、名前はNumPyになりました。SciPyはまだ1.0に達していませんが、NumPyは現在1.8.1としてリリースされています。NumPyには、FFTと線形代数のためのいくつかの機能がありますが、SciPyほど広範囲ではありません。
Sturla Molden 14年

@SturlaMoldenはEnthoughtについて知っておくと良いでしょう。Anacondaが両方を最適化するのか、それとも単純に最適化するのか知っていますか?
dashesy

回答:


138

前回チェックしたとき、scipy __init__メソッドは

from numpy import *

scipyモジュールがインポートされるときに、numpy名前空間全体がscipyに含まれるようにします。

log10ので、あなたが記述されている動作は、興味深いものです両方のバージョンがnumpyのから来ています。一つはufunc、他のあるnumpy.lib機能。なぜscipyはライブラリ関数よりもライブラリ関数を好んでいるのかufunc、頭の先からはわかりません。


編集:実際、私は質問に答えることができますlog10。scipy __init__メソッドを見ると、これがわかります。

# 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を重ねらしいsqrtloglog2lognlog10powerarccosarcsin、とarctanh。それはあなたが見ている行動を説明しています。それがそのように行われる根本的な設計理由は、おそらくどこかでメーリングリストの投稿に埋め込まれています。


10
しばらくの間これらのパッケージをフルタイムで作業した後、私はそれについて私が感じています:NumPyは数値配列のライブラリであり、Pythonでそのようなオブジェクトを必要とする人が使用することを目的としています。SciPyは科学者/エンジニアのためのライブラリであることを意図しているため、より厳密な理論数学(したがって、log10の複素数バージョンなどを含む)を目指しています。主な混乱は、NumPyがSciPy / NumPy間の境界が今日ほど明確ではなかったときに含まれていた多くの古いサブモジュール(Scipyに移行する必要がある)を保持しているという事実に起因します。
PhilMacKay 14

@PhilMacKayこんにちはフィル、私はこれと2013年のこのnumpy / scipy質問に固有のあなたの他の投稿を読みました。私の質問は、あなたの意見がまだ最新のものであるかどうかです。私はポスターにscipyに同等でないものがあると言っており、例としてabs、max、minをリストしていますが、absはnumpy.absoluteの単なるエイリアスであり、scipy.absolute、scipy.maximum、scipyがあることを理解しています。最小。それで、今までの経験で、すでにscipyが必要な場合、numpyをインポートする必要がありましたか?
Dan Boschen

@PhilMacKay一般的なコンセンサスは、SciPyのサブモジュールライブラリを関連するユースケースに使用してから、コアのNumPy操作でNumPyを具体的にインポートすることです(そうでなければインポートする必要があるSciPyの最上位レベルの代わりに) )。何らかの理由で、これは他の人やSciPyのドキュメント自体によってより優れたコーディング方法として述べられており、なぜそれが重要になるのかを理解しようとしています。それは慣習の問題であり、したがって読みやすさの問題だからだと思います。あなたの現在の意見は何ですか?
Dan Boschen

@DanBoschen 2018年11月現在、私はまだ上記のコメントを支持しています。NumPyのみが必要な場合にSciPyをインポートすることは少々やり過ぎかもしれません。一方、NumPyはSciPyのロード時にインポートされるため、SciPyに加えてNumPyをインポートする必要はありません。もちろん、ドキュメンテーションをフォローすることには良い議論がありますので、自分の状況に最も関連することを自由に行ってください。
PhilMacKay 2018年

@PhilMacKayご入力いただきありがとうございます。なぜnumpyをインポートすることが推奨されるのか(すべてをscipyで行うことができるにもかかわらず)と私が推測したことは、慣例の問題であり、したがって共有コードの可読性の問題です。すべてのnumpy固有のコードが具体的にnumpyライブラリに関連付けられている場合は、常に必要とは限らない多くのコードが含まれるより大きなscipyライブラリに関連付けられないようにすることもできます。それは私の考え(私自身のアプローチ)はnumpyをインポートしてからトップレベルのscipyをインポートせず、必要に応じてscipyサブパッケージのみをインポートすることであると述べました。
Dan Boschen

52

SciPyリファレンスガイドから:

...すべてのNumpy関数がscipy 名前空間に組み込まれているため、これらの関数はすべて、Numpyを追加でインポートしなくても使用できます。

意図は明らかに例外を見つけましたが、ユーザーがscipynumpy名前空間の違いを知る必要がないようにすることです。


50

それから思わscipyのダウンロードよくある質問 numpyのからいくつかの機能は、それが唯一のscipyのダウンロードにする必要がありながら、歴史的な理由のためにここにいるということ。

NumPyとSciPyの違いは何ですか?

理想的な世界では、NumPyには配列のデータ型と最も基本的な操作(インデックス作成、並べ替え、再整形、基本的な要素ごとの関数など)のみが含まれます。すべての数値コードはSciPyにあります。ただし、NumPyの重要な目標の1つは互換性です。そのため、NumPyは、いずれかの先行モデルでサポートされているすべての機能を保持しようとします。したがって、これらはSciPyに適切に属していますが、NumPyにはいくつかの線形代数関数が含まれています。いずれにせよ、SciPyには、線形代数モジュールのより完全な機能を備えたバージョンだけでなく、他の多くの数値アルゴリズムが含まれています。Pythonで科学計算を行う場合は、おそらくNumPyとSciPyの両方をインストールする必要があります。ほとんどの新機能は、NumPyではなくSciPyに属しています。

これが、にscipy.linalg.solveいくつかの追加機能を提供する理由を説明していますnumpy.linalg.solve

関連する質問に対する SethMMortonの回答が見つかりませんでした


12

SciPyドキュメントの紹介の最後に短いコメントがあります:

別の便利なコマンドはsourceです。引数としてPythonで記述された関数が渡されると、その関数のソースコードのリストが出力されます。これは、アルゴリズムについて学習したり、関数が引数を使用して何を行っているかを正確に理解するのに役立ちます。また、モジュールまたはパッケージの名前空間を調べるために使用できるPythonコマンドdirについても忘れないでください。

私は、すべてのパッケージの十分な知識と、このことができます誰かが離れて正確に違いが間にあるものを選択する関係だと思ういくつかの scipyのダウンロードとnumpyの機能(それはすべてのlog10の質問で私を助けていません)。私は間違いなくその知識を持っていませんが、それをsource示し、さまざまな方法でラパックscipy.linalg.solvenumpy.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は、外部LAPACKが見つからない場合に備えて、独自のf2c化されたlapack_liteを使用します。
Sturla Molden 2014年

8

ウィキペディアから(http://en.wikipedia.org/wiki/NumPy#History):

Numericコードは、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初期化ファイルからわかるように、SciPyをインポートするとNumPyも取得されます。

# 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をインポートする必要があるのですか?
Dan Boschen

1

複製を説明するSciPy FAQに加えて、主に後方互換性のために、NumPyのドキュメントでさらに明確にされて、

オプションでSciPy加速ルーチン(numpy.dual)

Scipyによって加速される可能性のある関数のエイリアス。

SciPyは、FFT、線形代数、および特殊関数用の高速化された、またはその他の方法で改善されたライブラリを使用するように構築できます。このモジュールにより、開発者はSciPyが利用可能な場合にこれらの高速化された機能を透過的にサポートできますが、NumPyのみをインストールしたユーザーをサポートできます。

簡潔にするために、これらは次のとおりです。

  • 線形代数
  • FFT
  • 第1種の修正ベッセル関数、次数0

また、SciPyチュートリアルから:

SciPyの最上位には、NumPyおよびnumpy.lib.scimathの関数も含まれています。ただし、代わりにNumPyモジュールから直接使用することをお勧めします。

したがって、新しいアプリケーションの場合は、SciPyの最上位に複製される配列操作のNumPyバージョンを優先する必要があります。上記のドメインについては、SciPyのドメインを優先し、必要に応じてNumPyの下位互換性を確認する必要があります。

私の個人的な経験では、私が使用するほとんどの配列関数はNumPyの最上位に存在します(を除くrandom)。ただし、すべてのドメイン固有のルーチンはSciPyのサブパッケージに存在するため、SciPyの最上位レベルのものはほとんど使用しません。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.