(Python Numpy) 是否存在赋值运算符(例如 *=)起作用但长手版本不起作用的情况?
(Python Numpy) Are there cases where assignment operators (eg. *=) work but the long hand versions don't?
我将两个相同大小的矩阵 A 和 B 逐元素相乘。当我使用以下代码时出现 'shapes not aligned' 错误:
A = A*B
但是以下代码可以正常工作:
A *= B
这些有区别吗?是否存在第二个可以工作而第一个不能工作的情况?我真的很困惑,因为我认为他们做了同样的事情。
错误是由于 A 是一个 nd 数组而 B 是 'matrix' 类型。
使用:
A = A * np.asarray(B)
转换矩阵有效。
我还是想知道一个有效而另一个无效的原因!
是的。就地运算符使用不同的 dunders than standard operators. In order to use inplace operators,例如*=
必须为带有参数的实例定义 __imul__
方法。相反,*
运算符使用实例的 __mul__
方法。
如果正如您在答案中注意到的那样,一个数组是 np.matrix
:
In [52]: A = np.ones((1,3)); B = np.matrix([1,2,3])
In [53]: A
Out[53]: array([[1., 1., 1.]])
In [54]: B
Out[54]: matrix([[1, 2, 3]])
它们的形状相同。但是 *
for B
是矩阵乘法。
In [55]: A*B
Traceback (most recent call last):
File "<ipython-input-55-47896efed660>", line 1, in <module>
A*B
File "/usr/local/lib/python3.8/dist-packages/numpy/matrixlib/defmatrix.py", line 224,
in __rmul__
return N.dot(other, self)
File "<__array_function__ internals>", line 5, in dot
ValueError: shapes (1,3) and (1,3) not aligned: 3 (dim 1) != 1 (dim 0)
请注意,A*B
变为 B.__rmul__(A)
,后者又被计算为 np.dot(A,B)
。
dot
for (1,3) with (3,1) 产生 (1,1) 内积。还要注意结果是 np.matrix
.
In [56]: A*B.T
Out[56]: matrix([[6.]])
在*=
A's
乘法规则中:
In [57]: A *=B
In [58]: A
Out[58]: array([[1., 2., 3.]])
@
是矩阵乘法运算符:
In [59]: A@B
Traceback (most recent call last):
File "<ipython-input-59-5016aafd2858>", line 1, in <module>
A@B
ValueError: matmul: Input operand 1 has a mismatch in its core dimension 0, with gufunc signature (n?,k),(k,m?)->(n?,m?) (size 1 is different from 3)
In [60]: A@B.T
Out[60]: matrix([[14.]])
正在将 B
转换为 np.array:
In [61]: B.A
Out[61]: array([[1, 2, 3]])
In [62]: A@(B.T).A
Out[62]: array([[14.]])
查看 np.matrix
文档。
为什么 A*B
使用 B's
乘法定义而不是 A's
?因为matrix
的优先级更高:
In [63]: B.__array_priority__
Out[63]: 10.0
In [64]: A.__array_priority__
Out[64]: 0.0
注意当 B
在右边时会发生什么:
In [70]: B *= A
Traceback (most recent call last):
File "<ipython-input-70-50eabec4c4f6>", line 1, in <module>
B *= A
File "/usr/local/lib/python3.8/dist-packages/numpy/matrixlib/defmatrix.py", line 227, in __imul__
self[:] = self * other
File "/usr/local/lib/python3.8/dist-packages/numpy/matrixlib/defmatrix.py", line 218, in __mul__
return N.dot(self, asmatrix(other))
File "<__array_function__ internals>", line 5, in dot
ValueError: shapes (1,3) and (1,3) not aligned: 3 (dim 1) != 1 (dim 0)
In [71]: B *= A.T
In [72]: B
Out[72]: matrix([[14, 14, 14]])
即使 np.matrix
不是一个因素,A*=...
也会有所不同,因为 A's
shape 和 dtype 不能改变。 A=A*
创建一个新数组,它可能具有不同的形状或数据类型。
例如Out[72]
是int dtype,就像原来的B
一样。 Out[58]
是浮动的,就像原来的 A
.
由于优先级的关系,A*B
被评估为B.__rmul__(A)
。将此代码与 In[55]
:
的回溯进行比较
Signature: B.__rmul__(other)
Docstring: Return value*self.
Source:
def __rmul__(self, other):
return N.dot(other, self)
我将两个相同大小的矩阵 A 和 B 逐元素相乘。当我使用以下代码时出现 'shapes not aligned' 错误:
A = A*B
但是以下代码可以正常工作:
A *= B
这些有区别吗?是否存在第二个可以工作而第一个不能工作的情况?我真的很困惑,因为我认为他们做了同样的事情。
错误是由于 A 是一个 nd 数组而 B 是 'matrix' 类型。
使用:
A = A * np.asarray(B)
转换矩阵有效。
我还是想知道一个有效而另一个无效的原因!
是的。就地运算符使用不同的 dunders than standard operators. In order to use inplace operators,例如*=
必须为带有参数的实例定义 __imul__
方法。相反,*
运算符使用实例的 __mul__
方法。
如果正如您在答案中注意到的那样,一个数组是 np.matrix
:
In [52]: A = np.ones((1,3)); B = np.matrix([1,2,3])
In [53]: A
Out[53]: array([[1., 1., 1.]])
In [54]: B
Out[54]: matrix([[1, 2, 3]])
它们的形状相同。但是 *
for B
是矩阵乘法。
In [55]: A*B
Traceback (most recent call last):
File "<ipython-input-55-47896efed660>", line 1, in <module>
A*B
File "/usr/local/lib/python3.8/dist-packages/numpy/matrixlib/defmatrix.py", line 224,
in __rmul__
return N.dot(other, self)
File "<__array_function__ internals>", line 5, in dot
ValueError: shapes (1,3) and (1,3) not aligned: 3 (dim 1) != 1 (dim 0)
请注意,A*B
变为 B.__rmul__(A)
,后者又被计算为 np.dot(A,B)
。
dot
for (1,3) with (3,1) 产生 (1,1) 内积。还要注意结果是 np.matrix
.
In [56]: A*B.T
Out[56]: matrix([[6.]])
在*=
A's
乘法规则中:
In [57]: A *=B
In [58]: A
Out[58]: array([[1., 2., 3.]])
@
是矩阵乘法运算符:
In [59]: A@B
Traceback (most recent call last):
File "<ipython-input-59-5016aafd2858>", line 1, in <module>
A@B
ValueError: matmul: Input operand 1 has a mismatch in its core dimension 0, with gufunc signature (n?,k),(k,m?)->(n?,m?) (size 1 is different from 3)
In [60]: A@B.T
Out[60]: matrix([[14.]])
正在将 B
转换为 np.array:
In [61]: B.A
Out[61]: array([[1, 2, 3]])
In [62]: A@(B.T).A
Out[62]: array([[14.]])
查看 np.matrix
文档。
为什么 A*B
使用 B's
乘法定义而不是 A's
?因为matrix
的优先级更高:
In [63]: B.__array_priority__
Out[63]: 10.0
In [64]: A.__array_priority__
Out[64]: 0.0
注意当 B
在右边时会发生什么:
In [70]: B *= A
Traceback (most recent call last):
File "<ipython-input-70-50eabec4c4f6>", line 1, in <module>
B *= A
File "/usr/local/lib/python3.8/dist-packages/numpy/matrixlib/defmatrix.py", line 227, in __imul__
self[:] = self * other
File "/usr/local/lib/python3.8/dist-packages/numpy/matrixlib/defmatrix.py", line 218, in __mul__
return N.dot(self, asmatrix(other))
File "<__array_function__ internals>", line 5, in dot
ValueError: shapes (1,3) and (1,3) not aligned: 3 (dim 1) != 1 (dim 0)
In [71]: B *= A.T
In [72]: B
Out[72]: matrix([[14, 14, 14]])
即使 np.matrix
不是一个因素,A*=...
也会有所不同,因为 A's
shape 和 dtype 不能改变。 A=A*
创建一个新数组,它可能具有不同的形状或数据类型。
例如Out[72]
是int dtype,就像原来的B
一样。 Out[58]
是浮动的,就像原来的 A
.
由于优先级的关系,A*B
被评估为B.__rmul__(A)
。将此代码与 In[55]
:
Signature: B.__rmul__(other)
Docstring: Return value*self.
Source:
def __rmul__(self, other):
return N.dot(other, self)