SymPy 是一个用于符号型数学计算的 Python 库,它的目标是成为一个功能齐全的计算机代数系统 (CAS),同时保持代码尽可能简单,以便易于理解和扩展。

SymPy 可以进行数学表达式的符号计算、代数运算、微积分、方程求解、矩阵运算、绘图等多种功能。

我们先来使用 SymPy 计算 Sigmoid 函数。也就是根据中的公式计算如下微分方程,

from sympy import *

# 定义符号
t = symbols('t')
f = symbols('f', cls=Function)
# 定义微分方程
eq = Eq(f(t).diff(t),  f(t)*(1-f(t)))
# 求解带初始条件的微分方程
f_sol = dsolve(eq, ics={f(0): 1/2})

print(f_sol)
# 绘制微分方程的解
plot(f_sol.rhs, (t, -10, 10))

Eq(f(t), 1/(1 + 1.0*exp(-t)))
打开网易新闻 查看精彩图片

以上代码中我们取 。

怎么样,是不是很好用。其实你也可以改动微分方程来设计自己的激活函数。

好了,演示完毕,进入正题。

微积分运算

SymPy 提供了一些常见的微积分运算函数,例如:

  • diff函数可以对符号表达式进行求导,也可以求偏导数和高阶导数

  • integrate函数可以对符号表达式进行积分,也可以求定积分和多重积分。

  • limit函数可以计算符号表达式的极限,也可以求一侧极限和无穷极限。

  • solve函数可以解决符号方程,也可以求解微分方程和方程组。

要使用 SymPy,需要先安装并导入它,然后使用 symbols 函数创建符号变量,例如:

from sympy import *
x, y = symbols('x y')

然后你就可以对符号变量进行各种运算,例如:

展开 (x + 1)^2

expand((x + 1)**2)
# 输出 x*2 + 2x + 1

求导 sin(x)

diff(sin(x), x)
# 输出 cos(x)

求二阶导

f = x*2 + 2x + 1

# 二阶导数
ddf = diff(f, x, 2) 
ddf
# 输出 2

求极限 lim(x->0) sin(x)/x

limit(sin(x)/x, x, 0)
# 输出 1

求积分 int(x^2, x)

integrate(x**2, x)
# 输出 x**3/3

SymPy 还可以将数学表达式转换为 LaTeX 代码,方便在文档中显示,例如:

# 将 x^2 + 2*x + 1 转换为 LaTeX 代码
latex(x*2 + 2x + 1)

'x^{2} + 2 x + 1'
SymPy 支持的数学函数

SymPy 支持多种数学函数,包括:

  • 常用的标准函数,如三角函数、指数函数、对数函数、绝对值函数等。

  • 特殊的数学函数,如 函数、Bessel 函数、误差函数、超几何函数等。

  • 自定义函数,如 等。

你可以使用Function类来创建自定义函数,也可以使用symbols函数来指定某个符号为函数类型。例如:

# 使用 Function 类创建自定义函数
f = Function('f')
f(x)

# 使用 symbols 函数指定 g 为函数类型
g = symbols('g', cls=Function)
g(x)
SymPy 支持的数学常量

SymPy 支持多种数学常量,例如:

  • pi:圆周率,约等于 3.14159。

  • E:自然对数的底数,约等于 2.71828。

  • I:虚数单位,满足I**2 = -1

  • oo:正无穷大,满足oo > x对任意有限的 x 成立。

  • zoo:复数无穷大,满足zoo + x = zoo对任意有限的 x 成立。

  • nan:非数值,表示未定义的数学表达式。

  • GoldenRatio:黄金比例,约等于 1.61803。

  • EulerGamma:欧拉常数,约等于 0.57722。

  • Catalan:卡塔兰常数,约等于 0.91597。

可以使用这些常量来构建数学表达式或函数,例如:

# 计算 sin(pi/4)
sin(pi/4)
# 输出 sqrt(2)/2

# 计算 e^i*pi
E*(Ipi)
# 输出 -1

# 计算 limit((1 + 1/n)**n, n, oo)
n = symbols('n')
limit((1 + 1/n)**n, n, oo)
# 输出 E
SymPy 求导应用

