我正在尝试从Tensorflow中的this paper实现轻量级卷积模块。根据第3页“实施”部分的作者,他们转换了大小为HxK
的卷积滤波器,其中H
是磁头数(例如16),而K
是磁头数核(例如3)成形状为B*HxTxT
的带矩阵,其中B
是批大小(例如64),T
是序列长度(例如10)。通过带矩阵,它们意味着内核外部的条目将为零。
根据轻量级卷积模块的Pytorch(Fairseq)中的official implementation,其实现方式是通过创建大小为(B*H)xTx(T+K-1)
的零张量,然后使用as_stride
函数,在最后一个维度(B*H)xTxK
上以滑动窗口的方式将内核余量(在平铺,重新定型并将其转置为大小(T+K-1)
之前)复制到零张量中。举个例子:
B = 64
T = 10
K = 3
H = 16
kernel = torch.ones(B*H, T, K) # torch.Size([1024, 10, 3])
kernel_expanded = kernel.new_zeros(B*H, T, T+K-1, requires_grad=False) # torch.Size([1024, 10, 12])
kernel_expanded.as_strided((B*H, T, K), (T*(T+K-1), T+K, 1)).copy_(kernel) # torch.Size([1024, 10, 12])
'''
Results before as_strided:
kernel_expanded[0,0,:] = [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]
kernel_expanded[0,1,:] = [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]
kernel_expanded[0,2,:] = [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]
...
kernel_expanded[0,9,:] = [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]
kernel_expanded[1,0,:] = [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]
kernel_expanded[1,1,:] = [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]
kernel_expanded[1,2,:] = [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]
...
kernel_expanded[1,9,:] = [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]
Results after the as_strided:
kernel_expanded[0,0,:] = [1., 1., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0.]
kernel_expanded[0,1,:] = [0., 1., 1., 1., 0., 0., 0., 0., 0., 0., 0., 0.]
kernel_expanded[0,2,:] = [0., 0., 1., 1., 1., 0., 0., 0., 0., 0., 0., 0.]
...
kernel_expanded[0,9,:] = [0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 1., 1.]
kernel_expanded[1,0,:] = [1., 1., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0.]
kernel_expanded[1,1,:] = [0., 1., 1., 1., 0., 0., 0., 0., 0., 0., 0., 0.]
kernel_expanded[1,2,:] = [0., 0., 1., 1., 1., 0., 0., 0., 0., 0., 0., 0.]
...
kernel_expanded[1,9,:] = [0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 1., 1.]
'''
现在的问题是,由于Tensorflow不支持跨步,我如何才能有效地实现上述结果。谢谢。