在 numpy 中定义矩阵和点积是标准的,如下所示
import numpy as np
a = np.array([[1, 2, 3], [4, 5, 6]])
b = np.array([[7, 8, 9, 10], [11, 12, 13, 14], [15, 16, 17, 18]])
print(a.shape)
print(b.shape)
print(a.dot(b).shape)
Run Code Online (Sandbox Code Playgroud)
按预期输出:
(2, 3)
(3, 4)
(2, 4)
Run Code Online (Sandbox Code Playgroud)
但令我惊讶的是,以下内容在 sympy 中失败
import sympy as sp
a = sp.Matrix([[1, 2, 3], [4, 5, 6]])
b = sp.Matrix([[7, 8, 9, 10], [11, 12, 13, 14], [15, 16, 17, 18]])
print(a.shape)
print(b.shape)
print(a.dot(b).shape)
Run Code Online (Sandbox Code Playgroud)
哪个输出
(2, 3)
(3, 4)
---------------------------------------------------------------------------
ShapeError Traceback (most recent call last)
<ipython-input-30-50c934c7fbaf> in <module>()
4 print(a.shape)
5 print(b.shape)
----> 6 print(a.dot(b).shape)
~/miniconda3/lib/python3.6/site-packages/sympy/matrices/matrices.py in dot(self, b)
2389 mat = mat.T
2390 b = b.T
-> 2391 prod = flatten((mat * b).tolist())
2392 if len(prod) == 1:
2393 return prod[0]
~/miniconda3/lib/python3.6/site-packages/sympy/core/decorators.py in binary_op_wrapper(self, other)
130 else:
131 return f(self)
--> 132 return func(self, other)
133 return binary_op_wrapper
134 return priority_decorator
~/miniconda3/lib/python3.6/site-packages/sympy/matrices/common.py in __mul__(self, other)
2006 if self.shape[1] != other.shape[0]:
2007 raise ShapeError("Matrix size mismatch: %s * %s." % (
-> 2008 self.shape, other.shape))
2009
2010 # honest sympy matrices defer to their class's routine
ShapeError: Matrix size mismatch: (3, 2) * (4, 3).
Run Code Online (Sandbox Code Playgroud)
这让我很困惑!
为什么 numpy 和 sympy 不一致?
为什么我在 sympy 的文档中找不到这种行为的警告?
如何在 sympy 中正确计算两个矩阵的点积?
我可以建议 sympy 的文档中有一个关于 numpy 和 sympy 之间语法差异的条目。(我很乐意做出贡献,但我不知道这些差异)
我将在 Github 上发布来自 SymPy 开发人员的回复:
作为一般规则,在 NumPy 中,所有操作都对数组进行向量化。在 SymPy 中,操作执行它们通常的数学意义。这意味着 SymPy 通常更严格地保持数学上的“纯”。
最明显的第一个:在 NumPy 中,一切都是数字。函数接受一个数字或数字数组并产生一个数字或数字数组。在 SymPy 中,一切都是象征性的。表达式可以使用默认情况下保持未计算的符号变量。例如, np.exp(np.pi) 产生一个数字,但 sympy.exp(sympy.pi) 产生一个未计算的表达式(可以用 sympy.exp(sympy.pi).evalf() 计算为一个数字) .
通常,SymPy 函数不适用于 NumPy 数组,而 NumPy 函数不适用于 SymPy 表达式。如果您想混合使用 SymPy 和 NumPy,建议使用 Lambdify(从仅使用 SymPy 函数的 SymPy 表达式开始,然后使用 lambdify 将其转换为等效的 NumPy 函数,并在具有 NumPy 数值类型的 NumPy 数组上使用它)。我已经在 StackOverflow 上多次讨论过这个问题。
'*' 是矩阵乘法。请注意,@(Python 3.5+)在 NumPy 和 SymPy 中进行矩阵乘法。
sympy.Matrix 总是排名 2。NumPy 数组可以是任何排名。请注意,NumPy 中的 dot/@ 可用于任何秩数组。rank 1 数组有一些奇怪的行为(它基本上将它们视为列向量或行向量,具体取决于上下文)。
在 SymPy 中的矩阵上调用数学函数,如果它有效,则执行该函数的分析矩阵估值。例如,exp(M) 计算矩阵指数。Matrix.applyfunc 可用于按元素应用函数。在 NumPy 中,exp(A) 取 A 的每个元素的指数(使用 scipy.linalg.expm 取 NumPy 数组的矩阵指数)。
np.dot 做矩阵乘法。在 SymPy 中,dot 做点积(需要两个 1xn 或 nx1 矩阵并产生一个标量)。如果参数不是 1xn,则 sympy.dot 错误(实际上当前在 master 中会给出弃用警告)。
1x1 矩阵不被视为与 SymPy 中的标量相同的东西。1 + Matrix([[1]]) 是一个错误。
小智 5
SymPy 中的矩阵乘积计算为a*b。
SymPy 中的方法dot旨在允许计算表示向量的两个矩阵的点积,例如:
>>> sp.Matrix([1, 2]).dot(sp.Matrix([3, 4]))
11
Run Code Online (Sandbox Code Playgroud)
是两个列向量的点积。这涉及到一个转置。
返回 Matrix self 和 b 的点积,放宽兼容维度的条件:如果行数或列数与 b 的长度相同,则返回点积。如果 self 是行或列向量,则返回标量。否则,返回结果列表(在这种情况下,self 中的列数必须与 b 的长度匹配)。