[PyTorch中文文档]-Package参考-torch-索引
torch.cat(inputs, dimension=0) → Tensor
在给定维度上对输入的张量序列seq 进行连接操作。
torch.cat()可以看做 torch.split() 和 torch.chunk()的反操作。 cat() 函数可以通过下面例子更好的理解。
参数:
inputs (sequence of Tensors) – 可以是任意相同Tensor 类型的python 序列
dimension (int, optional) – 沿着此维连接张量序列。
例子:
>>> x = torch.randn(2, 3)
>>> x
0.5983 -0.0341 2.4918
1.5981 -0.5265 -0.8735
[torch.FloatTensor of size 2x3]
>>> torch.cat((x, x, x), 0)
0.5983 -0.0341 2.4918
1.5981 -0.5265 -0.8735
0.5983 -0.0341 2.4918
1.5981 -0.5265 -0.8735
0.5983 -0.0341 2.4918
1.5981 -0.5265 -0.8735
[torch.FloatTensor of size 6x3]
>>> torch.cat((x, x, x), 1)
0.5983 -0.0341 2.4918 0.5983 -0.0341 2.4918 0.5983 -0.0341 2.4918
1.5981 -0.5265 -0.8735 1.5981 -0.5265 -0.8735 1.5981 -0.5265 -0.8735
[torch.FloatTensor of size 2x9]
torch.chunk(tensor, chunks, dim=0)
torch.chunk(tensor, chunk_num, dim)与torch.cat()原理相反,它是将tensor按dim(行或列)分割成chunk_num个tensor块,返回的是一个元组。
a = torch.Tensor([[1,2,4]])
b = torch.Tensor([[4,5,7], [3,9,8], [9,6,7]])
c = torch.cat((a,b), dim=0)
print(c)
print(c.size())
print('********************')
d = torch.chunk(c,4,dim=0)
print(d)
print(len(d))
torch.gather(input, dim, index, out=None) → Tensor
作用:收集输入的特定维度指定位置的数值
参数:
input(tensor): 待操作数。不妨设其维度为(x1, x2, …, xn)
dim(int): 待操作的维度。
index(LongTensor): 如何对input进行操作。其维度有限定,例如当dim=i时,index的维度为(x1, x2, …y, …,xn),既是将input的第i维的大小更改为y,且要满足y>=1(除了第i维之外的其他维度,大小要和input保持一致)。
out: 注意输出和index的维度是一致的
import torch
a = torch.tensor([[1, 2, 3, 4, 5], [6, 7, 8, 9, 10], [11, 12, 13, 14, 15] ])
index = torch.tensor([[0, 2],[3, 4], [1, 4]])
print(torch.gather(a, 1, index))
#tensor([[ 1, 3],
# [ 9, 10],
# [12, 15]])
torch.index_select(input, dim, index, out=None) → Tensor
沿着指定维度对输入进行切片,取index中指定的相应项(index为一个LongTensor),然后返回到一个新的张量, 返回的张量与原始张量Tensor有相同的维度(在指定轴上)。
注意: 返回的张量不与原始张量共享内存空间。
参数:
input (Tensor) – 输入张量
dim (int) – 索引的轴
index (LongTensor) – 包含索引下标的一维张量
out (Tensor, optional) – 目标张量
>>> x = torch.randn(3, 4)
>>> x
1.2045 2.4084 0.4001 1.1372
0.5596 1.5677 0.6219 -0.7954
1.3635 -1.2313 -0.5414 -1.8478
[torch.FloatTensor of size 3x4]
>>> indices = torch.LongTensor([0, 2])
>>> torch.index_select(x, 0, indices)
1.2045 2.4084 0.4001 1.1372
1.3635 -1.2313 -0.5414 -1.8478
[torch.FloatTensor of size 2x4]
>>> torch.index_select(x, 1, indices)
1.2045 0.4001
0.5596 0.6219
1.3635 -0.5414
[torch.FloatTensor of size 3x2]
torch.masked_select(input, mask, out=None) → Tensor
根据掩码张量mask中的二元值,取输入张量中的指定项( mask为一个 ByteTensor),将取值返回到一个新的1D张量,
张量 mask须跟input张量有相同数量的元素数目,但形状或维度不需要相同。 注意: 返回的张量不与原始张量共享内存空间。
参数:
input (Tensor) – 输入张量
mask (ByteTensor) – 掩码张量,包含了二元索引值
out (Tensor, optional) – 目标张量
>>> x = torch.randn(3, 4)
>>> x
tensor([[ 0.3552, -2.3825, -0.8297, 0.3477],
[-1.2035, 1.2252, 0.5002, 0.6248],
[ 0.1307, -2.0608, 0.1244, 2.0139]])
>>> mask = x.ge(0.5)
>>> mask
tensor([[False, False, False, False],
[False, True, True, True],
[False, False, False, True]])
>>> torch.masked_select(x, mask)
tensor([ 1.2252, 0.5002, 0.6248, 2.0139])
使用方法其实挺明显的,就是把input与mask相对应起来,取出mask中True所对应位置的数据,组成一维的tensor。
注意:mask和input的形状可以不相同,但是它们必须是可以广播的。并且返回tensor和原tensor使用不同的内存,相互独立。
torch.nonzero(input, out=None) → LongTensor
找出tensor中非零的元素的索引。返回一个包含输入 input 中非零元素索引的张量.输出张量中的每行包含 input 中非零元素的索引。
torch.nonzero(input, *, out=None, as_tuple=False)
image.png
import torch
label = torch.tensor([[1,0,0],
[1,0,1]])
print(label.nonzero())
输出:
tensor([[0, 0],
[1, 0],
[1, 2]])
有时我们只想得到一种元素对应的索引,比如我们只想要1对应的索引:
import torch
label = torch.tensor([[1,0,0],
[3,0,1]])
print((label==1).nonzero())
输出:
tensor([[0, 0],
[1, 2]])
或者,我们想要一定条件下的元素的索引,比如大于1的元素的索引:
import torch
label = torch.tensor([[1,0,0],
[3,0,1]])
print((label>1).nonzero())
输出:
tensor([[1, 0]])
torch.split(tensor, split_size, dim=0)
将输入张量分割成相等形状的chunks(如果可分)。 如果沿指定维的张量形状大小不能被split_size 整分, 则最后一个分块会小于其它分块。
参数:
tensor (Tensor) – 待分割张量
split_size (int) – 单个分块的形状大小
dim (int) – 沿着此维进行分割
split_size_or_sections为int型时
import torch
x = torch.rand(4,8,6)
y = torch.split(x,2,dim=0) #按照4这个维度去分,每大块包含2个小块
for i in y :
print(i.size())
output:
torch.Size([2, 8, 6])
torch.Size([2, 8, 6])
y = torch.split(x,3,dim=0)#按照4这个维度去分,每大块包含3个小块
for i in y:
print(i.size())
output:
torch.Size([3, 8, 6])
torch.Size([1, 8, 6])
split_size_or_sections为list型时。
import torch
x = torch.rand(4,8,6)
y = torch.split(x,[2,3,3],dim=1)
for i in y:
print(i.size())
output:
torch.Size([4, 2, 6])
torch.Size([4, 3, 6])
torch.Size([4, 3, 6])
y = torch.split(x,[2,1,3],dim=1) #2+1+3 等于7,报错
for i in y:
print(i.size())
output:
split_with_sizes expects split_sizes to sum exactly to 8 (input tensor's size at dimension 1), but got split_sizes=[2, 1, 3]
torch.squeeze(input, dim=None, out=None)
核心功能:
这个函数主要对数据的维度进行压缩,去掉维数为1的的维度。比如:是一行或者一列这种,一个一行三列(1,3)的数去掉第一个维数为一的维度之后就变成(3)行。b=torch.squeeze(a,N) 就是将a中所有为1的维度删掉,不为1的维度没有影响。
参数说明:
input (Tensor): 输入张量(the input tensor.)
dim (int, optional): 将输入Tensor的第dim个维度位置进行压缩,如果输入Tensor此处维度为1则压缩成功,否则失败。如果该参数给定,则输入张量将仅在该维度上压缩(if given, the input will be squeezed only in this dimension.),如果该参数不给定,则默认将输入Tensor所有维度为1的进行压缩。参数dim的取值范围为:[-input.dim(), input.dim()-1] 。
x = torch.zeros(2, 1, 2, 1, 2)
x
>>>
tensor([[[[[0., 0.]],
[[0., 0.]]]],
[[[[0., 0.]],
[[0., 0.]]]]])
print(x.size())
>>> torch.Size([2, 1, 2, 1, 2])
y = torch.squeeze(x)
y
>>>
tensor([[[0., 0.],
[0., 0.]],
[[0., 0.],
[0., 0.]]])
print(y.size())
>>> torch.Size([2, 2, 2])
# 如果第一个维度为一,则将其进行压缩;否则,不能压缩
y = torch.squeeze(x, 0) # 或者 y = torch.squeeze(x, dim=0)
print(y.size())
>>> torch.Size([2, 1, 2, 1, 2])
# 如果第二个维度为一,则将其进行压缩
y = torch.squeeze(x, 1) # 或者 y = torch.squeeze(x, dim=1)
print(y.size())
>>> torch.Size([2, 2, 1, 2])
# 如果第三个维度为一,则将其进行压缩;否则,不能压缩
y = torch.squeeze(x, 2) # 或者 y = torch.squeeze(x, dim=2)
print(y.size())
>>> torch.Size([2, 1, 2, 1, 2])
# 如果第四个维度为一,则将其进行压缩
y = torch.squeeze(x, dim=3) # 或者 y = torch.squeeze(x, dim=3)
print(y.size())
torch.Size([2, 1, 2, 2])
# 如果第五个维度为一,则将其进行压缩
y = torch.squeeze(x, dim=4) # 或者 y = torch.squeeze(x, dim=4)
print(y.size())
torch.Size([2, 1, 2, 1, 2])
torch.unsqueeze(input, dim)
核心功能:
在tensor的某个维度上添加一个维数为1的维度,这个功能用view()函数也可以实现。比如:原本有个三行的数据(3),在0的位置加了一维就变成一行三列(1,3)。a.unsqueeze(N) 就是在a中指定位置N加上一个维数为1的维度。还有一种形式就是b=torch.unsqueeze(a,N) a就是在a中指定位置N加上一个维数为1的维度。这一功能尤其在神经网络输入单个样本时很有用,由于pytorch神经网络要求的输入都是mini-batch型的,维度为[batch_size, channels, w, h],而一个样本的维度为[c, w, h],此时用unsqueeze()增加一个维度变为[1, c, w, h]就很方便了。
参数说明:
input (Tensor):输入张量(the input tensor.)
dim (int):插入维数为一的维度的位置(the index at which to insert the singleton dimension.)参数dim的取值范围为:[-input.dim() - 1, input.dim() + 1)
备注: 以0为分界,正向取值和反向取值的效果相同,其原理类似DataFrame中的正向、反向切片操作。正向取值时,0表示行,1表示列;反向取值时,-1表示列,-2表示行。
\quad
例如:若input。dim()==1,此时,dim的取值范围为[-2,2),正向取值时——dim=0(表示:行维度为1,即:新生成Tensor的shape为 torch.Size([1, 100]) );dim=1(表示:列维度为1,即:新生成Tensor的shape为 torch.Size([100, 1]) ))。反向取值时——dim=-2(表示:行维度为1,即:新生成Tensor的shape为 torch.Size([1, 100]) );dim=-1(表示:列维度为1,即:新生成Tensor的shape为 torch.Size([100, 1]) )
a = torch.linspace(-1, 1, 100) # 生成-1到1的100个数构成的等差数列
print(a.shape)
>>> torch.Size([100])
x = torch.unsqueeze(torch.linspace(-1, 1, 100), dim=1) # dim=1,表示列方向维度为1
print(x.shape)
>>> torch.Size([100, 1])
x = torch.tensor([1, 2, 3, 4])
torch.unsqueeze(x, 0)
>>> tensor([[ 1, 2, 3, 4]])
torch.unsqueeze(x, 1)
>>> tensor([[ 1],
[ 2],
[ 3],
[ 4]])
x = torch.zeros(2, 2, 2)
print(x.shape)
>>> torch.Size([2, 2, 2])
# 在input的第三个维度上扩充维度1
y = torch.unsqueeze(x, dim=2)
print(y.shape)
>>> torch.Size([2, 2, 1, 2])
torch.stack(sequence, dim=0)
torch.stack()函数和torch.cat()有所不同,torch.stack()并不在已有的维度进行拼接,而是沿着新的维度进行拼接。
我在使用torch.stack()产生了两个问题:
1.怎么确定新的维度产生在哪里?
2.指定了新维度后要怎么拼接?
下面我以两个张量来说明,分别是A和B
A = torch.arange(6.0).reshape(2,3)
B = torch.linspace(0,10,6).reshape(2,3)
A= tensor([[0., 1., 2.],
[3., 4., 5.]])
B= tensor([[ 0., 2., 4.],
[ 6., 8., 10.]])
既然知道函数会为张量产生一个新维度,那么我们可以假设,令A和B维度升级,从(2,3)变为(1,2,3),即:
A1= tensor([[[0., 1., 2.],
[3., 4., 5.]]])
B1= tensor([[[ 0., 2., 4.],
[ 6., 8., 10.]]])
#A1、B1比A、B在最外层多了一组括号[]
这样,接下里就很好解释了。
参数dim表示相连维度在这3维里的索引,如用link表示连接维度:
dim=0时,(link,#,#)
dim=1时,(#,link,#)
dim=2时,(#,#,link)
link所在的维度是哪个,就把A1和B1对应维度里的元素逐个相连。
下面我对每个维度都演示一遍
dim=0
F1 = torch.stack((A,B),dim=0)
print('F1=',F1)
print('F1的维度是',F1.shape)
F1= tensor([[[ 0., 1., 2.],
[ 3., 4., 5.]],
[[ 0., 2., 4.],
[ 6., 8., 10.]]])
F1的维度是 torch.Size([2, 2, 3])
用上面的说法来理解,这相当于在A1和B1的第0维度里,每个元素依次相连,每对连接元素用[ ]包装。
A1的第0维度里只有A一个元素
B1的第0维度里只有B一个元素
因此如上所示,F1的结果其实就是[A,B]
dim=1
F2 = torch.stack((A,B),dim=1)
print('F2=',F2)
print('F2的维度是',F2.shape)
F2= tensor([[[ 0., 1., 2.],
[ 0., 2., 4.]],
[[ 3., 4., 5.],
[ 6., 8., 10.]]])
F2的维度是 torch.Size([2, 2, 3])
沿用上面的理解
A1的第1维度里的两个元素:[0. 1, 2],[3, 4, 5]
B1的第1维度里的两个元素:[0, 2, 4],[6, 8, 10]
[0. 1, 2]和[0, 2, 4]相连,[ ]包起来
[3, 4, 5]和[6, 8, 10]相连,[ ]包起来
最后给以上两组用[ ]包起来
dim=2
F3 = torch.stack((A,B),dim=2)
print('F3=',F3)
print('F3的维度是',F3.shape)
F3= tensor([[[ 0., 0.],
[ 1., 2.],
[ 2., 4.]],
[[ 3., 6.],
[ 4., 8.],
[ 5., 10.]]])
F3的维度是 torch.Size([2, 3, 2])
A1和B1的第2维度里每个元素依次相连,每对连接元素用[]包装
A1第2维度里的元素:0,1,2,3,4,5
B1第2维度里的元素:0,2,4,6,8,10
两两相连后打包[0,0] [1,2] [2,4] [3,6] [4,8] [5,10]
由于[0,1,2]和[0,2,4]的第1维度属性是0
[3,4,5]和[6,8,10]的第1维度属性是1
所以把第一维度属性是0的和是1的单独打包
即[[0,0],[1,2],[2,4]]和[[3,6],[4,8],[5,10]]
最后将以上两组一起[]包起来
torch.t(input, out=None) → Tensor
输入一个矩阵(2维张量),并转置0, 1维。 可以被视为函数transpose(input, 0, 1)的简写函数。
参数:
input (Tensor) – 输入张量
out (Tensor, optional) – 结果张量
>>> x = torch.randn(2, 3)
>>> x
0.4834 0.6907 1.3417
-0.1300 0.5295 0.2321
[torch.FloatTensor of size 2x3]
>>> torch.t(x)
0.4834 -0.1300
0.6907 0.5295
1.3417 0.2321
[torch.FloatTensor of size 3x2]
torch.transpose(input, dim0, dim1, out=None) → Tensor
返回输入矩阵input的转置。交换维度dim0和dim1。 输出张量与输入张量共享内存,所以改变其中一个会导致另外一个也被修改。
参数:
input (Tensor) – 输入张量
dim0 (int) – 转置的第一维
dim1 (int) – 转置的第二维
>>> x = torch.randn(2, 3)
>>> x
0.5983 -0.0341 2.4918
1.5981 -0.5265 -0.8735
[torch.FloatTensor of size 2x3]
>>> torch.transpose(x, 0, 1)
0.5983 1.5981
-0.0341 -0.5265
2.4918 -0.8735
[torch.FloatTensor of size 3x2]
torch.unbind(tensor, dim=0)[source]
移除指定维后,返回一个元组,包含了沿着指定维切片后的各个切片
参数:
tensor (Tensor) – 输入张量
dim (int) – 删除的维度
此方法就是将我们的input从dim进行切片,并返回切片的结果,返回的结果里面没有dim这个维度。
例如维度为0的时候,如下所示:
>>> torch.unbind(torch.tensor([[1, 2, 3],
>>> [4, 5, 6],
>>> [7, 8, 9]]))
(tensor([1, 2, 3]), tensor([4, 5, 6]), tensor([7, 8, 9]))