Mối quan hệ giữa SciPy và NumPy


254

SciPy dường như cung cấp hầu hết (nhưng không phải tất cả [1]) các hàm NumPy trong không gian tên của chính nó. Nói cách khác, nếu có một chức năng được đặt tên numpy.foo, thì gần như chắc chắn là a scipy.foo. Hầu hết thời gian, cả hai dường như giống hệt nhau, đôi khi thậm chí chỉ đến cùng một đối tượng chức năng.

Đôi khi, chúng khác nhau. Để đưa ra một ví dụ xuất hiện gần đây:

  • numpy.log10là một ufunc trả về NaN cho các đối số phủ định;
  • scipy.log10 trả về các giá trị phức tạp cho các đối số phủ định và dường như không phải là một ufunc.

Điều tương tự có thể được nói về log, log2logn, nhưng không phải về log1p[2].

Mặt khác, numpy.expscipy.expdường như là các tên khác nhau cho cùng một ufunc. Điều này cũng đúng scipy.log1pnumpy.log1p.

Một ví dụ khác là numpy.linalg.solvevs scipy.linalg.solve. Chúng tương tự nhau, nhưng cái sau cung cấp một số tính năng bổ sung so với cái trước.

Tại sao sự trùng lặp rõ ràng? Nếu điều này có nghĩa là một nhập khẩu bán buôn numpyvào scipykhông gian tên, tại sao sự khác biệt tinh tế trong hành vi và các chức năng bị thiếu? Có một số logic bao quát sẽ giúp làm sáng tỏ sự nhầm lẫn?

[1] numpy.min, numpy.max, numpy.absvà một vài người khác không có các đối tác trong scipykhông gian tên.

[2] Đã thử nghiệm bằng NumPy 1.5.1 và SciPy 0.9.0rc2.


7
Tôi đọc trong câu trả lời rằng all of those functions are available without additionally importing Numpybởi vì the intention is for users not to have to know the distinction between the scipy and numpy namespaces. Bây giờ tôi tự hỏi, bởi vì tôi theo dõi các bài viết về numpy và scipy một chút và sử dụng nó cho mình. Và tôi hầu như luôn thấy numpy được nhập riêng biệt (như np). Vậy họ thất bại?
joris

8
có một số khác biệt giữa scipy và NumPy được trong FFT thứ, tôi một lần bị cắn bởi một vấn đề mà cuối cùng theo dõi xuống scipy và phiên bản numpy của rfft định nghĩa khác nhau
wim

1
Các FFT của SciPy và NumPy là khác nhau. SciPy sử dụng thư viện Fortran FFTPACK, do đó tên scipy.fftpack. NumPy sử dụng thư viện C có tên fftpack_lite; nó có ít chức năng hơn và chỉ hỗ trợ độ chính xác gấp đôi trong NumPy. Bao gồm inc. đã vá lỗi numpy.fft của họ để sử dụng Intel MKL cho FFT thay vì fftpack_lite.
Sturla Molden

7
NumPy ban đầu được đặt tên là scipy.core. NumPy và SciPy là các dự án liên quan chặt chẽ. Lý do chính cho sự phân tách là để đảm bảo rằng thư viện mảng (NumPy) gọn gàng và có ý nghĩa, vì phần lớn SciPy không phải lúc nào cũng cần thiết. Ngoài ra, đã có quyết định giữa các nhà khoa học về việc loại bỏ các gói mảng số (MIT) và numarray (NASA) để ủng hộ scipy.core, và do đó, nó có tên NumPy. SciPy vẫn chưa đạt 1.0, trong khi NumPy hiện được phát hành là 1.8.1. NumPy có một số phương tiện cho FFT và đại số tuyến tính, nhưng không rộng rãi như SciPy.
Sturla Molden

@SturlaMolden tốt để biết về Enth think, bạn có biết Anaconda tối ưu hóa cả hai hay chỉ là numpy?
bảnh bao

Câu trả lời:


138

Lần trước tôi đã kiểm tra nó, __init__phương thức scipy thực thi một

from numpy import *

để toàn bộ không gian tên numpy được đưa vào scipy khi mô-đun scipy được nhập.

Các log10hành vi mà bạn mô tả là thú vị, bởi vì cả hai phiên bản đều đến từ NumPy. Một là một ufunc, một là một numpy.libchức năng. Tại sao scipy lại thích chức năng thư viện hơn ufunc, tôi không biết trên đỉnh đầu.


