假设我有一个有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])我想知道,这两种方法在性能上有什么不同吗?西亚诺是否有足够的智慧来避免使用第二种方法重新计算梯度?说到智能,我的意思是计算w3_grad,Theano最好使用w_output_grad、w5_grad和w4_grad的预先计算的梯度,而不是再次计算它们。
发布于 2015-12-27 21:51:47
结果是,Theano没有用先前计算过的梯度来计算计算图的下层的梯度。这是一个有3个隐藏层和一个输出层的神经网络的虚拟例子。但是,这是,而不是,因为计算梯度是一种生命周期中的一次操作,除非您必须在每次迭代中计算梯度。Theano以计算图的形式返回导数的符号表达式,您可以从那时起将其作为函数使用。从那时起,我们只需使用Theano导出的函数来计算数值值,并使用这些值更新权重。
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使用了一种动态规划方法来计算有效方法的梯度。
https://stackoverflow.com/questions/34425161
复制相似问题