【问题标题】:Danger of mixing numpy matrix and array混合numpy矩阵和数组的危险
【发布时间】:2012-08-15 00:36:30
【问题描述】:

我正在研究的科学/工程应用程序有很多线性代数矩阵乘法,因此我使用 Numpy 矩阵。但是,python 中有许多函数可以互换地接受矩阵或数组类型。不错,不是吗?嗯,不是真的。让我用一个例子来说明这个问题:

from scipy.linalg import expm
from numpy import matrix

# Setup input variable as matrix
A = matrix([[ 0, -1.0,  0,  0],
            [ 0,  0,  0,  1.0],
            [ 0,  0,  0,  0],
            [ 0,  0,  1.0,  0]])

# Do some computation with that input
B = expm(A)

b1 = B[0:2, 2:4]
b2 = B[2:4, 2:4].T

# Compute and Print the desired output
print "The innocent but wrong answer:"
print b2 * b1

print "The answer I should get:"
print matrix(b2) * matrix(b1)

运行时会得到:

The innocent but wrong answer:
[[-0.16666667 -0.5       ]
 [ 0.          1.        ]]
The answer I should get, since I expected everything to still be matrices:
[[ 0.33333333  0.5       ]
 [ 0.5         1.        ]]

关于如何避免这种混淆的任何提示或建议?在 matrix() 调用中继续包装变量以确保它们仍然是矩阵真的很麻烦。在这方面似乎没有标准,因此可能会导致难以检测的错误。

【问题讨论】:

  • 这就是人们使用 Java 和其他静态语言的原因。 IDE 和编译器会因为使用不同的类型而绞尽脑汁(IDE 会告诉你类型)
  • 如果你想要点积,最好使用numpy.dot,而不是依赖于覆盖乘法运算符的矩阵。 Explicit is better than implicit.
  • 不得不使用 np.dot 真的很烦人,尤其是当你有如下等式时:A = GPG_tran+ MUM_tran
  • @Mehdi,我同意,但是,我发现坚持使用 numpy 数组总体上是一种更好的体验。不用担心返回类型,在矩阵上使用squeeze 来减少维度可能会很烦人(例如[[1]])。
  • 在今年的一次会议上,他们提到一旦采用另一种稀疏表示,numpy.matrix 就会贬值。避免使用 numpy.matrix 的另一个原因。

标签: python arrays matrix numpy


【解决方案1】:

出于以下几个原因,我倾向于在numpy 中使用array 而不是matrix

  1. matrix 严格来说是二维的,而numpy array 可以是任意维度的。
  2. 除了一些差异之外,arraymatrix 操作对于 Matlab 用户来说几乎是 interchangeable
  3. 如果您始终使用array,那么您将使用numpy.dot()(或在Python 3.5 中新的@ 二元运算符)进行矩阵乘法。这将防止不确定* 在您的代码中实际做了什么的问题。当您遇到乘法错误时,您可以更轻松地找到问题,因为您可以确定要执行的乘法类型。

所以我建议你尽量坚持numpy.array,但也要记住arraymatrix 之间的区别。

最后,我发现在bpython 上与numpy/scipy 合作很愉快。自动提示可以帮助您以比不断查阅numpy/scipy 文档更快的速度了解您尝试使用的功能的属性。

编辑: arraymatrix 之间的区别也许在这里得到最好的回答:'array' or 'matrix'? Which should I use?

【讨论】:

  • 但是牺牲了函数的可读性。例如:FGQG.TF.T**2 比任何 dot(a,b) 等效项都更具可读性。你不同意吗?另外,如果您没有注意到,我是一个 Matlab 转换器,发现 A * B 被定义为矩阵乘法是很自然的。
  • @user1609675 我认为这是一个有效的观点。但是由于我之前所有的科学计算都是使用 Matlab 进行的,因此语法差异对我来说几乎可以忽略不计,因为无论如何我都必须重新学习语法。习惯dot()需要一段时间,之后我就不再被它困扰了。它变得有点自然,真的:)
  • @user1609675 是的,我曾经为机器学习和自然语言处理做过大量的 Matlab。我认为这有助于我决定重新学习每一种语法,并通过重新连接心智模型逐渐忘记 Matlab 的方式。这需要一段时间,但我认为这是值得的。
  • FGQG.TF.T**2 ?你可以使用 np.einsum 干净地做到这一点。虽然这意味着使用特定的优化矩阵乘法库。但这也意味着要放弃很多临时工。可能会更快,具体取决于细节。
  • @EelcoHoogendoorn 那会是什么样子? np.einsum 对我来说是新的。
【解决方案2】:

混合矩阵和常规 ndarray 确实很棘手,而且通常不值得麻烦。我会支持其他海报并建议您坚持使用数组。

尽管如此,在您的特定示例中,问题来自expm。根据文档,它需要一个常规的ndarray 作为参数并输出一个 ndarray。如果您想将输出转换回matrix,您可以使用:

B = matrix(expm(A))

B = expm(A).view(matrix)

现在,B 是一个矩阵,B 的切片本身就是矩阵,您的乘法将按预期工作。

因此,建议始终检查函数输出的类型。

【讨论】:

    猜你喜欢
    • 2014-09-10
    • 2016-02-02
    • 2017-06-22
    • 2021-08-28
    • 2019-10-08
    • 1970-01-01
    • 1970-01-01
    • 2010-12-28
    • 1970-01-01
    相关资源
    最近更新 更多