简体   繁体   English

为什么 sympy lambdify function 无法识别 numpy 和 function 和乘以 ZC1C4214ABZ5074C

[英]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;混合numpysympy可能会很棘手; add to that the potential confusions caused by np.mat instead of the base array type, ndarray .再加上由np.mat而不是基本数组类型ndarray引起的潜在混淆。

In sum总共

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

details细节

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 ,所以wx都是 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

correction更正

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*xnp.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 矩阵概念,其中*作为矩阵乘法。

with sympy同情

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)+41*2+4都产生相同的东西。 It's only when the variables are arrays, or np.mat , or maybe sympy.Matrix that the expressions are different.只有当变量是 arrays 或np.matsympy.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 之间架起一座桥梁。

sympify同化

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))然后将操作委托给xsin方法 - 该方法不存在。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM