Python 什么';torch.stack()和torch.cat()函数之间的区别是什么?

Python 什么';torch.stack()和torch.cat()函数之间的区别是什么?,python,machine-learning,deep-learning,pytorch,Python,Machine Learning,Deep Learning,Pytorch,OpenAI强化学习的强化和演员批评示例包含以下代码: : : 一个使用torch.cat,另一个使用torch.stack 就我的理解而言,他们之间没有任何明确的区别 我很乐意知道函数之间的差异。堆栈 沿新维度连接张量序列 cat 将给定维中给定序列的seq张量串联起来 因此,如果A和B是形状(3,4),torch.cat([A,B],dim=0)将是形状(6,4)和torch.stack([A,B],dim=0)将是形状(2,3,4)。原始答案缺少一个自成一体的好例子,因此它是这样的: im

OpenAI强化学习的强化和演员批评示例包含以下代码:

:

:

一个使用
torch.cat
,另一个使用
torch.stack

就我的理解而言,他们之间没有任何明确的区别

我很乐意知道函数之间的差异。
堆栈

沿新维度连接张量序列

cat

将给定维中给定序列的seq张量串联起来


因此,如果
A
B
是形状(3,4),
torch.cat([A,B],dim=0)
将是形状(6,4)和
torch.stack([A,B],dim=0)
将是形状(2,3,4)。

原始答案缺少一个自成一体的好例子,因此它是这样的:

import torch

# stack vs cat

# cat "extends" a list in the given dimension e.g. adds more rows or columns

x = torch.randn(2, 3)
print(f'{x.size()}')

# add more rows (thus increasing the dimensionality of the column space to 2 -> 6)
xnew_from_cat = torch.cat((x, x, x), 0)
print(f'{xnew_from_cat.size()}')

# add more columns (thus increasing the dimensionality of the row space to 3 -> 9)
xnew_from_cat = torch.cat((x, x, x), 1)
print(f'{xnew_from_cat.size()}')

print()

# stack serves the same role as append in lists. i.e. it doesn't change the original
# vector space but instead adds a new index to the new tensor, so you retain the ability
# get the original tensor you added to the list by indexing in the new dimension
xnew_from_stack = torch.stack((x, x, x, x), 0)
print(f'{xnew_from_stack.size()}')

xnew_from_stack = torch.stack((x, x, x, x), 1)
print(f'{xnew_from_stack.size()}')

xnew_from_stack = torch.stack((x, x, x, x), 2)
print(f'{xnew_from_stack.size()}')

# default appends at the from
xnew_from_stack = torch.stack((x, x, x, x))
print(f'{xnew_from_stack.size()}')

print('I like to think of xnew_from_stack as a \"tensor list\" that you can pop from the front')
输出:

torch.Size([2, 3])
torch.Size([6, 3])
torch.Size([2, 9])
torch.Size([4, 2, 3])
torch.Size([2, 4, 3])
torch.Size([2, 3, 4])
torch.Size([4, 2, 3])
I like to think of xnew_from_stack as a "tensor list"
以下定义仅供参考:

cat:在给定维中连接给定序列的seq张量。其结果是,特定维度的大小会发生变化,例如dim=0,然后您将向行中添加元素,从而增加列空间的维度

堆栈:沿新维度连接张量序列。我喜欢将此视为火炬“附加”操作,因为您可以通过从前面“弹出”来索引/获取原始张量。在没有参数的情况下,它将张量附加到张量的前面


相关的:

  • 这里是pytorch论坛的链接,讨论了这一点:我希望
    tensor.torch
    将一个嵌套的张量列表转换为一个大的张量,该张量具有多个维度,考虑嵌套列表的深度

更新:具有相同大小的嵌套列表 下面是一些单元测试(我没有编写更多的测试,但它与我的真实代码一起工作,所以我相信它很好。如果您愿意,可以通过添加更多测试来帮助我):

t1=火炬张量([[1,2],
[3, 4]])
t2=火炬张量([[5,6],
[7, 8]])
torch.stack
torch.cat
“堆叠”沿新维度的张量序列:







“Concat启用”沿现有维度的张量序列:


因此,torch.stack([A,B],dim=0)相当于torch.cat([A.unsqueze(0),B.unsqueze(0)],dim=0)。因此,如果您发现自己在组合张量之前执行了许多unsqueze()操作,您可能会使用stack()简化代码。作为补充,在问题中的OpenAI示例中,
torch.stack
torch.cat
可以在任一代码行中互换使用,因为
torch.stack(tensors).sum()==torch.cat(tensor).sum()
。如果您对tensor的可变长度嵌套列表感兴趣,这里有一些似乎有解决方案的链接:和
import torch

# stack vs cat

# cat "extends" a list in the given dimension e.g. adds more rows or columns

x = torch.randn(2, 3)
print(f'{x.size()}')

# add more rows (thus increasing the dimensionality of the column space to 2 -> 6)
xnew_from_cat = torch.cat((x, x, x), 0)
print(f'{xnew_from_cat.size()}')

# add more columns (thus increasing the dimensionality of the row space to 3 -> 9)
xnew_from_cat = torch.cat((x, x, x), 1)
print(f'{xnew_from_cat.size()}')

print()

# stack serves the same role as append in lists. i.e. it doesn't change the original
# vector space but instead adds a new index to the new tensor, so you retain the ability
# get the original tensor you added to the list by indexing in the new dimension
xnew_from_stack = torch.stack((x, x, x, x), 0)
print(f'{xnew_from_stack.size()}')

xnew_from_stack = torch.stack((x, x, x, x), 1)
print(f'{xnew_from_stack.size()}')

xnew_from_stack = torch.stack((x, x, x, x), 2)
print(f'{xnew_from_stack.size()}')

# default appends at the from
xnew_from_stack = torch.stack((x, x, x, x))
print(f'{xnew_from_stack.size()}')

print('I like to think of xnew_from_stack as a \"tensor list\" that you can pop from the front')
torch.Size([2, 3])
torch.Size([6, 3])
torch.Size([2, 9])
torch.Size([4, 2, 3])
torch.Size([2, 4, 3])
torch.Size([2, 3, 4])
torch.Size([4, 2, 3])
I like to think of xnew_from_stack as a "tensor list"
def tensorify(lst):
    """
    List must be nested list of tensors (with no varying lengths within a dimension).
    Nested list of nested lengths [D1, D2, ... DN] -> tensor([D1, D2, ..., DN)

    :return: nested list D
    """
    # base case, if the current list is not nested anymore, make it into tensor
    if type(lst[0]) != list:
        if type(lst) == torch.Tensor:
            return lst
        elif type(lst[0]) == torch.Tensor:
            return torch.stack(lst, dim=0)
        else:  # if the elements of lst are floats or something like that
            return torch.tensor(lst)
    current_dimension_i = len(lst)
    for d_i in range(current_dimension_i):
        tensor = tensorify(lst[d_i])
        lst[d_i] = tensor
    # end of loop lst[d_i] = tensor([D_i, ... D_0])
    tensor_lst = torch.stack(lst, dim=0)
    return tensor_lst

def test_tensorify():
    t = [1, 2, 3]
    print(tensorify(t).size())
    tt = [t, t, t]
    print(tensorify(tt))
    ttt = [tt, tt, tt]
    print(tensorify(ttt))

if __name__ == '__main__':
    test_tensorify()
    print('Done\a')