Hah*_*pro 27 python numpy deep-learning pytorch tensor
例如,我有1维向量的维度(5).我想将其重塑为2D矩阵(1,5).
这是我如何用numpy做的
>>> import numpy as np
>>> a = np.array([1,2,3,4,5])
>>> a.shape
(5,)
>>> a = np.reshape(a, (1,5))
>>> a.shape
(1, 5)
>>> a
array([[1, 2, 3, 4, 5]])
>>>
Run Code Online (Sandbox Code Playgroud)
但是我怎么能用Pytorch Tensor(和Variable)做到这一点.我不想切换回numpy并再次切换到Torch变量,因为它会丢失反向传播信息.
这就是我在Pytorch中所拥有的
>>> import torch
>>> from torch.autograd import Variable
>>> a = torch.Tensor([1,2,3,4,5])
>>> a
1
2
3
4
5
[torch.FloatTensor of size 5]
>>> a.size()
(5L,)
>>> a_var = variable(a)
>>> a_var = Variable(a)
>>> a_var.size()
(5L,)
.....do some calculation in forward function
>>> a_var.size()
(5L,)
Run Code Online (Sandbox Code Playgroud)
现在我希望它的大小为(1,5).如何在不丢失梯度信息的情况下调整变量张量的大小或重新整形.(因为我会在向后进入另一个模型)
Hah*_*pro 22
使用 torch.unsqueeze(输入,暗淡,输出=无)
>>> import torch
>>> a = torch.Tensor([1,2,3,4,5])
>>> a
1
2
3
4
5
[torch.FloatTensor of size 5]
>>> a = a.unsqueeze(0)
>>> a
1 2 3 4 5
[torch.FloatTensor of size 1x5]
Run Code Online (Sandbox Code Playgroud)
小智 14
你可能会用
a.view(1,5)
Out:
1 2 3 4 5
[torch.FloatTensor of size 1x5]
Run Code Online (Sandbox Code Playgroud)
sta*_*010 12
有多种方法可以重塑 PyTorch 张量。您可以将这些方法应用于任何维度的张量。
让我们从一个二维2 x 3
张量开始:
x = torch.Tensor(2, 3)
print(x.shape)
# torch.Size([2, 3])
Run Code Online (Sandbox Code Playgroud)
为了给这个问题增加一些鲁棒性,让我们2 x 3
通过在前面添加一个新维度和在中间添加另一个维度来重塑张量,产生一个1 x 2 x 1 x 3
张量。
None
使用 NumPy 样式的None
(aka np.newaxis
)插入在您想要的任何位置添加维度。见这里。
print(x.shape)
# torch.Size([2, 3])
y = x[None, :, None, :] # Add new dimensions at positions 0 and 2.
print(y.shape)
# torch.Size([1, 2, 1, 3])
Run Code Online (Sandbox Code Playgroud)
使用torch.Tensor.unsqueeze(i)
(又名torch.unsqueeze(tensor, i)
或就地版本unsqueeze_()
)在第 i 个维度添加一个新维度。返回的张量与原始张量共享相同的数据。在这个例子中,我们可以使用unqueeze()
两次来添加两个新维度。
print(x.shape)
# torch.Size([2, 3])
# Use unsqueeze twice.
y = x.unsqueeze(0) # Add new dimension at position 0
print(y.shape)
# torch.Size([1, 2, 3])
y = y.unsqueeze(2) # Add new dimension at position 2
print(y.shape)
# torch.Size([1, 2, 1, 3])
Run Code Online (Sandbox Code Playgroud)
在 PyTorch 的实践中,为批处理添加额外的维度可能很重要,因此您可能经常看到unsqueeze(0)
.
使用torch.Tensor.view(*shape)
指定的所有尺寸。返回的张量与原始张量共享相同的数据。
print(x.shape)
# torch.Size([2, 3])
y = x.view(1, 2, 1, 3)
print(y.shape)
# torch.Size([1, 2, 1, 3])
Run Code Online (Sandbox Code Playgroud)
使用torch.Tensor.reshape(*shape)
(aka torch.reshape(tensor, shapetuple)
) 指定所有维度。如果原始数据是连续的并且具有相同的步幅,则返回的张量将是输入的视图(共享相同的数据),否则将是副本。此函数类似于 NumPyreshape()
函数,因为它允许您定义所有维度,并且可以返回视图或副本。
print(x.shape)
# torch.Size([2, 3])
y = x.reshape(1, 2, 1, 3)
print(y.shape)
# torch.Size([1, 2, 1, 3])
Run Code Online (Sandbox Code Playgroud)
此外,作者在 O'Reilly 2019 年的《深度学习编程 PyTorch 》一书中写道:
现在您可能想知道view()
和之间有什么区别reshape()
。答案是它view()
作为原始张量的视图运行,因此如果底层数据发生变化,视图也会发生变化(反之亦然)。但是,view()
如果所需视图不连续,则可能会引发错误;也就是说,如果从头开始创建所需形状的新张量,它不会共享相同的内存块。如果发生这种情况,您必须先调用,tensor.contiguous()
然后才能使用view()
. 但是,reshape()
所有这些都是在幕后完成的,所以总的来说,我建议使用reshape()
而不是view()
.
使用就地函数torch.Tensor.resize_(*sizes)
修改原始张量。该文件指出:
警告。这是一种低级方法。存储被重新解释为 C 连续,忽略当前步幅(除非目标大小等于当前大小,在这种情况下张量保持不变)。对于大多数用途,您将改为使用view()
,它检查连续性,或者reshape()
,它在需要时复制数据。要使用自定义步幅就地更改大小,请参阅set_()
。
print(x.shape)
# torch.Size([2, 3])
x.resize_(1, 2, 1, 3)
print(x.shape)
# torch.Size([1, 2, 1, 3])
Run Code Online (Sandbox Code Playgroud)
如果您只想添加一个维度(例如为批次添加第 0 个维度),则使用unsqueeze(0)
. 如果您想完全改变维度,请使用reshape()
.
pytorch 中的 reshape 和 view 有什么区别?
在 PyTorch 0.4 中,是否推荐使用reshape
比view
可能的时候?
对于张量的就地修改,你绝对应该使用 tensor.resize_():
In [23]: a = torch.Tensor([1, 2, 3, 4, 5])
In [24]: a.shape
Out[24]: torch.Size([5])
# tensor.resize_((`new_shape`))
In [25]: a.resize_((1,5))
Out[25]:
1 2 3 4 5
[torch.FloatTensor of size 1x5]
In [26]: a.shape
Out[26]: torch.Size([1, 5])
Run Code Online (Sandbox Code Playgroud)
在PyTorch中,如果在操作结束时有一个下划线(如tensor.resize_()
),则该操作会对in-place
原始张量进行修改.
此外,您只需np.newaxis
在割炬Tensor中使用即可增加尺寸.这是一个例子:
In [34]: list_ = range(5)
In [35]: a = torch.Tensor(list_)
In [36]: a.shape
Out[36]: torch.Size([5])
In [37]: new_a = a[np.newaxis, :]
In [38]: new_a.shape
Out[38]: torch.Size([1, 5])
Run Code Online (Sandbox Code Playgroud)
小智 6
或者您可以使用它,“-1”表示您不必指定元素的数量。
In [3]: a.view(1,-1)
Out[3]:
1 2 3 4 5
[torch.FloatTensor of size 1x5]
Run Code Online (Sandbox Code Playgroud)
这个问题已经得到了彻底的回答,但我想为经验不足的 Python 开发人员补充一点,您可能会发现*
运算符与view()
.
例如,如果您希望不同的数据张量符合特定的张量大小,则可以尝试:
img = Variable(tensor.randn(20,30,3)) # tensor with goal shape
flat_size = 20*30*3
X = Variable(tensor.randn(50, flat_size)) # data tensor
X = X.view(-1, *img.size()) # sweet maneuver
print(X.size()) # size is (50, 20, 30, 3)
Run Code Online (Sandbox Code Playgroud)
这也适用于 numpy shape
:
img = np.random.randn(20,30,3)
flat_size = 20*30*3
X = Variable(tensor.randn(50, flat_size))
X = X.view(-1, *img.shape)
print(X.size()) # size is (50, 20, 30, 3)
Run Code Online (Sandbox Code Playgroud)
torch.reshape()是为了欺骗numpy reshape方法。
它位于view()和torch.resize_()之后,并且位于dir(torch)
包内。
import torch
x=torch.arange(24)
print(x, x.shape)
x_view = x.view(1,2,3,4) # works on is_contiguous() tensor
print(x_view.shape)
x_reshaped = x.reshape(1,2,3,4) # works on any tensor
print(x_reshaped.shape)
x_reshaped2 = torch.reshape(x_reshaped, (-1,)) # part of torch package, while view() and resize_() are not
print(x_reshaped2.shape)
Run Code Online (Sandbox Code Playgroud)
出去:
tensor([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
18, 19, 20, 21, 22, 23]) torch.Size([24])
torch.Size([1, 2, 3, 4])
torch.Size([1, 2, 3, 4])
torch.Size([24])
Run Code Online (Sandbox Code Playgroud)
但您知道吗,它还可以替代squeeze()和unsqueeze()
x = torch.tensor([1, 2, 3, 4])
print(x.shape)
x1 = torch.unsqueeze(x, 0)
print(x1.shape)
x2 = torch.unsqueeze(x1, 1)
print(x2.shape)
x3=x.reshape(1,1,4)
print(x3.shape)
x4=x.reshape(4)
print(x4.shape)
x5=x3.squeeze()
print(x5.shape)
Run Code Online (Sandbox Code Playgroud)
出去:
torch.Size([4])
torch.Size([1, 4])
torch.Size([1, 1, 4])
torch.Size([1, 1, 4])
torch.Size([4])
torch.Size([4])
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
66707 次 |
最近记录: |