SymPy 可以用来求解神经网络里的反向传播问题,即根据损失函数对网络参数进行梯度下降更新。

例如,以下代码将构建一个简单的神经网络,包含一个输入层、一个隐藏层和一个输出层,使用 sigmoid 激活函数和均方误差损失函数,然后对网络参数进行反向传播更新:

from sympy import *

# 定义符号变量
x, y = symbols('x y') # 输入和输出

w1, w2, b1, b2 = symbols('w1 w2 b1 b2') # 权重和偏置

alpha = symbols('alpha') # 学习率

# 定义神经网络
z1 = w1 * x + b1        # 隐藏层的线性部分
a1 = 1 / (1 + exp(-z1)) # 隐藏层的激活部分,使用 sigmoid 函数
z2 = w2 * a1 + b2       # 输出层的线性部分
a2 = 1 / (1 + exp(-z2)) # 输出层的激活部分,使用 sigmoid 函数

# 定义损失函数
L = (y - a2)**2 / 2     # 使用均方误差作为损失函数

# 对网络参数求偏导数
dLdw1 = diff(L, w1)     # 损失函数对 w1 的偏导数
dLdw2 = diff(L, w2)     # 损失函数对 w2 的偏导数
dLdb1 = diff(L, b1)     # 损失函数对 b1 的偏导数
dLdb2 = diff(L, b2)     # 损失函数对 b2 的偏导数

# 更新网络参数
w1_new = w1 - alpha * dLdw1 # 使用梯度下降法更新 w1
w2_new = w2 - alpha * dLdw2 # 使用梯度下降法更新 w2
b1_new = b1 - alpha * dLdb1 # 使用梯度下降法更新 b1
b2_new = b2 - alpha * dLdb2 # 使用梯度下降法更新 b2

# 打印更新后的网络参数
print(w1_new)
print(w2_new)
print(b1_new)
print(b2_new)

SymPy 提供了一个通用的微分方程求解工具dsolve,它能够找到许多基本微分方程的解析解。

dsolve可以用来符号化地求解一阶和高阶微分方程,以及具有较少未知函数的一阶线性常微分方程组。

要使用dsolve,需要遵循以下基本步骤:

  • 定义符号变量:首先,你需要定义用于表示未知函数和变量的符号。在 SymPy 中,可以使用Symbolsymbols函数来定义符号变量。例如,可以使用x = symbols('x')来定义一个名为 x 的符号变量。

  • 定义微分方程:其次,你需要将微分方程表示为符号表达式。在 SymPy 中,可以使用Eq函数来表示等式,使用Derivative函数来表示导数。例如,可以使用eq = Eq(Derivative(f(x), x) + f(x), x**2)来表示如下微分方程


  • 求解微分方程:一旦你定义了微分方程,就可以使用dsolve函数来求解微分方程。该函数将返回一个表示微分方程的解的符号表达式。例如,可以使用solution = dsolve(eq, f(x))来求解上述微分方程的解。

  • 初始条件:对于一般的微分方程,解中通常包含一些常数,如 等。为了获得特定的解,你需要为方程提供初始条件。在 SymPy 中,可以使用ics参数来指定初始条件。例如,可以使用solution = dsolve(eq, f(x), ics={f(0): 3})来求解上述微分方程在初始条件 下的解。

  • 计算特定解:最后,你可以使用subs函数将初始条件代入所获得的一般解中,得到特定的解。例如,可以使用solution.subs(x, 0)来计算上述微分方程的解在 时的值。

x = symbols('x')
eq = Eq(Derivative(f(x), x) + f(x), x**2)
solution = dsolve(eq, f(x))
solution

solution_ics = dsolve(eq, f(x), ics={f(0): 3})
solution_ics

solution_ics.subs(x, 0)
SymPy 的绘图功能

SymPy 提供了一个简单而强大的绘图模块,可以绘制各种类型的二维和三维图形。

SymPy 使用 Matplotlib 作为绘图后端,因此你需要安装 Matplotlib 才能使用 SymPy 的绘图功能。

