torch/nn - Tensors张量的逐元素拼接

这个问题的主题是使用torch/nn和torch/nngraph Lua库来为神经网络拼接张量。我几周前才开始使用Lua编程,所以我的经验非常有限。在下面的文本中,我将lua表称为数组。

背景

我正在为语音识别构建一个递归神经网络。 在网络中的某个时刻,有N个大小为m的张量数组。

a = {a1, a2, ..., aM},
b = {b1, b2, ..., bM},
... N次

其中aibi是张量,{}表示一个数组。

需要做的是逐元素拼接所有这些数组,以便output是一个由M个张量组成的数组,其中output [i]是第二个维度上从N个数组的每个第i个张量拼接的结果。

output = {z1, z2, ..., zM}

示例

||表示张量

x = {|1 1|, |2 2|}
     |1 1|  |2 2|
     2x2大小的张量

y = {|3 3 3|, |4 4 4|}
     |3 3 3|  |4 4 4|
     2x3大小的张量
        |
        | Join{x,y}
        \/
z = {|1 1 3 3 3|, |2 2 4 4 4|}
     |1 1 3 3 3|  |2 2 4 4 4|
     2x5大小的张量

因此,第一个大小为2x2的x张量与第一个大小为2x3的y张量在第二维上拼接,每个数组的第二个张量也是如此,从而导致z是一个张量数组大小为2x5。

问题

现在这是一个基本的拼接,但是我似乎找不到一个可以让我这么做的torch/nn库中的模块。当然我可以编写自己的模块,但是如果已经存在的模块可以做到这一点,那么我宁愿选择那种方式。

我所知道的唯一现有模块是JoinTable,它接受大小相同的张量数组并将它们拼接在一起。但我想逐元素拼接张量数组。

另外,当我们将输入馈送到我们的网络时,N个数组中的张量数量会发生变化,因此上下文中的m不是常数。

想法

为了使用JoinTable模块,我想我可以将我的数组转换为张量,然后在转换的N张量上进行JoinTable。但是再次,我需要一个执行这种转换的模块,以及另一个将其转换回一个数组的模块,以便将其馈送到网络的下一层。

最后的手段

编写一个新模块,迭代所有给定的数组并按元素拼接。当然可行,但是这篇文章的整个目的是找到一种避免编写不好模块的方法。我觉得这样的模块不存在很奇怪。


结论

最后我决定按照我在最后的手段中写的那样做。我编写了一个新模块,迭代所有给定的数组并按元素拼接。

尽管如此,@fmguler给出的答案也可以在不编写新模块的情况下完成相同的工作。

点赞
用户213123
用户213123

你可以使用 nn.SelectTablenn.JoinTable 来完成像下面这样的操作:

require 'nn'

x = {torch.Tensor{{1,1},{1,1}}, torch.Tensor{{2,2},{2,2}}}
y = {torch.Tensor{{3,3,3},{3,3,3}}, torch.Tensor{{4,4,4},{4,4,4}}}

res = {}
res[1] = nn.JoinTable(2):forward({nn.SelectTable(1):forward(x),nn.SelectTable(1):forward(y)})
res[2] = nn.JoinTable(2):forward({nn.SelectTable(2):forward(x),nn.SelectTable(2):forward(y)})

print(res[1])
print(res[2])

如果你希望将其包装成一个模块,可以使用 nnGraph 来实现:

require 'nngraph'

x = {torch.Tensor{{1,1},{1,1}}, torch.Tensor{{2,2},{2,2}}}
y = {torch.Tensor{{3,3,3},{3,3,3}}, torch.Tensor{{4,4,4},{4,4,4}}}

xi = nn.Identity()()
yi = nn.Identity()()
res = {}
--you can loop over columns here>>
res[1] = nn.JoinTable(2)({nn.SelectTable(1)(xi),nn.SelectTable(1)(yi)})
res[2] = nn.JoinTable(2)({nn.SelectTable(2)(xi),nn.SelectTable(2)(yi)})
module = nn.gModule({xi,yi},res)

--test like this
result = module:forward({x,y})
print(result)
print(result[1])
print(result[2])

--gives the result
th> print(result)
{
  1 : DoubleTensor - size: 2x5
  2 : DoubleTensor - size: 2x5
}

th> print(result[1])
 1  1  3  3  3
 1  1  3  3  3
[torch.DoubleTensor of size 2x5]

th> print(result[2])
 2  2  4  4  4
 2  2  4  4  4
[torch.DoubleTensor of size 2x5]

其中,nn.Identity 可以看作是一个函数,nn.JoinTablenn.SelectTable 是层级存储的模块。内层的 nn.SelectTable 可以依次选择输入的 Tensor 中的第 $1$ 到 $d$ 列(即第一行坐标)。外层的 nn.JoinTable 可以按列或者按行将输入合并起来,从而生成一个新的 Tensor

使用 nnGraph 可以将 “张量到张量” 的映射表示成图中的结点,非线性层向前传播的过程可通过对图中对应映射的结点进行计算实现。这种高度抽象的表达方式非常方便且直观。

2016-08-27 20:13:26