Theano - 简单训练示例
Theano 在训练神经网络时非常有用,因为我们必须反复计算成本和梯度才能达到最优。在大型数据集上,这会变得计算密集。Theano 可以有效地完成这一点,因为它对我们之前看到的计算图进行了内部优化。
问题陈述
我们现在将学习如何使用 Theano 库来训练网络。我们将举一个简单的例子,从四个特征的数据集开始。在对每个特征应用一定的权重(重要性)后,我们计算这些特征的总和。
训练的目标是修改分配给每个特征的权重,使总和达到目标值 100。
sum = f1 * w1 + f2 * w2 + f3 * w3 + f4 * w4
其中 f1、f2、... 是特征值,w1、w2、... 是权重。
让我量化这个例子,以便更好地理解问题陈述。我们将为每个特征假设一个初始值 1.0,并且我们将取 w1 等于 0.1、w2 等于 0.25、w3 等于 0.15 和 w4 等于 0.3。在分配权重值时没有明确的逻辑,这只是我们的直觉。因此,初始总和如下 −
sum = 1.0 * 0.1 + 1.0 * 0.25 + 1.0 * 0.15 + 1.0 * 0.3
总计为 0.8。现在,我们将继续修改权重分配,以使该总和接近 100。当前的结果值 0.8 与我们期望的目标值 100 相差甚远。在机器学习术语中,我们将 cost 定义为目标值减去当前输出值之间的差值,通常取平方以消除误差。我们通过计算梯度和更新权重向量来降低每次迭代的成本。
让我们看看整个逻辑是如何在 Theano 中实现的。
声明变量
我们首先声明我们的输入向量 x,如下所示 −
x = tensor.fvector('x')
其中 x 是浮点值的一维数组。
我们定义一个标量 target 变量,如下所示 −
target = tensor.fscalar('target')
接下来,我们创建一个权重张量 W,其初始值如上所述 −
W = theano.shared(numpy.asarray([0.1, 0.25, 0.15, 0.3]), 'W')
定义 Theano 表达式
我们现在使用以下表达式 − 计算输出
y = (x * W).sum()
请注意,在上面的语句中 x 和 W 是向量,而不是简单的标量变量。我们现在使用以下表达式 − 计算误差(成本)
cost = tensor.sqr(target - y)
成本是目标值与当前输出之间的差值的平方。
为了计算梯度以告诉我们距离目标有多远,我们使用内置的 grad 方法,如下所示 −
gradients = tensor.grad(cost, [W])
我们现在通过采用 0.1 的学习率来更新 权重 向量,如下所示 −
W_updated = W - (0.1 * gradients[0])
接下来,我们需要使用上述值更新我们的权重向量。我们在以下语句中执行此操作 −
updates = [(W, W_updated)]
定义/调用 Theano 函数
最后,我们在 Theano 中定义一个 函数 来计算总和。
f = function([x, target], y, updates=updates)
要调用上述函数一定次数,我们创建一个 for 循环,如下所示 −
for i in range(10): output = f([1.0, 1.0, 1.0, 1.0], 100.0)
如前所述,函数的输入是一个包含四个特征的初始值的向量 - 我们为每个特征分配 1.0 的值,无需任何特定原因。您可以分配不同的值,并检查函数是否最终收敛。我们将打印每次迭代中的权重向量值和相应的输出。它显示在下面的代码中 −
print ("iteration: ", i) print ("Modified Weights: ", W.get_value()) print ("Output: ", output)
完整程序列表
完整的程序列表在此处重现,供您快速参考 −
from theano import * import numpy x = tensor.fvector('x') target = tensor.fscalar('target') W = theano.shared(numpy.asarray([0.1, 0.25, 0.15, 0.3]), 'W') print ("Weights: ", W.get_value()) y = (x * W).sum() cost = tensor.sqr(target - y) gradients = tensor.grad(cost, [W]) W_updated = W - (0.1 * gradients[0]) updates = [(W, W_updated)] f = function([x, target], y, updates=updates) for i in range(10): output = f([1.0, 1.0, 1.0, 1.0], 100.0) print ("iteration: ", i) print ("Modified Weights: ", W.get_value()) print ("Output: ", output)
运行程序时你会看到以下输出 −
Weights: [0.1 0.25 0.15 0.3 ] iteration: 0 Modified Weights: [19.94 20.09 19.99 20.14] Output: 0.8 iteration: 1 Modified Weights: [23.908 24.058 23.958 24.108] Output: 80.16000000000001 iteration: 2 Modified Weights: [24.7016 24.8516 24.7516 24.9016] Output: 96.03200000000001 iteration: 3 Modified Weights: [24.86032 25.01032 24.91032 25.06032] Output: 99.2064 iteration: 4 Modified Weights: [24.892064 25.042064 24.942064 25.092064] Output: 99.84128 iteration: 5 Modified Weights: [24.8984128 25.0484128 24.9484128 25.0984128] Output: 99.968256 iteration: 6 Modified Weights: [24.89968256 25.04968256 24.94968256 25.09968256] Output: 99.9936512 iteration: 7 Modified Weights: [24.89993651 25.04993651 24.94993651 25.09993651] Output: 99.99873024 iteration: 8 Modified Weights: [24.8999873 25.0499873 24.9499873 25.0999873] Output: 99.99974604799999 iteration: 9 Modified Weights: [24.89999746 25.04999746 24.94999746 25.09999746] Output: 99.99994920960002
观察四次迭代后的输出结果为 99.96,五次迭代后的输出结果为 99.99,接近我们期望的 100.0 目标。
根据期望的准确度,您可以放心地得出结论,网络经过 4 到 5 次迭代即可完成训练。训练完成后,查找权重向量,该向量在 5 次迭代后取以下值 −
iteration: 5 Modified Weights: [24.8984128 25.0484128 24.9484128 25.0984128]
您现在可以在网络中使用这些值来部署模型。