EDIT: Trong thực tế, tôi có thể trả lời log10câu hỏi. Nhìn vào __init__phương pháp scipy tôi thấy điều này:

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

Các log10chức năng bạn nhận được trong scipy đến từ numpy.lib.scimath. Nhìn vào mã đó, nó nói:

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

Dường như mô-đun lớp phủ các ufuncs cơ sở NumPy cho sqrt, log, log2, logn, log10, power, arccos, arcsin, và arctanh. Điều đó giải thích hành vi bạn đang thấy. Lý do thiết kế cơ bản tại sao nó được thực hiện như thế có lẽ được chôn trong một danh sách gửi thư ở đâu đó.


10
Sau khi làm việc toàn thời gian với các gói này trong một thời gian, đây là cảm giác tôi nhận được về nó: NumPy có nghĩa là một thư viện cho các mảng số, được sử dụng bởi bất kỳ ai cần một đối tượng như vậy trong Python. SciPy có nghĩa là một thư viện cho các nhà khoa học / kỹ sư, vì vậy nó nhắm đến toán học lý thuyết nghiêm ngặt hơn (do đó bao gồm phiên bản số phức của log10 và tương tự). Sự nhầm lẫn chính xuất phát từ việc NumPy giữ lại nhiều mô-đun phụ cũ (đáng lẽ phải đi vào Scipy) được đưa vào thời điểm phân định giữa SciPy / NumPy không rõ ràng như ngày nay.
PhilMacKay

@PhilMacKay Xin chào Phil, tôi đã đọc bài này và bài đăng khác của bạn cụ thể cho câu hỏi khó hiểu / khó hiểu này từ năm 2013. Câu hỏi của tôi là nếu ý kiến ​​của bạn vẫn còn hiện hành, như đã nêu trong nhận xét của bạn ở trên? Tôi thấy người đăng cho biết có một số không tương đương trong scipy và liệt kê abs, max và min làm ví dụ, nhưng tôi hiểu rằng abs chỉ là một bí danh cho numpy.absolute và có scipy.absolute, scipy.maximum và scipy . tối đa. Vì vậy, theo kinh nghiệm của bạn cho đến nay bạn đã bao giờ cần phải nhập numpy nếu bạn đang cần scipy?
Dan Boschen

@PhilMacKay Dường như có sự đồng thuận chung là sử dụng các thư viện mô hình con của SciPy cho các trường hợp sử dụng có liên quan của họ và sau đó cho các hoạt động NumPy cốt lõi để nhập NumPy một cách cụ thể (thay vì SciPy cấp cao nhất mà bạn cần nhập ). Vì một số lý do, điều này được tuyên bố bởi những người khác cũng như chính tài liệu SciPy là thực hành mã hóa tốt hơn và tôi đang cố gắng để hiểu tại sao nó lại quan trọng. Tôi cho rằng đó là vì nó là vấn đề của quy ước và do đó dễ đọc. Ý kiến ​​hiện tại của bạn là gì?
Dan Boschen

@DanBoschen Tính đến tháng 11 năm 2018, tôi vẫn đứng trước bình luận của tôi ở trên. Nhập SciPy khi chỉ cần NumPy có thể là hơi quá mức. Mặt khác, NumPy được nhập khi SciPy được tải, do đó không cần nhập NumPy ngoài SciPy. Dĩ nhiên, có những lý lẽ tốt để làm theo tài liệu, vì vậy hãy thoải mái làm những gì phù hợp nhất trong tình huống của bạn.
PhilMacKay

@PhilMacKay Cảm ơn bạn đã đóng góp. Đã suy nghĩ thông qua phỏng đoán của tôi tại sao nên nhập numpy (mặc dù mọi thứ có thể được thực hiện trong scipy) là một vấn đề quy ước và do đó dễ đọc cho mã chia sẻ. Nếu tất cả các mã cụ thể numpy được gắn vào thư viện numpy một cách cụ thể, nó cũng có thể dễ dàng bị phá vỡ hơn khỏi việc bị ràng buộc vào thư viện scipy lớn hơn bao gồm nhiều hơn có thể không cần thiết luôn luôn. Điều đó nói rằng suy nghĩ của tôi (đối với cách tiếp cận của riêng tôi) là nhập numpy và sau đó KHÔNG nhập scipy cấp cao nhất mà chỉ nhập các gói con scipy khi cần thiết.
Dan Boschen

