Skip to content

Latest commit

 

History

History
101 lines (66 loc) · 2.84 KB

symbolic_computing.md

File metadata and controls

101 lines (66 loc) · 2.84 KB

符号计算

什么是符号计算?

c = a + b
d = a - b
e = c - d

那么计算得到e = (a + b) - (a - b),这就是符号计算。

看起来似乎什么计算都没有发生,事实确实如此,但不仅如此。

符号计算是没有发生“计算”,但又发生了“计算”。

  • “没有发生计算“,指的是没有发生实质的数值计算,这里无论ab值是多少都无关紧要。
  • “但又发生计算”,指的是并非任何处理都没有做,因为切切实实e = (a + b) - (a - b)是计算出来的。

说到这里,应该不难理解,其实符号计算,就是“代数计算”。

Paradox主要功能就在于构建一个具有梯度计算功能的的符号计算系统。

系统实现

在Paradox中,所有符号计算的载体都是由Symbol(符号)和Operator(算子)构成。

Symbol共有3个衍生类,分别是Variable、Constant和Placeholder。

  • Variable,变量符号,它的作用是告诉计算引擎该符号的值是可变的,其值不能用于计算优化。 且在极值化时,被训练的参数Symbol只能是Variable类型。

  • Constant,常量符号,用于表达式或模型在计算过程中常量的Symbol,这类符号在计算时可能会被优化器优化掉。 因此一旦创建,就无法改变其实际值,也无法在计算引擎中绑定新值。

  • Placeholder,占位符号,它的作用是为实际数据在表达式或模型中占位。因为在表达式或模型构建时,承载数据的符号尚不知数据的具体值, 就需要靠占位符号来占位。占位符号只需要提供数据的维度大小(shape),而无需输入任何实际数据。Variable和Constant在创建时必须有明确的初始值。

符号计算代码实例

创建简单的1+1计算:

import paradox as pd

a = pd.Constant(1)
b = pd.Constant(1)

c = a + b

print(pd.Engine(c).value())

运行结果:

2.0

1+1计算结果为2.0而非2的原因是Paradox使用float为默认数据类型,任何类型的数据都会尝试转化为float。

需要注意的是,如果不使用计算引擎计算而直接print(c)的话,会得到c的代数表达式。

运行结果:

(1.0 + 1.0)

每一个Symbol在创建时还可以为其指定一个name,这个参数将用于直接打印表达式时有更直观的显示。

import paradox as pd

x = pd.Placeholder(name='x')
k = pd.Constant(1, name='k')
b = pd.Constant(1, name='b')

f = k * x + b

print(f)

运行结果:

((k * x) + b)

该例可以看出,x作为Placeholder是不需要有初始值的,'k'和'b'在创建时就必须有初始值。

如果需要带入x算出f的具体值,就需要在创建引擎后绑定(bind)x的值再进行计算。

e = pd.Engine(f)
e.bind = {x: 3}
print(e.value())

运行结果:

4.0