【问题标题】:How efficient/intelligent is Theano in computing gradients?Theano 在计算梯度方面的效率/智能程度如何?
【发布时间】:2016-03-29 06:25:29
【问题描述】:

假设我有一个具有 5 个隐藏层的人工神经网络。暂时忘记神经网络模型的细节,例如偏差、使用的激活函数、数据类型等等......。当然,激活函数是可微的。

通过符号微分,以下计算目标函数相对于层权重的梯度:

w1_grad = T.grad(lost, [w1])
w2_grad = T.grad(lost, [w2])
w3_grad = T.grad(lost, [w3])
w4_grad = T.grad(lost, [w4])
w5_grad = T.grad(lost, [w5])
w_output_grad = T.grad(lost, [w_output])

这样,要计算 w.r.t w1 的梯度,必须首先计算 w.r.t w2、w3、w4 和 w5 的梯度。与计算梯度 w.r.t w2 类似,必须首先计算 w.r.t w3、w4 和 w5 的梯度。

但是,我可以使用以下代码计算每个权重矩阵的梯度 w.r.t:

w1_grad, w2_grad, w3_grad, w4_grad, w5_grad, w_output_grad = T.grad(lost, [w1, w2, w3, w4, w5, w_output])

我想知道,这两种方法在性能方面有什么区别吗? Theano 是否足够智能,可以避免使用第二种方法重新计算梯度?智能是指计算 w3_grad,Theano 应该 [preferably] 使用预先计算好的 w_output_grad、w5_grad 和 w4_grad 梯度,而不是再次计算它们。

【问题讨论】:

  • 有趣的问题。您是否简单地尝试并测量了这两种方法的运行时间?
  • @hbaderts 还没有,我会做一些实验,把性能结果贴在这里。
  • @hbaderts 解决方案现已发布。
  • Amir,您一直在将新标签(jacobean、hessian)编辑成一堆旧问题,但我不相信标签是必要的 - 我认为它们是 "meta tags",因为它们真的无法自立。它们当然不够重要,不足以证明对有很多其他问题的旧帖子进行仅标记编辑是合理的。我建议你发表一个元帖子来讨论是否欢迎这些标签;如果有社区支持添加它们,则不需要一个人的努力。
  • @Amir 我们并不是说它们不应该在这里存在,只是说你开始讨论元数据,因为我们犹豫是否同意你的看法关于这些标签的元状态,就像它一样。如果您可以在那里提供令人信服的论点,以及提供准确使用指导的良好标签描述(目前没有),那么正如 Mogsdad 所说,其他人甚至可以帮助您将这些标签添加到适当的问题中。

标签: python-2.7 neural-network gradient theano automatic-differentiation


【解决方案1】:

事实证明,Theano 没有采用先前计算的梯度来计算计算图较低层中的梯度。这是一个具有 3 个隐藏层和一个输出层的神经网络的虚拟示例。但是,这不会有什么大不了的,因为计算梯度是一生一次的操作,除非您必须在每次迭代中计算梯度。 Theano 将导数的符号表达式作为computational graph 返回,从那时起,您可以简单地将其用作函数。从那时起,我们只需使用 Theano 派生的函数来计算 numerical 值并使用这些值更新权重。

import theano.tensor as T
import time
import numpy as np
class neuralNet(object):
    def __init__(self, examples, num_features, num_classes):
        self.w = shared(np.random.random((16384, 5000)).astype(T.config.floatX), borrow = True, name = 'w')
        self.w2 = shared(np.random.random((5000, 3000)).astype(T.config.floatX), borrow = True, name = 'w2')
        self.w3 = shared(np.random.random((3000, 512)).astype(T.config.floatX), borrow = True, name = 'w3')
        self.w4 = shared(np.random.random((512, 40)).astype(T.config.floatX), borrow = True, name = 'w4')
        self.b = shared(np.ones(5000, dtype=T.config.floatX), borrow = True, name = 'b')
        self.b2 = shared(np.ones(3000, dtype=T.config.floatX), borrow = True, name = 'b2')
        self.b3 = shared(np.ones(512, dtype=T.config.floatX), borrow = True, name = 'b3')
        self.b4 = shared(np.ones(40, dtype=T.config.floatX), borrow = True, name = 'b4')
        self.x = examples

        L1 = T.nnet.sigmoid(T.dot(self.x, self.w) + self.b)
        L2 = T.nnet.sigmoid(T.dot(L1, self.w2) + self.b2)
        L3 = T.nnet.sigmoid(T.dot(L2, self.w3) + self.b3)
        L4 = T.dot(L3, self.w4) + self.b4
        self.forwardProp = T.nnet.softmax(L4)
        self.predict = T.argmax(self.forwardProp, axis = 1)

    def loss(self, y):
        return -T.mean(T.log(self.forwardProp)[T.arange(y.shape[0]), y])

x = T.matrix('x')
y = T.ivector('y')

nnet = neuralNet(x)
loss = nnet.loss(y)

diffrentiationTime = []
for i in range(100):
    t1 = time.time()
    gw, gw2, gw3, gw4, gb, gb2, gb3, gb4 = T.grad(loss, [nnet.w, nnet.w2, logReg.w3, nnet.w4, nnet.b, nnet.b2, nnet.b3, nnet.b4])
    diffrentiationTime.append(time.time() - t1)
print 'Efficient Method: Took %f seconds with std %f' % (np.mean(diffrentiationTime), np.std(diffrentiationTime))

diffrentiationTime = []
for i in range(100):
    t1 = time.time()
    gw = T.grad(loss, [nnet.w])
    gw2 = T.grad(loss, [nnet.w2])
    gw3 = T.grad(loss, [nnet.w3])
    gw4 = T.grad(loss, [nnet.w4])
    gb = T.grad(loss, [nnet.b])
    gb2 = T.grad(loss, [nnet.b2])
    gb3 = T.grad(loss, [nnet.b3])
    gb4 = T.grad(loss, [nnet.b4])
    diffrentiationTime.append(time.time() - t1)
print 'Inefficient Method: Took %f seconds with std %f' % (np.mean(diffrentiationTime), np.std(diffrentiationTime))

这将打印出以下内容:

Efficient Method: Took 0.061056 seconds with std 0.013217
Inefficient Method: Took 0.305081 seconds with std 0.026024

这表明 Theano 使用动态规划方法来计算梯度以实现高效方法。

【讨论】:

    猜你喜欢
    • 2015-09-16
    • 2016-04-01
    • 2017-03-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多