52

Từ Hướng dẫn tham khảo SciPy:

... tất cả các hàm Numpy đã được đưa vào scipy không gian tên để tất cả các hàm đó đều khả dụng mà không cần nhập thêm Numpy.

Mục đích là để người dùng không phải biết phân biệt giữa không gian tên scipynumpymặc dù rõ ràng bạn đã tìm thấy một ngoại lệ.


50

Có vẻ như từ Câu hỏi thường gặp về SciPy rằng một số chức năng từ NumPy có ở đây vì lý do lịch sử trong khi nó chỉ có trong SciPy:

Sự khác biệt giữa NumPy và SciPy là gì?

Trong một thế giới lý tưởng, NumPy sẽ không chứa gì ngoài kiểu dữ liệu mảng và các hoạt động cơ bản nhất: lập chỉ mục, sắp xếp, định hình lại, các hàm nguyên tố cơ bản, et cetera. Tất cả các mã số sẽ nằm trong SciPy. Tuy nhiên, một trong những mục tiêu quan trọng của NumPy là khả năng tương thích, vì vậy NumPy cố gắng giữ lại tất cả các tính năng được hỗ trợ bởi một trong những người tiền nhiệm của nó. Do đó NumPy chứa một số hàm đại số tuyến tính, mặc dù những hàm này thuộc về SciPy đúng hơn. Trong mọi trường hợp, SciPy chứa các phiên bản đầy đủ tính năng hơn của các mô-đun đại số tuyến tính, cũng như nhiều thuật toán số khác. Nếu bạn đang thực hiện tính toán khoa học với python, có lẽ bạn nên cài đặt cả NumPy và SciPy. Hầu hết các tính năng mới thuộc về SciPy chứ không phải NumPy.

Điều đó giải thích tại sao scipy.linalg.solvecung cấp một số tính năng bổ sung hơnnumpy.linalg.solve .

Tôi không thấy câu trả lời của SethMMorton cho câu hỏi liên quan


12

Có một nhận xét ngắn ở phần cuối của phần giới thiệu về tài liệu SciPy :

Một lệnh hữu ích khác là source. Khi được cung cấp một hàm được viết bằng Python làm đối số, nó sẽ in ra một danh sách mã nguồn cho hàm đó. Điều này có thể hữu ích trong việc tìm hiểu về một thuật toán hoặc hiểu chính xác những gì một hàm đang làm với các đối số của nó. Cũng đừng quên thư mục lệnh Python có thể được sử dụng để xem xét không gian tên của mô-đun hoặc gói.

Tôi nghĩ rằng điều này sẽ cho phép ai đó có đủ kiến ​​thức về tất cả các gói liên quan để phân biệt chính xác sự khác biệt giữa một số chức năng scipy và numpy (nó hoàn toàn không giúp tôi với câu hỏi log10). Tôi chắc chắn không có kiến ​​thức đó nhưng sourcechỉ ra điều đó scipy.linalg.solvenumpy.linalg.solvetương tác với lapack theo những cách khác nhau;

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

Đây cũng là bài viết đầu tiên của tôi vì vậy nếu tôi nên thay đổi một cái gì đó ở đây xin vui lòng cho tôi biết.


Các hàm bao bên dưới rất khác nhau. NumPy sử dụng một lớp mỏng được viết bằng C. SciPy sử dụng một lớp được tự động tạo bởi f2py. SciPy luôn liên kết với thư viện LAPACK bên ngoài. NumPy sử dụng có lapack_lite f2c'd riêng của mình trong trường hợp không tìm thấy LAPACK bên ngoài.
Sturla Molden

8

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

Mã Numeric đã được điều chỉnh để làm cho nó dễ bảo trì hơn và đủ linh hoạt để thực hiện các tính năng mới lạ của Numarray. Dự án mới này là một phần của SciPy. Để tránh cài đặt toàn bộ gói chỉ để lấy một đối tượng mảng, gói mới này được tách ra và được gọi là NumPy.

scipyphụ thuộc numpyvà nhập nhiều numpyhàm vào không gian tên của nó để thuận tiện.


4

