我使用 lasagne 构建了一个 LSTM 循环 NNet ,该NNet大致基于此博客文章中的架构。我的输入是一个包含大约 1,000,000 个句子和 2,000 个单词标记的词汇表的文本文件。通常,当我构建图像识别网络时,我的输入层将如下所示:
l_in = nn.layers.InputLayer((32, 3, 128, 128))
(其中尺寸是批量大小、通道、高度和宽度)这很方便,因为所有图像的大小都相同,所以我可以批量处理它们。由于我的 LSTM 网络中的每个实例都有不同的句子长度,我有一个如下所示的输入层:
l_in = nn.layers.InputLayer((None, None, 2000))
如上面引用的博客文章所述,
掩码:
因为并非每个小批量中的所有序列都始终具有相同的长度,所以千层面中的所有循环层都接受一个单独的掩码输入,其形状为 (batch_size, n_time_steps) ,其填充使得掩码 [i, j] = 1 当 j <= (序列 i 的长度) 和 mask[i, j] = 0 当 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 函数中全部发生?
谢谢。