【发布时间】:2016-02-04 20:51:21
【问题描述】:
我使用lasagne 构建了一个 LSTM 循环 NNet,它大致基于此 blog post 中的架构。我的输入是一个包含大约 1,000,000 个句子和 2,000 个单词标记的词汇表的文本文件。通常,当我构建图像识别网络时,我的输入层将如下所示:
l_in = nn.layers.InputLayer((32, 3, 128, 128))
(其中尺寸是批量大小、通道、高度和宽度)这很方便,因为所有图像的大小都相同,因此我可以批量处理它们。由于我的 LSTM 网络中的每个实例都有不同的句子长度,我有一个如下所示的输入层:
l_in = nn.layers.InputLayer((None, None, 2000))
如上面引用的博文所述,
口罩:
因为并非每个 minibatch 中的所有序列都将始终具有相同的长度,所以 千层面 接受具有形状的单独掩码输入 (batch_size, n_time_steps) ,其填充使得 掩码[i, j] = 1 什么时候 j (长度 序列 i) . 当没有提供掩码时,假设小批量中的所有序列都是有长度的 n_time_steps。
我的问题是:有没有办法在小批量不使用掩码的情况下处理这种类型的网络?
这是我的网络的简化版本。
# -*- coding: utf-8 -*-
import theano
import theano.tensor as T
import lasagne as nn
softmax = nn.nonlinearities.softmax
def build_model():
l_in = nn.layers.InputLayer((None, None, 2000))
lstm = nn.layers.LSTMLayer(l_in, 4096, grad_clipping=5)
rs = nn.layers.SliceLayer(lstm, 0, 0)
dense = nn.layers.DenseLayer(rs, num_units=2000, nonlinearity=softmax)
return l_in, dense
model = build_model()
l_in, l_out = model
all_params = nn.layers.get_all_params(l_out)
target_var = T.ivector("target_output")
output = nn.layers.get_output(l_out)
loss = T.nnet.categorical_crossentropy(output, target_var).sum()
updates = nn.updates.adagrad(loss, all_params, 0.005)
train = theano.function([l_in.input_var, target_var], cost, updates=updates)
从那里我有生成器会吐出(X, y) 对,我正在计算train(X, y) 并在每次迭代时更新梯度。我想做的是做 N 个训练步骤,然后用平均梯度更新参数。
为此,我尝试创建一个compute_gradient 函数:
gradient = theano.grad(loss, all_params)
compute_gradient = theano.function(
[l_in.input_var, target_var],
output=gradient
)
然后循环几个训练实例以创建一个“批次”并将梯度计算收集到一个列表中:
grads = []
for _ in xrange(1024):
X, y = train_gen.next() # generator for producing training data
grads.append(compute_gradient(X, y))
这会产生一个列表列表
>>> grads
[[<CudaNdarray at 0x7f83b5ff6d70>,
<CudaNdarray at 0x7f83b5ff69f0>,
<CudaNdarray at 0x7f83b5ff6270>,
<CudaNdarray at 0x7f83b5fc05f0>],
[<CudaNdarray at 0x7f83b5ff66f0>,
<CudaNdarray at 0x7f83b5ff6730>,
<CudaNdarray at 0x7f83b5ff6b70>,
<CudaNdarray at 0x7f83b5ff64f0>] ...
从这里我需要在每一层取梯度的平均值,然后更新模型参数。这可以像这样分块完成,梯度计算/参数更新是否需要在一个 theano 函数中全部发生?
谢谢。
【问题讨论】:
-
难道您不需要在编译时定义一个将 batch_size 梯度作为输入、取平均值并将更改应用于共享值参数的 theano 函数吗?
-
@user2255757 是的,这听起来像我所追求的。我只是不确定如何使用符号 CudaNdarray 实例列表来做到这一点。如果它们是其中包含实际值的 numpy 数组,我只需执行
map(np.mean, zip(*grads))然后更新参数,但它们不是,所以我不确定如何继续。 -
我更新了关于您更新问题的答案,希望对您有所帮助
标签: python theano gradient-descent lstm recurrent-neural-network