使矩阵乘法运算符@对numpy中的标量有效

jhi*_*hin 6 python signal-processing numpy linear-algebra matrix-multiplication

在python 3.5中,在PEP465之后@引入了用于矩阵乘法的运算。这例如在numpy中作为matmul运算符实现

但是,按照PEP的建议,当用标量操作数调用numpy运算符时会引发异常:

>>> import numpy as np
>>> np.array([[1,2],[3,4]]) @ np.array([[1,2],[3,4]])    # works
array([[ 7, 10],
       [15, 22]])
>>> 1 @ 2                                                # doesn't work
Traceback (most recent call last):
  File "<input>", line 1, in <module>
TypeError: unsupported operand type(s) for @: 'int' and 'int'
Run Code Online (Sandbox Code Playgroud)

对我来说,这是一个真正的选择,因为我正在实现对标量和矩阵均适用的数字信号处理算法。两种情况下的方程在数学上都是完全等价的,这并不奇怪,因为“ 1-D x 1-D矩阵乘法”等效于标量乘法。但是,当前状态迫使我编写重复的代码,以便正确处理这两种情况。

因此,鉴于当前状态不令人满意,是否有任何合理的方法可以使@操作员使用标量?我曾考虑过向__matmul__(self, other)标量数据类型添加自定义方法,但是考虑到涉及的内部数据类型的数量,这似乎很麻烦。我可以更改__matmul__numpy数组数据类型的方法的实现,以不为1x1数组操作数抛出异常吗?

而且,在旁注中,此设计决定的依据是什么?我不由自主地想到,没有任何令人信服的理由也不要将这种运算符用于标量。

小智 10

正如ajcr所建议的,您可以通过对相乘的对象强制一些最小维度来解决此问题。有两个合理的选项:atleast_1datleast_2d,它们对于 所返回的类型有不同的结果@:标量与 1×1 2D 数组。

x = 3
y = 5
z = np.atleast_1d(x) @ np.atleast_1d(y)   # returns 15 
z = np.atleast_2d(x) @ np.atleast_2d(y)   # returns array([[15]])
Run Code Online (Sandbox Code Playgroud)

然而:

  • 如果 x 和 y 是原本会正常相乘的一维数组,则使用 atleast_2d 将导致错误
  • 使用 atleast_1d 会产生一个标量或矩阵的乘积,但您不知道是哪一个。
  • 这两种方法都比np.dot(x, y)处理所有这些情况更详细。

此外, atleast_1d 版本也存在同样的缺陷,标量 @ 标量 = 标量也会共享该缺陷:您不知道可以对输出做什么。会z.Tz.shape抛出错误吗?这些适用于 1×1 矩阵,但不适用于标量。在Python的设置中,我们根本不能忽略标量和1×1数组之间的区别,而不放弃后者所拥有的所有方法和属性。