在 Theano 中创建符号变量的目的是什么?

Mat*_*ien 1 python theano

在 Theano 中,变量被写成“符号”:

x = T.matrix("x")
y = T.vector("y")
Run Code Online (Sandbox Code Playgroud)

从阅读文档中可以看出,我们创建这些符号的原因可能是因为这些变量被编译成 C 代码。但我不确定是否是这种情况,更不用说使用符号变量的唯一原因了。

在 Theano 中创建符号变量的目的是什么?他们能做什么,而 Python 中的现成分配不能做?

Dan*_*haw 5

Theano 网站打开为

Theano 是一个 Python 库,允许您有效地定义、优化和评估涉及多维数组的数学表达式。

这似乎是对它做什么的一个很好的总结,但也许不是它为什么这样做。

Theano 的主要特征之一是其符号微分特征。也就是说,给定一个符号数学表达式,Theano 可以自动对表达式中的某个变量进行微分,即它可以自动确定表达式沿某些感兴趣维度的梯度。

例如,如果y=x**2(其中**是电力操作者),然后的梯度y相对于x是dy/dx = 2*x。Theano 可以自动执行此操作:

import theano
import theano.tensor
x = theano.tensor.scalar('x')
y = x ** 2
theano.printing.pp(y)
dy_dx = theano.grad(y, x)
theano.printing.pp(dy_dx)
Run Code Online (Sandbox Code Playgroud)

如果您运行此代码,您将看到输出

(x ** TensorConstant{2})
((fill((x ** TensorConstant{2}), TensorConstant{1.0}) * TensorConstant{2}) * (x ** (TensorConstant{2} - TensorConstant{1})))
Run Code Online (Sandbox Code Playgroud)

该fill操作只是创建一个正确形状的张量(在本例中为标量),其中填充有 1 并且TensorConstant{a}只是数字,a因此可以简化为

(x ** 2) == x ** 2
((1 * 2) * (x ** (2 - 1))) == (2 * (x ** 1)) == 2 * x
Run Code Online (Sandbox Code Playgroud)

正如预期的那样。

显然,这对于这样一个简单的数学表达式并不是特别有用,但是现在想象一下您正在构建一个任意大且复杂的数学表达式,其梯度不是那么明显,就像神经网络研究中的情况一样。

但还有更多。Theano 可以对不仅涉及标量而且涉及向量、矩阵或任何其他张量的运算的表达式执行上述操作。

除了符号微分之外,Theano 的符号方法还提供了其他显着的好处:

  • Theano 可以将符号数学表达式编译成可执行代码。它使用各种技术来生成比普通 Python 代码运行得更快的可执行代码。
  • Theano 程序通常可以在 CPU 和 GPU 上运行之间切换,无需任何代码更改。
  • 在 CPU 上运行时,Theano 充分利用 numpy BLAS 和 OpenMP 工具(如果可用)来并行执行多个 CPU 内核。
  • 在 GPU 上运行时,Theano 充分利用现代 GPU 上的许多内核来并行化最昂贵的操作(最显着的是矩阵乘法)。
  • Theano 的编译器是一个优化编译器,因为它可以使用保持表达式语义的各种变换来更改表达式(也称为计算图)(在给定相同输入的情况下,它仍然计算相同的结果),但实现不同的性能,而且至关重要的是,数值稳定性增益。

纯 Python 不提供上述任何功能,单独使用 numpy 仅提供一些并行化功能(通过 BLAS 和 OpenMP)。

Theano 文档中有关此主题的更多信息。

PS 这是对问题的@eickenberg 简短评论的扩展。