切片保存在列表中的 Pytorch 张量

slice Pytorch tensors which are saved in a list

我有以下代码段来生成随机样本。生成的 samples 是一个 list,其中列表的每个条目都是一个 tensor。每个张量都有两个元素。我想从列表中的所有张量中提取第一个元素;并从列表中的所有张量中提取第二个元素。如何进行这种张量切片操作

import torch
import pyro.distributions as dist
num_samples = 250
# note that both covariance matrices are diagonal
mu1 = torch.tensor([0., 5.])
sig1 = torch.tensor([[2., 0.], [0., 3.]])
dist1 = dist.MultivariateNormal(mu1, sig1)
samples1 = [pyro.sample('samples1', dist1) for _ in range(num_samples)]

samples1

我建议 torch.cat 具有列表理解力:

col1 = torch.cat([t[0] for t in samples1])
col2 = torch.cat([t[1] for t in samples1])

torch.cat 的文档:https://pytorch.org/docs/stable/generated/torch.cat.html

或者

您可以使用 torch.stack 将一维张量列表转换为一个大的二维张量,然后进行普通切片:

samples1_t = torch.stack(samples1)
col1 = samples1_t[:, 0]  # : means all rows
col2 = samples1_t[:, 1]

torch.stack 的文档:https://pytorch.org/docs/stable/generated/torch.stack.html

我应该提到 PyTorch 张量开箱即用,这意味着您可以将第一个轴解包为多个变量,而无需额外考虑。这里 torch.stack will output a tensor of shape (rows, cols), we just need to transpose it to (cols, rows) and unpack:

>>> c1, c2 = torch.stack(samples1).T

所以你得到 c1c2(rows,):

>>> c1
tensor([0.6433, 0.4667, 0.6811, 0.2006, 0.6623, 0.7033])

>>> c2
tensor([0.2963, 0.2335, 0.6803, 0.1575, 0.9420, 0.6963])

建议 .stack().cat() 的其他答案从 PyTorch 的角度来看完全没问题。

但是,由于问题的上下文涉及到pyro,请允许我添加以下内容:

因为你在做 IID 样本

[pyro.sample('samples1', dist1) for _ in range(num_samples)]

使用 pyro 的更好方法是

dist1 = dist.MultivariateNormal(mu1, sig1).expand([num_samples])

这告诉 pyro 分布是 批处理的 ,批量大小为 num_samples。从中抽样将产生

>> dist1.sample()
tensor([[-0.8712,  6.6087],
    [ 1.6076, -0.2939],
    [ 1.4526,  6.1777],
    ...
    [-0.0168,  7.5085],
    [-1.6382,  2.1878]])

现在很容易解决你原来的问题。像这样切片就可以了

samples = dist1.sample()
samples[:, 0]  # all first elements
samples[:, 1]  # all second elements