- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
NumPy 中 matrix
类的状态是什么?
我一直被告知我应该改用 ndarray
类。在我编写的新代码中使用 matrix
类是否值得/安全?我不明白为什么我应该使用 ndarray
来代替。
最佳答案
tl;博士: numpy.matrix
类正在被弃用。有一些引人注目的库依赖于该类作为依赖项(最大的一个是 scipy.sparse
),这阻碍了该类的适当短期弃用,但强烈建议用户使用 ndarray
类(通常使用 0x251341124函数)代替。随着用于矩阵乘法的 numpy.array
运算符的引入,矩阵的许多相对优势已被消除。
为什么(不是)矩阵类?@
是 numpy.matrix
的子类。它最初是为了方便在涉及线性代数的计算中使用,但与更一般的数组类的实例相比,它们的行为方式既有局限性,也有惊人的差异。行为根本差异的示例:
numpy.ndarray
(并不是说这具有任何实际重要性)。 np.matrix(np.random.rand(2,3))[None,...,None].shape == (1,2,3,1)
为您提供任何大小的数组。矩阵上的索引表达式总是会给你一个矩阵。这意味着两个arr[:,0]
和arr[0,:]
用于2D阵列给你一个1D ndarray
,而mat[:,0]
具有形状(N,1)
和mat[0,:]
具有形状(1,M)
在matrix
的情况下。 mat1 * mat2
如果 mat1.shape[1] == mat2.shape[0]
有效,但 arr1 * arr2
有效,如果 arr1.shape == arr2.shape
(当然结果意味着完全不同的东西)。此外,令人惊讶的是,mat1 / mat2
执行两个矩阵的元素除法。这种行为可能是从 ndarray
继承的,但对矩阵没有意义,特别是考虑到 *
的含义。 mat.A
和mat.A1
都与相同的值分别np.array(mat)
和np.array(mat).ravel()
,阵列的观点:矩阵除了什么阵列具有有how you are indexing it。 mat.T
和mat.H
是矩阵的转置和共轭转置(伴随); arr.T
是 ndarray
类中唯一存在的此类属性。最后, mat.I
是 mat
的逆矩阵。 ndarray
的子类,但
matrix
是一个行为不良的子类,它可以很容易地破坏试图依赖鸭子类型的代码。考虑以下使用形状为
(3,4)
的数组和矩阵的示例:
import numpy as np
shape = (3, 4)
arr = np.arange(np.prod(shape)).reshape(shape) # ndarray
mat = np.matrix(arr) # same data in a matrix
print((arr + mat).shape) # (3, 4), makes sense
print((arr[0,:] + mat[0,:]).shape) # (1, 4), makes sense
print((arr[:,0] + mat[:,0]).shape) # (3, 3), surprising
arr[:,0]
的形状为
(3,)
与形状
(1,3)
兼容,但
mat[:.0]
的形状为 0x231418。这两个是
a few handy attributes 一起形成
(3,1)
。
(3,3)
matmul operator was introduced in python 3.5 时,矩阵类的最大优势(即简洁地制定涉及大量矩阵乘积的复杂矩阵表达式的可能性)被删除。比较一个简单的二次形式的计算:
v = np.random.rand(3); v_row = np.matrix(v)
arr = np.random.rand(3,3); mat = np.matrix(arr)
print(v.dot(arr.dot(v))) # pre-matmul style
# 0.713447037658556, yours will vary
print(v_row * mat * v_row.T) # pre-matmul matrix style
# [[0.71344704]]
print(v @ arr @ v) # matmul style
# 0.713447037658556
@
运算符使表达式变得不那么冗长且更易于阅读。但是,我们使用现代 python 和 numpy 获得了与
*
运算符相同的可读性。此外,请注意矩阵情况为我们提供了一个形状为
@
的矩阵,它在技术上应该是一个标量。这也意味着我们不能将列向量与这个“标量”相乘:上例中的
(1,1)
会引发错误,因为形状为
(v_row * mat * v_row.T) * v_row.T
和
(1,1)
的矩阵不能按此顺序相乘。
(3,1)
是矩阵的正确三次矩阵幂(而它是 ndarray 的元素立方)。不幸的是
mat ** 3
更加冗长。此外,就地矩阵乘法仅适用于矩阵类。相比之下,虽然
in numpy 1.10 和
PEP 465 都允许
numpy.linalg.matrix_power
作为使用 matmul 的增强赋值,但从 numpy 1.15 开始,这并未为 ndarrays 实现。
@=
类的复杂性,长期以来一直反复讨论其可能的弃用。引入
matrix
中缀运算符,这是此过程
python grammar 的重要先决条件。不幸的是,早期矩阵类的优势意味着它的使用范围很广。有一些依赖于矩阵类的库(最重要的依赖之一是
happened in September 2015,它同时使用
@
语义,并且在增密时经常返回矩阵),因此完全弃用它们总是有问题的。
scipy.sparse
中,我发现了诸如
numpy was designed for general purpose computational needs, not any one branch of math. nd-arrays are very useful for lots of things. In contrast, Matlab, for instance, was originally designed to be an easy front-end to linear algebra package. Personally, when I used Matlab, I found that very awkward -- I was usually writing 100s of lines of code that had nothing to do with linear algebra, for every few lines that actually did matrix math. So I much prefer numpy's way -- the linear algebra lines of code are longer an more awkward, but the rest is much better.
The Matrix class is the exception to this: is was written to provide a natural way to express linear algebra. However, things get a bit tricky when you mix matrices and arrays, and even when sticking with matrices there are confusions and limitations -- how do you express a row vs a column vector? what do you get when you iterate over a matrix? etc.
There has been a bunch of discussion about these issues, a lot of good ideas, a little bit of consensus about how to improve it, but no one with the skill to do it has enough motivation to do it.
What sparked this discussion (on Github) is that it is not possible to write duck-typed code that works correctly for:
- ndarrays
- matrices
- scipy.sparse sparse matrixes
The semantics of all three are different; scipy.sparse is somewhere between matrices and ndarrays with some things working randomly like matrices and others not.
With some hyberbole added, one could say that from the developer point of view, np.matrix is doing and has already done evil just by existing, by messing up the unstated rules of ndarray semantics in Python.
numpy.matrix
运算符,也有很多人考虑过矩阵类的弃用以及它如何影响下游用户。据我所知,这个讨论直接导致了引入 matmul 的 PEP 465 的诞生。
In my opinion, a "fixed" version of np.matrix should (1) not be a np.ndarray subclass and (2) exist in a third party library not numpy itself.
I don't think it's really feasible to fix np.matrix in its current state as an ndarray subclass, but even a fixed matrix class doesn't really belong in numpy itself, which has too long release cycles and compatibility guarantees for experimentation -- not to mention that the mere existence of the matrix class in numpy leads new users astray.
@
运算符可用一段时间后,
In early 2015 、
the discussion of deprecation surfaced again 关于矩阵弃用和
@
的关系。
How would the community handle the scipy.sparse matrix subclasses? These are still in common use.
他们很长一段时间都不会去任何地方(直到稀疏的 ndarrays
至少实现)。因此 np.matrix 需要移动,而不是删除。
( first action to deprecatescipy.sparse
was taken in late November 2017 ) 和
while I want to get rid of np.matrix as much as anyone, doing that anytime soon would be really disruptive.
There are tons of little scripts out there written by people who didn't know better; we do want them to learn not to use np.matrix but breaking all their scripts is a painful way to do that
There are major projects like scikit-learn that simply have no alternative to using np.matrix, because of scipy.sparse.
So I think the way forward is something like:
Now or whenever someone gets together a PR: issue a PendingDeprecationWarning in np.matrix.__init__ (unless it kills performance for scikit-learn and friends), and put a big warning box at the top of the docs. The idea here is to not actually break anyone's code, but start to get out the message that we definitely don't think anyone should use this if they have any alternative.
After there's an alternative to scipy.sparse: ramp up the warnings, possibly all the way to FutureWarning so that existing scripts don't break but they do get noisy warnings
Eventually, if we think it will reduce maintenance costs: split it into a subpackage
( source )。
现状
截至 2018 年 5 月(numpy 1.15,相关 source 和 pull request), commit 包含以下注释:
It is no longer recommended to use this class, even for linear algebra. Instead use regular arrays. The class may be removed in the future.
同时numpy.matrix
已添加到PendingDeprecationWarning
。不幸的是, matrix class docstring ,所以大多数 numpy 的最终用户不会看到这个强烈的提示。
最后,截至 2018 年 11 月的 deprecation warnings are (almost always) silenced by default 提到了多个相关主题,作为“任务和功能 [numpy 社区] 将投入资源”之一:
Some things inside NumPy do not actually match the Scope of NumPy.
- A backend system for numpy.fft (so that e.g. fft-mkl doesn’t need to monkeypatch numpy)
- Rewrite masked arrays to not be a ndarray subclass – maybe in a separate project?
- MaskedArray as a duck-array type, and/or
- dtypes that support missing values
- Write a strategy on how to deal with overlap between numpy and scipy for linalg and fft (and implement it).
- Deprecate np.matrix
只要较大的库/许多用户(特别是matrix.__new__
)依赖矩阵类,这种状态就可能会保持下去。但是,有 the numpy roadmap 移动scipy.sparse
以依赖其他东西,例如 ongoing discussion 。不管弃用过程的发展如何,用户都应该在新代码中使用scipy.sparse
类,如果可能,最好移植旧代码。最终,矩阵类可能会在一个单独的包中结束,以消除由于它以当前形式存在而造成的一些负担。
关于python - NumPy 矩阵类的弃用状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53254738/
我是一名优秀的程序员,十分优秀!