Theano Python教程
Theano是Python的数值计算库。
这是实现神经网络模型的常见选择,因为它使您可以有效地定义,优化和评估数学表达式,包括多维数组((numpy.ndaray))。
Theano Python
Theano使获得高速成为可能,从而在涉及大量数据的问题上与手工C实现进行了激烈的竞争。
它可以利用最新的GPU,在某些情况下,它在CPU上的性能要比C高出好几个数量级。
Theano有一个了不起的编译器,它可以进行各种复杂度不同的优化。
一些这样的优化是:
- 算术简化(例如:
--x-> x; x + y-x-> y
) - 使用内存别名以避免计算
- 不断折叠
- 合并相似的子图,以避免重复计算
- 循环融合用于元素子表达式
- GPU计算
您可以在此处查看优化的完整列表。
为什么选择Theano Python库?
通常,我们使用numpy软件包来处理矩阵,那么什么使Theano优于任何此类软件包!
Theano是numpy和sympy之间的一种混合体,它试图将两者组合成一个功能强大的库。
让我们来看看它相对于其他的一些优势:
- 稳定性优化:Theano可以找出一些不稳定的表达式,并可以使用更稳定的方式对其进行评估
- 执行速度优化:如前所述,theano可以利用最新的GPU并在您的CPU或者GPU中执行部分表达式,从而使其比Python快得多
- 符号区分:Theano足够聪明,可以自动创建符号图以计算梯度
好了,从理论上讲,让我们开始研究示例部分。
Theano教程
要开始使用Theano,请使用PIP进行安装,如下图所示。
Theano表达式到可调用对象中
使用Theano,我们可以将表达式转换为可调用对象。
让我们看一下代码片段:
import theano from theano import tensor x = tensor.dscalar() y = tensor.dscalar() z = x + y f = theano.function([x,y], z) print(f(1.5, 2.5))
运行此命令时,将得到以下输出:现在,让我们尝试了解上述程序中发生的情况:
- 我们首先声明两个符号浮点标量或者变量
- 然后,我们创建了一个简单的表达式,将两个数字相加
- 在表达式之后,我们将表达式转换为可调用对象,该对象以(x,y)作为输入,并在计算后返回z的值
- 最后,我们使用一些参数调用该函数并打印结果
物流功能
让我们看一个更复杂的示例,而不只是将两个数字相加。
让我们尝试计算logistic曲线,它由下式给出:如果为该方程式绘制图形,将看起来像:Logistic函数应用于矩阵的每个元素。
让我们写一个代码片段来演示这一点:
import theano from theano import tensor # declare a variable x = tensor.dmatrix('x') # create the expression s = 1/(1 + tensor.exp(-x)) # convert the expression into a callable object which takes # a matrix as parameter and returns s(x) logistic = theano.function([x], s) # call the function with a test matrix and print the result print(logistic([[0, 1], [-1, -2]]))
运行脚本时,我们可以看到输出:一切正常,输出看起来与预期的相同。
现在,让我们仔细看看这些功能。
仔细看看Theano函数
Theano函数有助于与符号图进行交互。
它们允许theano构建计算图并对其进行优化。
典型的theano函数如下所示:
f= theano.function([x],y)
x是输入变量的列表,y是输出变量的列表。
我们来看看此功能的用处。
一次计算多个结果
假设我们必须计算两个矩阵" x"和" y"之间的元素差,绝对差和平方差。
同时执行此操作可以极大地优化程序,因为我们不必为每个操作而一次又一次地转到每个元素。
import theano from theano import tensor # declare variables x, y = tensor.dmatrices('x', 'y') # create simple expression for each operation diff = x - y abs_diff = abs(diff) diff_squared = diff**2 # convert the expression into callable object f = theano.function([x, y], [diff, abs_diff, diff_squared]) # call the function and store the result in a variable result= f([[1, 1], [1, 1]], [[0, 1], [2, 3]]) # format print for readability print('Difference: ') print(result[0]) print('Absolute Difference: ') print(result[1]) print('Squared Difference: ') print(result[2])
运行此程序时,我们可以看到输出为多个打印结果:
使用Theano渐变功能
让我们尝试一些更有用和更复杂的功能,以逐步简化培训示例。
其中我们将尝试找出表达式相对于参数的导数
我们将计算上面定义的逻辑函数的梯度,可以将其绘制为:让我们通过一个示例演示Gradient的工作方式:
import numpy import theano from theano import tensor from theano import pp # declare variable x = tensor.dmatrix('x') #create a simple expression for logistic function s = tensor.sum(1/(1 + tensor.exp(-x))) # create expression to compute gradient of s with respect to x gs = tensor.grad(s, x) # create callable object dlogistic = theano.function([x], gs) # call the function and print the results print(dlogistic([[0, 1], [-1, -2]]))
当我们运行该程序时,我们可以看到输出为:这样,即使对于具有许多输入的函数,Theano也可用于进行有效的符号微分(因为tensor.grad返回的表达式将在编译过程中进行优化)。
让我们将它们放到一个简单的培训示例中,以更好地了解theano!
最少培训Theano示例
让我们尝试使用theano训练一些东西。
我们将使用梯度下降来训练W中的权重,以便从模型中获得比现有(0.9)更好的结果:
import theano import numpy # declare variables x = theano.tensor.fvector('x') target = theano.tensor.fscalar('target') W = theano.shared(numpy.asarray([0.2, 0.7]), 'W') # create expressions y = (x * W).sum() cost = theano.tensor.sqr(target - y) gradients = theano.tensor.grad(cost, [W]) W_updated = W - (0.1 * gradients[0]) updates = [(W, W_updated)] # create a callable object from expression f = theano.function([x, target], y, updates=updates) # call the function and print results for i in range(10): result = f([1.0, 1.0], 20.0) print(result)
运行此程序时,我们可以看到以下输出:第二个输入变量" target"将用作我们用于训练的目标值:
target = theano.tensor.fscalar('target')
我们需要一个成本函数来训练模型,通常是与目标值的平方距离
cost = theano.tensor.sqr(target - y)
接下来,我们需要为要相对于成本函数更新的参数计算局部梯度。
正如我们在较早的示例中看到的那样,Theano将为我们做到这一点。
我们只需使用必需的参数调用grad函数即可:
gradients = theano.tensor.grad(cost, [W])
现在,为参数的更新版本定义一个变量。
众所周知,在梯度下降中,更新值等于学习率乘以从现有值中减去的梯度。
假设学习率α= 0.1:
W_updated = W - (0.1 * gradients[0])
接下来,我们必须再次定义Theano函数,进行一些更改:
f = theano.function([x, target], y, updates=updates)
调用该函数时,它将获取x和target的值,并返回y的值作为输出,然后Theano执行更新列表中的所有更新。
现在我们反复调用该函数以进行训练,在此示例中要重复10次以具体说明。
通常,训练数据包含不同的值,但出于本示例的目的,我们每次使用相同的值x = [1.0,1.0]和target = 20来检查事情是否正常运行。
在上面的输出中,请注意目标值在每个步骤中如何接近20(目标值)。