Theano函数中的索引技巧

1 投票
1 回答
576 浏览
提问于 2025-04-18 16:16

我正在使用Theano来实现一个神经网络的n-gram语言模型,参考了Bengio等人2003年的论文。这个模型使用了分布式的单词表示,而我在写一个符号表达式时遇到了麻烦,这个表达式可以让我计算单词表示向量的梯度。

根据论文中的符号,我有一个大小为C的单词表示矩阵,尺寸为V x m,其中V是词汇表的大小,m是单词嵌入的维度。C的每一行都是一个单词的向量表示。

我的训练数据是从一个语料库中提取的n-grams。假设我设定n = 3。那么我想估计P(wt|wt-1, wt-2)。一个神经网络通过使用wt-1wt-2的嵌入向量的拼接来预测wt的概率,使用的是一个非线性函数。(具体细节请参见论文。)每个单词通过一个索引来表示,这个索引也指向C中对应的表示行。如果这些索引是i1i2i3,我想为此写一个Theano表达式。

f(i_3, C[i_1].C[i_2])

其中f包含一个隐藏层和一个非线性函数,而C[i_1].C[i_2]是数组C[i_1]C[i_2]的拼接。我首先需要为C[i_1].C[i_2]写一个符号的Theano表达式。此外,这个函数不仅需要处理单个训练实例,还需要处理多个训练实例的迷你批次。

如果我直接使用numpy矩阵而不是抽象的Theano表达式,我知道怎么做。例如,如果C是共享的,而X是一个N x n - 1的迷你批次,包含N个单词索引的训练向量,我可以这样查找拼接的向量:

C.get_value()[X].reshape(X.shape[0], -1)

(这是我在StackOverflow上学到的一点索引技巧。)

然而,当我尝试将这个表达式编译成Theano函数时,我遇到了错误。

X_var = T.lmatrix('X_var')
function([X_var], C[X_var].reshape(X_var.shape[0], -1))

前面的代码给了我这个错误

Exception: ('The following error happened while compiling the node'
, Reshape{-1 (AdvancedSubtensor1.0, InplaceDimShuffle{x}.0), 
'\n', "Compilation failed (return status=1): 
/Users/williammcneill/.theano/compiledir_Darwin-13.3.0-x86_64-i386-64bit-i386-2.7.6-64/tmpOlUO0n/mod.cpp:300:31: error: 
'new_dims' declared as an array with a negative size.
             npy_intp new_dims[-1];.
                               ^~. 1 error generated.. ", '[Reshape{-1}(<TensorType(float64, matrix)>, <TensorType(int64, (True,))>)]')

我认为这意味着将-1作为最后一个重塑参数的索引技巧不被Theano编译器支持。

等效的命令给出了不同的错误。

function([X_var], C[X_var].reshape(X_var.shape[0], X_var.shape[1]*X_var.shape[2]))

ValueError: Expected ndim to be an integer, is <class 'theano.tensor.var.TensorVariable'>

我需要为f写出符号表达式,以便我可以计算它相对于C的梯度。有人能帮我做到这一点吗?

另外,有人能给我指个方向,找一些可以处理单词嵌入的Theano代码示例吗?我找到的所有教程材料都是关于如何在图像数据上写神经网络的,但我还没看到如何做分布式表示的例子。

1 个回答

3

好吧,我真是个傻瓜。算是吧。我在我的 reshape 参数周围漏了一个额外的括号。下面这个就能正常工作了。

function([X_var], C[X_var].reshape((X_var.shape[0], -1)))

不过这有点让人困惑,因为一个 arrayreshape 方法可以接受两种参数:一种是我上面写的那样的两个参数,另一种是像我在答案中写的那样的元组,但 Theano 只会编译后者。

撰写回答