一、Theano 的介绍
Theano 是一个开源的数学库,可以让有效的定义、优化和求值数学表达式。
Theano 可以在 CPU 和 GPU 上高效地进行数值计算。其背后的功能主要有:
- 有效地处理多维数组,以实现进行矩阵运算的高效性
- 自动计算微分
- 高度优化的编译器,使得运行速度较快且能提高执行效率
二、使用 Theano 构建数学表达式
Theano 的强大功能在于能够极大地简化代码,并可以高可读性地定义复杂的函数,例如下面的例子:
import theano.tensor as T
from theano import function
x = T.scalar('x')
y = T.scalar('y')
z = x + y
f = function([x, y], z)
assert 3.0 == f(1.5, 1.5)
assert 0.0 == f(-1.5, 1.5)
这段代码运行后,会将 x 和 y 定义为 Theano 的符号变量(Symbolic Variable),而不是 Python 变量。我们可以通过这些符号变量,来定义数学表达式 z,具体地,z 表示 x 和 y 的和。
之后我们使用 Theano 的函数构建函数 f,并传入 x 和 y 的初始值。这样我们就能够成功地使用 Theano 进行计算,将其应用在各个领域。
三、Theano 的运算速度
Theano 不仅仅是优秀的符号计算库,同时也是一个实现了编译、内存提升和操作优化的框架。在许多应用中,Theano 能够比原生的 Python 库进行更好的优化,这主要体现在以下方面:
-
快速的矩阵和向量操作:
import theano import numpy as np import theano.tensor as T from theano import pp, function # 双精度矩阵,大小为 1000 x 10000 X = T.dmatrix('X') # 向量,大小为 10000 y = T.dvector('y') # 数乘 z = X.dot(y) # 函数输出 f = function([X, y], z) x = np.random.rand(1000, 10000) a = np.random.rand(10000) # 执行前预热 f(x, a) %timeit f(x, a)
上面代码用 Theano 实现了 矩阵与向量乘法 ,并将其使用函数封装。需要注意的是,这个过程中,X,y 和 z 都是 Theano 的符号表达式。
运行到最后一行代码时,会输出运行时间。经过测试,这个例子用原本的 numpy 库算出来结果需要 10s ,而用 Theano 则只需要 不到 5 ms ,其速度十分之快。
-
自动求导和高级优化:
import theano import numpy as np import theano.tensor as T from theano import function # 训练数据,1000 组数据,每组 50 个属性 train_X = np.random.randint(1, 1000, size=(1000, 50)) train_y = np.random.randint(0, 2, size=(1000, 1)) # 对结果进行分类,二分类问题需要将结果由 0, 1 确定下来 # 权重向量和偏置 w = theano.shared(np.random.randn(50).astype(theano.config.floatX), name='w') b = theano.shared(np.random.randn().astype(theano.config.floatX), name='b') # 输入和输出的类型均为 MatrixType,代表训练数据的输入和输出是矩阵 X = T.matrix('X') y = T.matrix('y') # 计算 sigmoid 函数 p_1 = 1 / ( 1 + T.exp(-T.dot(X, w) - b) ) prediction = p_1 > 0.5 # 误差函数的输出 xent = -y * T.log(p_1) - (1-y) * T.log(1-p_1) cost = xent.mean() + 0.01 * (w ** 2).sum() gw, gb = T.grad(cost, [w, b]) # 定义训练函数 learning_rate = 0.1 train = function(inputs=[X,y], outputs=[prediction, xent.mean()], updates=((w, w - learning_rate * gw), (b, b - learning_rate * gb))) # 修改更新速率 for i in range(500): pred, err = train(train_X, train_y) print(w.get_value()) print(b.get_value())
这段代码是一个在线性模型中使用 Theano 的示例,利用这个模型,能够让我们有效地地利用训练数据,计算出这个函数的误差函数,并计算梯度。
此处采用了一个用于分类任务的 sigmoid 函数,作为这个函数的模型回归部分。若使用原生的 Python 实现,生成的代码会比较长。但自己使用 Theano 就会自动计算梯度,并生成对应的优化算法。这个例子通过简单的几行代码实现了整个过程,不仅时间效率提升了,代码也更加简化。
四、Theano 的限制
然而,Theano 并不是万能的解决方案,在不同的场景下,Theano 善长的领域将会不同。下面列出了 Theano 无法或不能高效应对的场景。
- 复杂的控制结构:
由于 Theano 的符号运算特性,Theano 通常不能将条件式和循环的语句优化为连续的操作。因此,当数据结构过于复杂,代码中包含大量的控制语句时,很难达到最优的 性能。
- 时序的手写模型 或 需要并行化处理的算法 :
类似于深度学习领域的模型,神经网络、循环神经网络等均需要处理时序信号,这需要大量的分支调整。Theano 也可以在这类模型上支持训练,不过在循环中很难进行并行化处理,最终导致性能瓶颈。
- 需要跨尺寸和数据类型进行计算的应用程序:
Theano 是为多维数据和矩阵运算优化的。虽然它可以很好地对 32 位浮点型数据进行处理,但由于硬件之间的数据类型转换需要耗费时间和内存,因此处理和管理不同尺寸和数据类型数据的任务使用其他工具通常会快得多。
五、总结
Theano 作为一个优秀的符号计算库,它可以方便地 生产、optimizes和evaluates数学表达式,特别擅长一个是在矩阵和向量计算上显得极为醒目。同时,作为自动微分的一个库,Theano 能够在大型数据集上实现矩阵和向量运算的自动计算梯度以减少反向传播算法的复杂度。在许多应用程序中,Theano 根据自身特性和使用场景,相对于 CPU 和 GPU ,Theano 的代码能够更快地驱动可产生巨大影响的操作,这意味着可以让数据科学家训练并优化模型、借助纹理映射、平行处理、并加快矩阵的执行效率。
原创文章,作者:EUWNA,如若转载,请注明出处:https://www.506064.com/n/368567.html