[英]Why sympy lambdify function cannot identify numpy sum function and multiply function
I want to use sympy and numpy to learning machine learning.我想用 sympy 和 numpy 来学习机器学习。 Because symoy provides very convenient partial derivative calculation.
因为 symoy 提供了非常方便的偏导数计算。 But in the process of use, I found that sympy lambdify function and can't identify the numpy sum function and multiply function.
But in the process of use, I found that sympy lambdify function and can't identify the numpy sum function and multiply function.
Take the following example举个例子
y_ = np.sum(np.dot(w,x)+b)
print(y_)
y_f = lambdify((w,x,b),y_,"numpy")
w_l = np.mat([1,1,1,1,1])
x_l= np.mat([1,1,1,1,1]).T
b_l = np.mat([0,0,0,0,0]).T
y_l = np.mat([6,6,6,6,6]).T
print(y_f(w_l,x_l,b_l))
b + w*x
[[5]
[5]
[5]
[5]
[5]]
Process finished with exit code 0
y_ = np.multiply(w,x)+b
print(y_)
y_f = lambdify((w,x,b),y_,"numpy")
w_l = np.mat([1,1,1,1,1]).T
x_l= np.mat([1,1,1,1,1]).T
b_l = np.mat([0,0,0,0,0]).T
y_l = np.mat([6,6,6,6,6]).T
print(y_f(w_l,x_l,b_l))
b + w*x
Traceback (most recent call last):
File "G:/lijie/PycharmProjects/hw3/test.py", line 24, in <module>
print(y_f(w_l,x_l,b_l))
File "<lambdifygenerated-1>", line 2, in _lambdifygenerated
File "C:\Users\lijie\AppData\Local\Programs\Python\Python36\lib\site-packages\numpy\matrixlib\defmatrix.py", line 220, in __mul__
return N.dot(self, asmatrix(other))
ValueError: shapes (5,1) and (5,1) not aligned: 1 (dim 1) != 5 (dim 0)
b + w*x
Traceback (most recent call last):
File "G:/lijie/PycharmProjects/hw3/test.py", line 24, in <module>
print(y_f(w_l,x_l,b_l))
File "<lambdifygenerated-1>", line 2, in _lambdifygenerated
File "C:\Users\lijie\AppData\Local\Programs\Python\Python36\lib\site-packages\numpy\matrixlib\defmatrix.py", line 220, in __mul__
return N.dot(self, asmatrix(other))
ValueError: shapes (5,1) and (5,1) not aligned: 1 (dim 1) != 5 (dim 0)
As you can see,lambdify simply accepts lamda expressions without checking the operation notation.如您所见,lambdify 只接受 lamda 表达式而不检查操作符号。 How to solve this problem.
如何解决这个问题呢。 Thank you for your help
谢谢您的帮助
Mixing numpy
and sympy
can be tricky;混合
numpy
和sympy
可能会很棘手; add to that the potential confusions caused by np.mat
instead of the base array type, ndarray
.再加上由
np.mat
而不是基本数组类型ndarray
引起的潜在混淆。
y_ = np.sum(np.dot(w,x)+b)
evaluates a python/numpy expression on sympy objects.评估 sympy 对象上的 python/numpy 表达式。 The result is a sympy expression
w*x+b
.结果是一个 sympy 表达式
w*x+b
。 The sympy objects are scalars, so this doesn't encode any sort of matrix multiplication, or array summation. sympy 对象是标量,因此它不编码任何类型的矩阵乘法或数组求和。 The
multiply
expression evaluates the same way. multiply
表达式的计算方式相同。
The lambdify
expressions then translate the same y_
to the same Python function.然后,
lambdify
表达式将相同的y_
转换为相同的 Python function。 And that evaluation depends on the dimensions and class of the np.mat
arguments.该评估取决于 np.mat arguments 的尺寸和
np.mat
。
Ignoring the sympy
part for now:现在忽略
sympy
部分:
In [310]: w = np.mat([1,1,1,1,1])
...: x= np.mat([1,1,1,1,1]).T
...: b = np.mat([0,0,0,0,0]).T
...: y = np.mat([6,6,6,6,6]).T
In [311]: np.sum(np.dot(w,x)+b)
Out[311]: 25
In [312]: np.multiply(w,x)+b
Out[312]:
matrix([[1, 1, 1, 1, 1],
[1, 1, 1, 1, 1],
[1, 1, 1, 1, 1],
[1, 1, 1, 1, 1],
[1, 1, 1, 1, 1]])
Because they are np.mat
, both w
and x
are 2d:因为它们是
np.mat
,所以w
和x
都是 2d:
In [316]: w.shape
Out[316]: (1, 5)
In [317]: x.shape
Out[317]: (5, 1)
np.dot
of (1,5) with (5,1) is a (1,1) result: (1,5) 和 (5,1) 的
np.dot
是 (1,1) 结果:
In [313]: np.dot(w,x)
Out[313]: matrix([[5]])
and for np.matrix
, *
is defined as the dot
:对于
np.matrix
, *
被定义为dot
:
In [314]: w*x
Out[314]: matrix([[5]])
Elementwise:元素方面:
In [315]: np.multiply(w,x) # elementwise produces (5,5)
Out[315]:
matrix([[1, 1, 1, 1, 1],
[1, 1, 1, 1, 1],
[1, 1, 1, 1, 1],
[1, 1, 1, 1, 1],
[1, 1, 1, 1, 1]])
np.sum(np.dot(w,x)+b)
does the dot
, then adds b
, and ends with a sum
over all elements. np.sum(np.dot(w,x)+b)
执行dot
,然后添加b
,并以所有元素的sum
结束。
np.multiply(w,x)+b
does this multiply, adds b
. np.multiply(w,x)+b
做这个乘法,加b
。 There's no sum
.没有
sum
。
Using the wT
that I missed the first time:使用我第一次错过的
wT
:
In [322]: np.multiply(w.T,x)
Out[322]:
matrix([[1],
[1],
[1],
[1],
[1]])
In [323]: w.T*x
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-323-11ad839cfa88> in <module>
----> 1 w.T*x
/usr/local/lib/python3.6/dist-packages/numpy/matrixlib/defmatrix.py in __mul__(self, other)
218 if isinstance(other, (N.ndarray, list, tuple)) :
219 # This promotes 1-D vectors to row vectors
--> 220 return N.dot(self, asmatrix(other))
221 if isscalar(other) or not hasattr(other, '__rmul__') :
222 return N.dot(self, other)
<__array_function__ internals> in dot(*args, **kwargs)
ValueError: shapes (5,1) and (5,1) not aligned: 1 (dim 1) != 5 (dim 0)
np.multiply
of (5,1) and (5,1) produces (5,1), element wise multiplication (5,1) 和 (5,1) 的
np.multiply
产生 (5,1),元素乘法
wT*x
is matrix multiplication for np.mat
, hence the np.dot
error. wT*x
是np.mat
的矩阵乘法,因此是np.dot
错误。
The use of np.mat
is discouraged (if not formally depricated).不鼓励使用
np.mat
(如果没有正式贬低)。 In numpy
the addition of matmul/@
eliminates its notational advantages.在
numpy
中,添加matmul/@
消除了它的符号优势。 Life is simpler in numpy
if you stick with the base array class, ndarray
.如果您坚持使用基本阵列 class,
ndarray
numpy
生活会更简单。 I realize that sympy
still uses a 2d matrix concept, with *
as matrix multiplication.我意识到
sympy
仍然使用 2d 矩阵概念,其中*
作为矩阵乘法。
In a isympy
session, I find that I need to define w,x,b
as symbols:在
isympy
session 中,我发现我需要将w,x,b
定义为符号:
y_ = np.sum(np.dot(w,x)+b)
If w,x,b
are just Symbols, they are scalars, not matrices or arrays.如果
w,x,b
只是符号,它们是标量,而不是矩阵或 arrays。 Your np.sum(np.dot(1,2)+4)
, np.multiply(1,2)+4
and 1*2+4
all produce the same thing.你的
np.sum(np.dot(1,2)+4)
, np.multiply(1,2)+4
和1*2+4
都产生相同的东西。 It's only when the variables are arrays, or np.mat
, or maybe sympy.Matrix
that the expressions are different.只有当变量是 arrays 或
np.mat
或sympy.Matrix
时,表达式才会不同。
The problem isn't with lambdify
.问题不
lambdify
。 In both cases it is given the same y_
(as verified by the print(y_)
. You get the error because the arguments are np.mat
, and *
is matrix multiplication.在这两种情况下,它都被赋予相同的
y_
(由print(y_)
验证。您会收到错误,因为 arguments 是np.mat
,而*
是矩阵乘法。
With x,y,z
symbols:使用
x,y,z
符号:
In [55]: f = lambdify((x,y,z),x*y+z, 'numpy')
Using isympy
introspection:使用
isympy
内省:
In [56]: f??
Signature: f(x, y, z)
Docstring:
Created with lambdify. Signature:
func(x, y, z)
Expression:
x*y + z
Source code:
def _lambdifygenerated(x, y, z):
return (x*y + z)
Imported modules:
Source:
def _lambdifygenerated(x, y, z):
return (x*y + z)
File: ~/mypy/<lambdifygenerated-4>
Type: function
Read the full documentation for lambdify
.阅读
lambdify
的完整文档。 Note that it is basically a lexical substitution请注意,它基本上是一个词法替换
https://docs.sympy.org/latest/modules/utilities/lambdify.html https://docs.sympy.org/latest/modules/utilities/lambdify.html
This documentation warns:本文档警告:
As a general rule, NumPy functions do not know how to operate on SymPy expressions, and SymPy functions do not know how to operate on NumPy arrays.
作为一般规则,NumPy 函数不知道如何对 SymPy 表达式进行操作,而 SymPy 函数不知道如何对 NumPy arrays 进行操作。 This is why lambdify exists: to provide a bridge between SymPy and NumPy.
这就是 lambdify 存在的原因:在 SymPy 和 NumPy 之间架起一座桥梁。
https://docs.sympy.org/latest/modules/core.html#module-sympy.core.sympify https://docs.sympy.org/latest/modules/core.html#module-sympy.core.sympify
says it uses eval
.说它使用
eval
。 With x,y,z
defined as symbols:将
x,y,z
定义为符号:
In [66]: eval('np.dot(x,y)+z')
Out[66]: x⋅y + z
In [67]: eval('np.sum(np.dot(x,y)+z)')
Out[67]: x⋅y + z
In [68]: eval('np.multiply(x,y)+z')
Out[68]: x⋅y + z
In other words, it just passes the symbols to the numpy functions (and/or operators),换句话说,它只是将符号传递给 numpy 函数(和/或运算符),
In [69]: np.dot(x,y)
Out[69]: x⋅y
dot
turns its inputs into arrays: dot
将其输入转换为 arrays:
In [70]: np.array(x)
Out[70]: array(x, dtype=object)
In [71]: np.dot(np.array(x), np.array(y))
Out[71]: x⋅y
This works because symbols have '*' and '+' defined.这是有效的,因为符号定义了“*”和“+”。
sympy
docs warn that evaluating numpy
does not 'know' anything about sympy objects. sympy
文档警告说,评估numpy
对 sympy 对象一无所知。 It treats them as object dtype arrays, which may or might not work:它将它们视为 object dtype arrays,这可能有效也可能无效:
In [72]: sin(x) # sympy sin
Out[72]: sin(x)
In [73]: np.sin(x) # numpy sin
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
AttributeError: 'Symbol' object has no attribute 'sin'
The above exception was the direct cause of the following exception:
TypeError Traceback (most recent call last)
<ipython-input-73-92f2c2d0df9d> in <module>
----> 1 np.sin(x)
TypeError: loop of ufunc does not support argument 0 of type Symbol which has no callable sin method
The np.sin
does np.sin(np.array(x))
and then delegates the action to a sin
method of x
- which does not exist. np.sin
执行np.sin(np.array(x))
然后将操作委托给x
的sin
方法 - 该方法不存在。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.