问题描述
我想使用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
推荐答案
混合numpy
和sympy
可能很棘手;加上由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
,所以w
和x
均为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*x
是np.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)+4
和1*2+4
都产生相同的结果.仅当变量是数组,np.mat
或sympy.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
此文档警告:
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))
,然后将操作委派给x
的sin
方法-该方法不存在.
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函数和乘法函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!