Python 在mxnet中高效创建压缩带状对角矩阵

Python 在mxnet中高效创建压缩带状对角矩阵,python,mxnet,Python,Mxnet,在我的问题中,我有一个包含n元素的向量。给定一个窗口大小k,我想有效地创建一个包含带状对角线的矩阵大小nx2k+1。例如: a = [a_1, a_2, a_3, a_4] k = 1 b = [[0, a_1, a_2], [a_1, a_2, a_3], [a_2, a_3, a_4], [a_3, a_4, a_5], [a_4, a_5, 0]] 实现这一点的简单方法是使用for循环 out_data=mx.ndarray.zeros((n,2k+1))

在我的问题中,我有一个包含
n
元素的向量。给定一个窗口大小
k
,我想有效地创建一个包含带状对角线的矩阵大小
nx2k+1
。例如:

a = [a_1, a_2, a_3, a_4]
k = 1
b = [[0, a_1, a_2],
    [a_1, a_2, a_3],
    [a_2, a_3, a_4],
    [a_3, a_4, a_5],
    [a_4, a_5, 0]]
实现这一点的简单方法是使用for循环

out_data=mx.ndarray.zeros((n,2k+1))
对于范围(0,n)内的i:
对于范围(0,2k+1)内的j:
指数=i-k+j
如果不是(索引<0或索引>=序号):
out_data[i][j]=in_data[index]
这很慢

只需使用
平铺
重塑
即可轻松创建完整矩阵,但遮罩部分并不清晰

更新 我发现了一个更快但仍然非常缓慢的实现:

window = 2*self.windowSize + 1
in_data_reshaped = in_data.reshape((batch_size, seq_len))
out_data = mx.ndarray.zeros((seq_len * window))
for i in range(0, seq_len):
    copy_from_start = max(i - self.windowSize, 0)
    copy_from_end = min(seq_len -1, i+1+self.windowSize)
    copy_length = copy_from_end - copy_from_start
    copy_to_start = i*window + (2*self.windowSize + 1 - copy_length)
    copy_to_end = copy_to_start + copy_length
    out_data[copy_to_start:copy_to_end] = in_data_reshaped[copy_from_start:copy_from_end]
out_data = out_data.reshape((seq_len, window))

如果在您的操作中,
k
n
是常数,您可以使用和组合来执行您想要的操作。即使生成索引张量也同样低效,因为只需要做一次,这也不是问题。您可能希望使用
collection\u nd
有效地“复制”原始阵列中的数据,然后使用
scatter\u nd
将它们分散到最终的矩阵形状。或者,您可以简单地将
0
元素连接到输入数组(例如
[a_1,a_2,a_3]
将变成
[0,a_1,a_2,a_3]
),然后仅使用
mxnet.nd.gather_nd()
将元素复制到最终矩阵中。

谢谢这一技巧的帮助。我做了一个示例实现,看到了这一点。有两个警告。(1) mxnet中的填充仅适用于4维或5维数组(2)聚集尚未与批次“兼容”,这意味着必须显式计算索引,以获得第一个警告,您可以调用
NDArray.reformate()
,要向数组中添加额外维度并在填充完成后将其重新整形,请执行以下操作:attention_padded=mx.nd.pad(attention.reforme((1,2,4,1)),mode='constant',constant_value=0,pad_width=(0,0,0,k,k,0,0)).reforme((2,4,1))