Về gói linalg - các hàm scipy sẽ gọi lapack và blas, có sẵn trong các phiên bản được tối ưu hóa cao trên nhiều nền tảng và cung cấp hiệu suất rất tốt, đặc biệt cho các hoạt động trên ma trận dày đặc hợp lý. Mặt khác, chúng không phải là các thư viện dễ biên dịch, đòi hỏi một trình biên dịch fortran và nhiều điều chỉnh cụ thể nền tảng để có được hiệu suất đầy đủ. Do đó, numpy cung cấp các triển khai đơn giản của nhiều hàm đại số tuyến tính phổ biến thường đủ tốt cho nhiều mục đích.


numpy 1.10 có một mô-đun đẹp dual: "Mô-đun này nên được sử dụng cho các chức năng cả numpy và scipy nếu bạn muốn sử dụng phiên bản numpy nếu có nhưng phiên bản scipy khác." Cách sử dụng ---from numpy.dual import fft, inv
denis

1

Từ các bài giảng về ' Kinh tế định lượng '

SciPy là gói chứa các công cụ khác nhau được xây dựng dựa trên NumPy, sử dụng kiểu dữ liệu mảng và chức năng liên quan

Thực tế, khi chúng ta nhập SciPy, chúng ta cũng nhận được NumPy, như có thể thấy từ tệp khởi tạo 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')

Tuy nhiên, việc sử dụng chức năng NumPy một cách rõ ràng và phổ biến hơn

import numpy as np

a = np.identity(3)

Điều hữu ích trong SciPy là chức năng trong các gói con của nó

  • scipy.opt tối đa, scipy.integrate, scipy.stats, v.v.

1
Tôi thấy nhận xét của bạn rằng nên sử dụng chức năng NumPy một cách rõ ràng và tôi thấy điều này lặp lại ở nơi khác kể cả trong hướng dẫn SciPy, nhưng tại sao cách này tốt hơn? Không ai có vẻ trả lời điều đó. Nếu bạn đã nhập SciPy và nó có chức năng NumPy, tại sao vẫn tốt hơn để nhập NumPy? Có phải là khi chúng ta nhập một gói con trong SciPy, chúng ta KHÔNG nhập cấp cao nhất, và do đó thay vì thực hiện bước nhập SciPy cụ thể, chúng ta chỉ nên nhập Numpy cho các hàm xử lý mảng lõi đó?
Dan Boschen

1

Ngoài Câu hỏi thường gặp về SciPy mô tả sự trùng lặp chủ yếu là để tương thích ngược, nó còn được làm rõ thêm trong tài liệu NumPy để nói rằng

Các thói quen tăng tốc SciPy tùy chọn (numpy.dual)

Bí danh cho các chức năng có thể được tăng tốc bởi Scipy.

SciPy có thể được xây dựng để sử dụng các thư viện được tăng tốc hoặc cải tiến cho các FFT, đại số tuyến tính và các hàm đặc biệt. Mô-đun này cho phép các nhà phát triển hỗ trợ minh bạch các chức năng được tăng tốc này khi SciPy khả dụng nhưng vẫn hỗ trợ người dùng chỉ cài đặt NumPy.

Để cho ngắn gọn, đây là:

  • Đại số tuyến tính
  • FFT
  • Hàm B sửa đổi của loại thứ nhất, thứ tự 0

Ngoài ra, từ Hướng dẫn SciPy :

Cấp cao nhất của SciPy cũng chứa các hàm từ NumPy và numpy.lib.scimath. Tuy nhiên, tốt hơn là sử dụng chúng trực tiếp từ mô-đun NumPy thay thế.

Vì vậy, đối với các ứng dụng mới, bạn nên ưu tiên phiên bản NumPy của các hoạt động mảng được sao chép ở cấp cao nhất của SciPy. Đối với các tên miền được liệt kê ở trên, bạn nên ưu tiên những tên miền trong SciPy và kiểm tra tính tương thích ngược nếu cần trong NumPy.

Theo kinh nghiệm cá nhân của tôi, hầu hết các hàm mảng tôi sử dụng đều tồn tại ở cấp cao nhất của NumPy (ngoại trừ random). Tuy nhiên, tất cả các thói quen cụ thể của miền tồn tại trong các gói con của SciPy, vì vậy tôi hiếm khi sử dụng bất cứ thứ gì từ cấp cao nhất của SciPy.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.