在NumPy中计算Tp,q,r = Sp,q Sp,r的最佳方法是什么?

mnemlml8  于 2023-10-19  发布在  其他
关注(0)|答案(2)|浏览(97)

我试图把一系列m个输入序列,每个序列有n个元素(sm,n),变成一个Tensor,其中tp,q,r = sp,qsp,r
虽然我的代码确实工作,但我觉得必须有更好的解决方案。这是我得到的。

# nseqs is the number of sequences
# seq_length is the sequence length
# seq is a list of sequences

output = np.empty((nseqs, seq_length, seq_length))
for n in range(nseqs):
    for i, j in enumerate(seq[n]):
        output[n, i, :] = j
    output[n, :, :] *= output[n, :, :].T

更重要的是,有没有一种方法可以重新调整outputTensor,使乘法阶段在一个步骤中完成,而没有那些循环?

bmvo0sr5

bmvo0sr51#

你可以通过广播达到预期的效果。第一个尺寸对齐,其他尺寸可以使用None引入的单位尺寸强制为正确的形状:

t = s[:, :, None] * s[:, None, :]

你可以在没有循环的情况下实现你的原始方法,方法是给输出的元素分配广播,然后只对最后一个维度进行转置:

output = np.empty((seq.shape[0], seq.shape[1], seq.shape[1]), seq.dtype)
output[:] = seq[..., None]
output *= output.transpose(0, 2, 1)
vecaoik1

vecaoik12#

你没有给予任何数字或例子,所以我编了一个小的(如果它不适合你的实际情况,你必须告诉我)。
考虑以下情况:

import numpy as np

nseqs = 4
seq_length = 5

seq = np.arange(nseqs*seq_length).reshape(nseqs, seq_length)

从内部循环开始,我们可以使用广播来实现同样的事情。

output = np.empty((nseqs, seq_length, seq_length))
for n in range(nseqs):
    output2[n] = seq[n,None]
    output[n, :, :] *= output[n, :, :].T

现在,乘法实际上不会影响后续的循环,所以我们可以将其分为两个循环。

output = np.empty((nseqs, seq_length, seq_length))
for n in range(nseqs):
    output2[n] = seq[n,None]
for n in range(nseqs):
    output[n, :, :] *= output[n, :, :].T

第一个循环的广播只是在每个子矩阵中重复seq[n]的元素,所以我们可以使用np.repeat得到相同的结果。

output = np.repeat(seq[:,None], seq_length, axis=1)

第二个循环是子矩阵output[n]乘以它的转置。这可以使用np.swapaxes来完成,交换最后两个轴(即执行子矩阵的转置)。

output *= np.swapaxes(output, 1, 2)

最后,你的代码缩减为:

output = np.repeat(seq[:,None], seq_length, axis=1)
output *= np.swapaxes(output, 1, 2)

相关问题