SymPy 的绘图模块包含了以下几种主要的绘图函数:

  • plot:绘制二维线状图,可以绘制一个或多个符号表达式或函数。

  • plot_parametric:绘制二维参数图,可以绘制一个或多个参数化的曲线。

  • plot_implicit:绘制二维隐式图或区域图,可以绘制一个或多个隐式方程或不等式。

  • plot3d:绘制三维线状图,可以绘制一个或多个符号表达式或函数。

  • plot3d_parametric_line:绘制三维参数线图,可以绘制一个参数化的空间曲线。

  • plot3d_parametric_surface:绘制三维参数曲面图,可以绘制一个参数化的曲面。

要使用 SymPy 的绘图功能,你需要遵循以下基本步骤:

  • 导入绘图模块:首先,从 SymPy 中导入绘图模块,例如from sympy.plotting import plot

  • 定义符号变量:其次,定义用于表示未知函数和变量的符号。在 SymPy 中,可以使用Symbolsymbols函数来定义符号变量,例如x = symbols('x')

  • 调用绘图函数:最后,根据需求调用相应的绘图函数,传入符号表达式或函数,以及可选的范围和参数,例如plot(x**2, (x, -5, 5), title='y = x^2')

下面是一些使用 SymPy 绘图功能的示例:

绘制二维线状图

要绘制二维线状图,可以使用plot函数,传入一个或多个符号表达式或函数,以及可选的范围和参数。例如,以下代码将绘制 和 的图像,并设置标题和图例:

from sympy import *
from sympy.plotting import plot

x = symbols('x')
plot(x2, x3, (x, -5, 5), title='y = x^2 and y = x^3', legend=True)
打开网易新闻 查看精彩图片
绘制二维参数图

要绘制二维参数图,可以使用plot_parametric函数,传入一个或多个参数化的曲线,以及可选的范围和参数。例如,以下代码将绘制一个类似无穷大符号的图像,并设置标题和图例:

from sympy import *
from sympy.plotting import plot_parametric

t = symbols('t')
plot_parametric(2cos(t), sin(2t), (t, 0, 2*pi), title='Circle and Ellipse', legend=True)
打开网易新闻 查看精彩图片
绘制二维隐式图或区域图

要绘制二维隐式图或区域图,可以使用plot_implicit函数,传入一个或多个隐式方程或不等式,以及可选的范围和参数。例如,以下代码将绘制 和 的图像,并设置标题和图例:

from sympy import *
from sympy.plotting import plot_implicit

x, y = symbols('x y')
plot_implicit(Eq(x2 + y2, 5), (x, -4, 4), (y, -4, 4), depth = 0.6, title='Implicit Curves')
打开网易新闻 查看精彩图片
绘制三维线状图

要绘制三维线状图,可以使用plot3d函数,传入一个或多个符号表达式或函数,以及可选的范围和参数。例如,以下代码将绘制 和 的图像,并设置标题和图例:

from sympy import *
from sympy.plotting import plot3d
x, y = symbols('x y')

plot3d(x2 - y2, (x, -5, 5), (y, -5, 5), title='3D Surfaces')
打开网易新闻 查看精彩图片

plot3d(x2 + y2, (x, -5, 5), (y, -5, 5), title='3D Surfaces')
打开网易新闻 查看精彩图片
绘制三维参数线图

要绘制三维参数线图,可以使用plot3d_parametric_line函数,传入一个参数化的空间曲线,以及可选的范围和参数。例如,以下代码将绘制一个螺旋线的图像,并设置标题和图例:

from sympy import *
from sympy.plotting import plot3d_parametric_line

t = symbols('t')
plot3d_parametric_line(cos(t), sin(t), t, (t, 0, 10*pi), title='3D Parametric Line', legend=True)
打开网易新闻 查看精彩图片
绘制三维参数曲面图

要绘制三维参数曲面图,可以使用plot3d_parametric_surface函数,传入一个参数化的曲面,以及可选的范围和参数。例如,以下代码将绘制一个球面的图像,并设置标题和图例:

from sympy import *
from sympy.plotting import plot3d_parametric_surface

u, v = symbols('u v')

plot3d_parametric_surface(cos(u)sin(v), sin(u)sin(v), cos(v), (u, 0, 2*pi), (v, 0, pi), title='3D Parametric Surface')
打开网易新闻 查看精彩图片

好了,是不是觉得 SymPy 挺强大呢!赶紧去安装吧。