Theano - 简单的训练示例


Theano 在训练神经网络时非常有用,我们必须重复计算成本和梯度才能达到最佳值。在大型数据集上,这会变得计算密集型。Theano 之所以能高效地做到这一点,是因为它对我们之前看到的计算图进行了内部优化。

问题陈述

我们现在将学习如何使用 Theano 库来训练网络。我们将采用一个简单的案例,从四个特征数据集开始。在对每个特征应用一定的权重(重要性)后,我们计算这些特征的总和。

训练的目标是修改分配给每个特征的权重,使总和达到目标值 100。

sum = f1 * w1 + f2 * w2 + f3 * w3 + f4 * w4

其中f1 , f2 , ... 是特征值,w1 , w2 , ... 是权重。

让我量化这个例子,以便更好地理解问题陈述。我们假设每个特征的初始值为 1.0 ,并且 w1 等于0.1w2等于0.25w3等于0.15w4等于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 很远。在机器学习术语中,我们将成本定义为目标值减去当前输出值,通常平方以放大误差。我们通过计算梯度和更新权重向量来降低每次迭代的成本。

让我们看看整个逻辑是如何在 Theano 中实现的。

声明变量

我们首先声明输入向量 x 如下 -

x = tensor.fvector('x')

其中x是浮点值的一维数组。

我们定义一个标量目标变量,如下所示 -

target = tensor.fscalar('target')

接下来,我们使用上面讨论的初始值创建一个权重张量W -

W = theano.shared(numpy.asarray([0.1, 0.25, 0.15, 0.3]), 'W')

定义 Theano 表达式

我们现在使用以下表达式计算输出 -

y = (x * W).sum()

请注意,在上面的语句中,xW是向量而不是简单的标量变量。我们现在用以下表达式计算误差(成本) -

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]

您现在可以在网络中使用这些值来部署模型。