为什么sympy lambdify函数无法识别numpy sum函数和乘法函数 [英] Why sympy lambdify function cannot identify numpy sum function and multiply function

查看:97
本文介绍了为什么sympy lambdify函数无法识别numpy sum函数和乘法函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想使用sympy和numpy来学习机器学习.因为symoy提供了非常方便的偏导数计算. 但是在使用过程中,我发现了sympy lambdify函数,无法识别numpy sum函数和乘法函数.

I want to use sympy and numpy to learning machine learning. Because symoy provides very convenient partial derivative calculation. But in the process of use, I found that sympy lambdify function and can't identify the numpy sum function and multiply function.

以下面的示例为例

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)

如您所见,lambdify仅接受lamda表达式而无需检查操作符号.如何解决这个问题呢.谢谢您的帮助

As you can see,lambdify simply accepts lamda expressions without checking the operation notation. How to solve this problem. Thank you for your help

推荐答案

混合numpysympy可能很棘手;加上由np.mat而不是基本数组类型ndarray引起的潜在混乱.

Mixing numpy and sympy can be tricky; add to that the potential confusions caused by np.mat instead of the base array type, ndarray.

y_ = np.sum(np.dot(w,x)+b)

在sympy对象上评估python/numpy表达式.结果是一个sympy表达式w*x+b. sympy对象是标量,因此不会编码任何形式的矩阵乘法或数组求和. multiply表达式的计算方式相同.

evaluates a python/numpy expression on sympy objects. The result is a sympy expression w*x+b. The sympy objects are scalars, so this doesn't encode any sort of matrix multiplication, or array summation. The multiply expression evaluates the same way.

lambdify表达式然后将相同的y_转换为相同的Python函数.该评估取决于np.mat参数的维度和类别.

The lambdify expressions then translate the same y_ to the same Python function. And that evaluation depends on the dimensions and class of the np.mat arguments.

暂时忽略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]])

因为它们是np.mat,所以wx均为2d:

Because they are np.mat, both w and x are 2d:

In [316]: w.shape                                                               
Out[316]: (1, 5)
In [317]: x.shape                                                               
Out[317]: (5, 1)

(1,5)与(5,1)中的

np.dot是(1,1)结果:

np.dot of (1,5) with (5,1) is a (1,1) result:

In [313]: np.dot(w,x)                                                           
Out[313]: matrix([[5]])

,对于np.matrix*被定义为dot:

In [314]: w*x                                                                   
Out[314]: matrix([[5]])

逐元素:

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)执行dot,然后添加b,并在所有元素上以sum结尾.

np.sum(np.dot(w,x)+b) does the dot, then adds b, and ends with a sum over all elements.

np.multiply(w,x)+b进行乘法运算,添加b.没有sum.

np.multiply(w,x)+b does this multiply, adds b. There's no sum.

使用我第一次错过的w.T:

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)

(5,1)和(5,1)中的

np.multiply会生成(5,1)元素逐次乘法

np.multiply of (5,1) and (5,1) produces (5,1), element wise multiplication

w.T*xnp.mat的矩阵乘法,因此是np.dot误差.

w.T*x is matrix multiplication for np.mat, hence the np.dot error.

不鼓励使用np.mat(如果未正式描述).在numpy中,添加matmul/@会消除其符号上的优势.如果坚持使用基本数组类ndarray,则numpy中的生活会更简单.我意识到sympy仍然使用2d矩阵概念,其中*作为矩阵乘法.

The use of np.mat is discouraged (if not formally depricated). In numpy the addition of matmul/@ eliminates its notational advantages. Life is simpler in numpy if you stick with the base array class, ndarray. I realize that sympy still uses a 2d matrix concept, with * as matrix multiplication.

isympy会话中,我发现需要将w,x,b定义为符号:

In a isympy session, I find that I need to define w,x,b as symbols:

y_ = np.sum(np.dot(w,x)+b)

如果w,x,b仅仅是Symbols,则它们是标量,而不是矩阵或数组.您的np.sum(np.dot(1,2)+4)np.multiply(1,2)+41*2+4都产生相同的结果.仅当变量是数组,np.matsympy.Matrix时,表达式才不同.

If w,x,b are just Symbols, they are scalars, not matrices or arrays. Your np.sum(np.dot(1,2)+4), np.multiply(1,2)+4 and 1*2+4 all produce the same thing. It's only when the variables are arrays, or np.mat, or maybe sympy.Matrix that the expressions are different.

问题不是lambdify.在这两种情况下,它都被赋予相同的y_(由print(y_)验证.由于参数为np.mat,而*为矩阵乘法,因此会出现错误.

The problem isn't with 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.

带有x,y,z符号:

In [55]: f = lambdify((x,y,z),x*y+z, 'numpy')                                   

使用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

阅读lambdify的完整文档.请注意,它基本上是词汇替换

Read the full documentation for lambdify. Note that it is basically a lexical substitution

https://docs.sympy.org/latest/modules/utilities /lambdify.html

此文档警告:

通常,NumPy 函数不知道如何对SymPy表达式和SymPy进行运算 函数不知道如何对NumPy数组进行操作.这就是为什么lambdify 存在:在SymPy和NumPy之间架起一座桥梁.

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. This is why lambdify exists: to provide a bridge between SymPy and NumPy.

sympify

https://docs.sympy.org /latest/modules/core.html#module-sympy.core.sympify

表示它使用eval.将x,y,z定义为符号:

says it uses eval. With x,y,z defined as symbols:

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

换句话说,它只是将符号传递给numpy函数(和/或运算符),

In other words, it just passes the symbols to the numpy functions (and/or operators),

In [69]: np.dot(x,y)                                                            
Out[69]: x⋅y

dot将其输入转换为数组:

dot turns its inputs into 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文档警告说,评估numpy不会了解"关于sympy对象的任何信息.它将它们视为对象dtype数组,可能有效也可能无效:

sympy docs warn that evaluating numpy does not 'know' anything about sympy objects. It treats them as object dtype arrays, which may or might not work:

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

np.sin执行np.sin(np.array(x)),然后将操作委派给xsin方法-该方法不存在.

The np.sin does np.sin(np.array(x)) and then delegates the action to a sin method of x - which does not exist.

这篇关于为什么sympy lambdify函数无法识别numpy sum函数和乘法函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