前面已经介绍了 index_select 和 mask_select 两个选择函数,这两个函数通过一定的索引规则从输入张量中筛选出满足条件的元素值,只不过 index_select 函数使用索引 index 的索引规则,而 mask_select 函数使用布尔掩码 mask 的索引规则。
本小节介绍的 torch.nonzero(input, out = None, as_tuple = False) 函数与前面两个选择函数最大的不同是:「nonzero 函数返回的是输入张量中非零元素的索引而不是输入张量中符合索引规则的元素值 (index_select 和 mask_select)」,nonzero 函数的参数有:
参数 as_tuple 的取值决定了 nonzero 函数最终呈现的输出形式,接下来以参数 as_tuple 的参数值为 False 或 True 来分别介绍 nonzero 函数。
torch.nonzero(input, out = None, as_tuple = False) 函数返回一个 2D 张量,2D 张量中的每一行都是输入张量中非零元素值的索引。
>>> import torch
>>> # 输入张量为1D张量
>>> input_1d = torch.tensor([1, 1, 0, 1])
>>> output_1d = torch.nonzero(input_1d, as_tuple = False)
>>> print(output_1d.size())
torch.Size([3, 1])
>>> print(output_1d)
tensor([[0],
[1],
[3]])
>>> # 输入张量为2D张量
>>> input_2d = torch.tensor([[0, 1], [2, 3]])
>>> output_2d = torch.nonzero(input_2d, as_tuple = False)
>>> print(output_2d.size())
torch.Size([3, 2])
>>> print(output_2d)
tensor([[0, 1],
[1, 0],
[1, 1]])
>>> # 输入张量为3D张量
>>> input_3d = torch.tensor([[[0, 1],[3, 4]],
[[1, 0],[0, 0]]])
>>> output_3d = torch.nonzero(input_3d, as_tuple = False)
>>> print(output_3d.size())
torch.Size([4, 3])
>>> print(output_3d)
tensor([[0, 0, 1],
[0, 1, 0],
[0, 1, 1],
[1, 0, 0]])
这里以 2D 张量为例,简单分析当 as_tuple = False 时的 nonzero 函数,此时的 2D 输入张量为:
2D 输入张量可以看成大家熟悉的矩阵,通过矩阵中的行和列可以索引矩阵中任意元素,此时矩阵中有 3 个非零元素:
使用 torch.nonzero(input, out = None, as_tuple = False) 函数返回的是一个形状为 (3 x 2) 的 2D 张量 torch.tensor([[0, 1], [1, 0], [1, 1]])
,2D 张量一共有 3 个行,每一个行都是一个非零元素的索引,即 torch.tensor([index_1, index_2, index_3])
。
当 as_tuple = False (默认) 时的 nonzero 函数需要注意两点:
torch.nonzero(input, out = None, as_tuple = True) 函数返回元素为 1D 张量的元组,每一个 1D 张量对应输入张量的一个维度,而 1D 张量中的每个元素值表示输入张量中的非零元素在该维度上的索引。
>>> import torch
>>> # 输入张量为1D张量
>>> input_1d = torch.tensor([1, 1, 0, 1])
>>> output_1d = torch.nonzero(input_1d, as_tuple = True)
>>> print(output_1d)
(tensor([0, 1, 3]),)
>>> # 输入张量为2D张量
>>> input_2d = torch.tensor([[0, 1], [1, 2]])
>>> output_2d = torch.nonzero(input_2d, as_tuple = True)
>>> print(output_2d)
(tensor([0, 1, 1]), tensor([1, 0, 1]))
>>> # 输入张量为3D张量
>>> input_3d = torch.tensor([[[0, 1],[3, 4]],
[[1, 0],[0, 0]]])
>>> output_3d = torch.nonzero(input_3d, as_tuple = True)
>>> print(output_3d)
(tensor([0, 0, 0, 1]), tensor([0, 1, 1, 0]), tensor([1, 0, 1, 0]))
此处的代码只是对前面 as_tuple = False 时的代码进行了两处修改:
因为 2D 张量可以看成矩阵方便描述,因此同样以大家熟悉的 2D 张量为例,简单分析当 as_tuple = True 时的 nonzero 函数。此时 nonzero 函数返回的元组为 (tensor([0, 1, 1]), tensor([1, 0, 1]))
,元组中的两个 1D 张量分别对应矩阵的行和列:
此时矩阵中有 3 个非零元素:
使用 torch.nonzero(input, out = None, as_tuple = True) 函数返回长度为 2 的元组,元组中的每一个元素都是一个形状为 (3, ) 的 1D 张量 torch.tensor([0, 1, 1])
和 torch.tensor([1, 0, 1])
,元组中的每 1D 张量对应输入张量的一个维度,而每个 1D 张量的元素值分别对应输入张量中非零元素在对应维度上的索引,即 (torch.tensor([index_1_row, index_2_row, index_3_row]), torch.tensor([index_1_col, index_2_col, index_3_col]))
。
当 as_tuple = True 时的 nonzero 函数需要注意三点:
>>> import torch
>>> # 输入张量为2D张量
>>> input_2d = torch.tensor([[0, 1], [1, 2]])
>>> output_2d = torch.nonzero(input_2d, as_tuple = True)
>>> print(input_2d)
tensor([[0, 1],
[1, 2]])
>>> print(output_2d)
(tensor([0, 1, 1]), tensor([1, 0, 1]))
>>> # 使用高级索引索引输入张量中的非零元素
>>> # 通过索引元组获取其中的1D张量
>>> # output_2d[0] = tensor([0, 1, 1])
>>> # output_2d[1] = tensor([1, 0, 1])
>>> print(input_2d[output_2d[0], output_2d[1]])
tensor([1, 1, 2])
>>> import torch
>>> input_0d = torch.tensor(2)
>>> output_0d = torch.nonzero(input_0d, as_tuple = True)
>>> print(output_0d)
(tensor([0]),)
>>> input_1d = torch.tensor([2])
>>> output_1d = torch.nonzero(input_1d, as_tuple = True)
>>> print(output_1d)
(tensor([0]),)
>>> print(output_0d == output_1d)
True
本文分享自 AI机器学习与深度学习算法 微信公众号,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文参与 腾讯云自媒体同步曝光计划 ,欢迎热爱写作的你一起参与!