当前位置:网站首页>tensor.nozero(), mask, [mask]
tensor.nozero(), mask, [mask]
2022-08-05 00:15:00 【Le0v1n】
1. nozero()
https://pytorch.org/docs/stable/generated/torch.nonzero.html?highlight=nonzero#torch.nonzero
torch.nonzero(input, *, out=None, as_tuple=False) → LongTensor or tuple of LongTensors
torch.nonzero(..., as_tuple=False) (default)returns a2-Dtensor where each row is the index for a nonzero value.torch.nonzero(..., as_tuple=False) (默认)返回一个2-D张量,其中每一行是一个非零值的索引。
tensor.nozero()默认返回一个2维的tensor, 里面是符合条件的索引.
举个例子:
import torch
x = torch.randint(low=2, high=3, size=[2, 3])
idx = x.nonzero()
print(f"x:\n{
x}\n")
print(f"idx:\n{
idx}\n")
print(f"x.size: {
x.size()}")
print(f"idx.size: {
idx.size()}")
结果:
x:
tensor([[2, 2, 2],
[2, 2, 2]])
idx:
tensor([[0, 0],
[0, 1],
[0, 2],
[1, 0],
[1, 1],
[1, 2]])
x.size: torch.Size([2, 3])
idx.size: torch.Size([6, 2])
可以看到, 这里的idx是用2-D tensor来表示x中符合条件元素的索引.
因为
x有两个维度, 所以idx中的size()[1]也是2
如果输入是多维的tensor, 那么表示也只会用2-D的tensor. 例子如下:
import torch
x = torch.randint(low=2, high=3, size=[2, 3, 4])
idx = x.nonzero()
print(f"x:\n{
x}\n")
print(f"idx:\n{
idx}\n")
print(f"x.size: {
x.size()}")
print(f"idx.size: {
idx.size()}")
结果:
x:
tensor([[[2, 2, 2, 2],
[2, 2, 2, 2],
[2, 2, 2, 2]],
[[2, 2, 2, 2],
[2, 2, 2, 2],
[2, 2, 2, 2]]])
idx:
tensor([[0, 0, 0],
[0, 0, 1],
[0, 0, 2],
[0, 0, 3],
[0, 1, 0],
[0, 1, 1],
[0, 1, 2],
[0, 1, 3],
[0, 2, 0],
[0, 2, 1],
[0, 2, 2],
[0, 2, 3],
[1, 0, 0],
[1, 0, 1],
[1, 0, 2],
[1, 0, 3],
[1, 1, 0],
[1, 1, 1],
[1, 1, 2],
[1, 1, 3],
[1, 2, 0],
[1, 2, 1],
[1, 2, 2],
[1, 2, 3]])
x.size: torch.Size([2, 3, 4])
idx.size: torch.Size([24, 3])
因为
x有3个维度, 所以idx中的size()[1]也是3
再举个例子:
import torch
x = torch.randint(low=2, high=3, size=[2, 3, 4, 2])
idx = x.nonzero()
print(f"x:\n{
x}\n")
print(f"idx:\n{
idx}\n")
print(f"x.size: {
x.size()}")
print(f"idx.size: {
idx.size()}")
结果:
x:
tensor([[[[2, 2],
[2, 2],
[2, 2],
[2, 2]],
[[2, 2],
[2, 2],
[2, 2],
[2, 2]],
[[2, 2],
[2, 2],
[2, 2],
[2, 2]]],
[[[2, 2],
[2, 2],
[2, 2],
[2, 2]],
[[2, 2],
[2, 2],
[2, 2],
[2, 2]],
[[2, 2],
[2, 2],
[2, 2],
[2, 2]]]])
idx:
tensor([[0, 0, 0, 0],
[0, 0, 0, 1],
[0, 0, 1, 0],
[0, 0, 1, 1],
[0, 0, 2, 0],
[0, 0, 2, 1],
[0, 0, 3, 0],
[0, 0, 3, 1],
[0, 1, 0, 0],
[0, 1, 0, 1],
[0, 1, 1, 0],
[0, 1, 1, 1],
[0, 1, 2, 0],
[0, 1, 2, 1],
[0, 1, 3, 0],
[0, 1, 3, 1],
[0, 2, 0, 0],
[0, 2, 0, 1],
[0, 2, 1, 0],
[0, 2, 1, 1],
[0, 2, 2, 0],
[0, 2, 2, 1],
[0, 2, 3, 0],
[0, 2, 3, 1],
[1, 0, 0, 0],
[1, 0, 0, 1],
[1, 0, 1, 0],
[1, 0, 1, 1],
[1, 0, 2, 0],
[1, 0, 2, 1],
[1, 0, 3, 0],
[1, 0, 3, 1],
[1, 1, 0, 0],
[1, 1, 0, 1],
[1, 1, 1, 0],
[1, 1, 1, 1],
[1, 1, 2, 0],
[1, 1, 2, 1],
[1, 1, 3, 0],
[1, 1, 3, 1],
[1, 2, 0, 0],
[1, 2, 0, 1],
[1, 2, 1, 0],
[1, 2, 1, 1],
[1, 2, 2, 0],
[1, 2, 2, 1],
[1, 2, 3, 0],
[1, 2, 3, 1]])
x.size: torch.Size([2, 3, 4, 2])
idx.size: torch.Size([48, 4])
因为
x有4个维度, 所以idx中的size()[1]也是4
终于, 我们可以发现结论了:
tensor.nozero()默认返回的是一个2-Dtensor, 行表示非零元素的索引, 列的大小 = 输入tensor维度的数量
2. mask
在手撸YOLOv3时, 需要写mask, 一般是根据置信度是否大于阈值来判断是否为正样本:
- ≥ thresh: 张样本
- < thresh: 负样本
在YOLOv3中, 网络的前向推理结果一般为 [N, H, W, 3, 8], 其中:
N: batch sizeH: heightW: weight3: 3种预测尺度8: conf + loc + cls = 1 + 4 + 3
为了能够取到置信度conf, 因此output[..., 0], 由此就可以得到mask:
output = net(input) # [N, H, W, 3, 8]
mask = output[..., 0] > thresh # [N, H, W, 3]
那么问题来了: 为什么得到的mask的size为[N, H, W, 3]呢?
我们讲一下mask这样的取法究竟是在做什么.
import torch
x = torch.randint(low=2, high=3, size=[2, 3])
mask = x[..., 0] > 1 # 最后一个维度中的第一个元素如果大于1, 则前面的维度返回True, 否则返回False
print(f"x:\n{
x}\n")
print(f"x[..., 0]:\n{
x[..., 0]}\n")
print(f"x[..., 0].size:\n{
x[..., 0].size()}\n")
print(f"mask:\n{
mask}\n")
print(f"mask.size:\n{
mask.size()}\n")
x:
tensor([[2, 2, 2],
[2, 2, 2]])
x[..., 0]:
tensor([2, 2])
x[..., 0].size:
torch.Size([2])
mask:
tensor([True, True])
mask.size:
torch.Size([2])
或许这样看还不够明显, 那么我们将x的值修改一下:
import torch
x = torch.tensor(data=[[0, 2, 2],
[0, 2, 2]], dtype=torch.int8)
mask = x[..., 0] > 1 # 最后一个维度中的第一个元素如果大于1, 则前面的维度返回True, 否则返回False
print(f"x:\n{
x}\n")
print(f"x[..., 0]:\n{
x[..., 0]}\n")
print(f"x[..., 0].size:\n{
x[..., 0].size()}\n")
print(f"mask:\n{
mask}\n")
print(f"mask.size:\n{
mask.size()}\n")
结果:
x:
tensor([[0, 2, 2],
[0, 2, 2]], dtype=torch.int8)
x[..., 0]:
tensor([0, 0], dtype=torch.int8)
x[..., 0].size:
torch.Size([2])
mask:
tensor([False, False])
mask.size:
torch.Size([2])
看起来, 这个函数取的是第一列(这里的描述并不准确). 那么我们在将x的维度扩充一下看看:
import torch
x = torch.randint(low=0, high=3, size=[2, 3, 2])
mask = x[..., 0] > 1 # 最后一个维度中的第一个元素如果大于1, 则前面的维度返回True, 否则返回False
print(f"x:\n{
x}\n")
print(f"x[..., 0]:\n{
x[..., 0]}\n")
print(f"x[..., 0].size:\n{
x[..., 0].size()}\n")
print(f"mask:\n{
mask}\n")
print(f"mask.size:\n{
mask.size()}\n")
结果:
x:
tensor([[[2, 1],
[2, 1],
[1, 0]],
[[2, 0],
[1, 2],
[0, 0]]])
x[..., 0]:
tensor([[2, 2, 1],
[2, 1, 0]])
x[..., 0].size:
torch.Size([2, 3])
mask:
tensor([[ True, True, False],
[ True, False, False]])
mask.size:
torch.Size([2, 3])
结论仍然是对的, 我们再将x扩充至 [N, H, W, 3]:
import torch
x = torch.randint(low=0, high=3, size=[2, 3, 2, 1])
mask = x[..., 0] > 1 # 最后一个维度中的第一个元素如果大于1, 则前面的维度返回True, 否则返回False
print(f"x:\n{
x}\n")
print(f"x[..., 0]:\n{
x[..., 0]}\n")
print(f"x[..., 0].size:\n{
x[..., 0].size()}\n")
print(f"mask:\n{
mask}\n")
print(f"mask.size:\n{
mask.size()}\n")
x:
tensor([[[[0],
[0]],
[[0],
[1]],
[[2],
[2]]],
[[[1],
[2]],
[[2],
[2]],
[[2],
[2]]]])
x[..., 0]:
tensor([[[0, 0],
[0, 1],
[2, 2]],
[[1, 2],
[2, 2],
[2, 2]]])
x[..., 0].size:
torch.Size([2, 3, 2])
mask:
tensor([[[False, False],
[False, False],
[ True, True]],
[[False, True],
[ True, True],
[ True, True]]])
mask.size:
torch.Size([2, 3, 2])
结论是对的.
3. [mask]
上面我们分析了mask究竟是在取什么, 那么将mask应用到x中(x[mask])会是怎么样的呢?
import torch
x = torch.randint(low=0, high=3, size=[2, 3])
mask = x[..., 0] > 1 # 最后一个维度中的第一个元素如果大于1, 则前面的维度返回True, 否则返回False
filtered_x = x[mask]
print(f"x:\n{
x}\n")
print(f"x.size:\n{
x.size()}\n")
print("-" * 50)
print(f"x[..., 0]:\n{
x[..., 0]}\n")
print(f"x[..., 0].size:\n{
x[..., 0].size()}\n")
print("-" * 50)
print(f"mask:\n{
mask}\n")
print(f"mask.size:\n{
mask.size()}\n")
print("-" * 50)
print(f"filtered_x:\n{
filtered_x}\n")
print(f"filtered_x.size:\n{
filtered_x.size()}\n")
结果2:
x:
tensor([[2, 2, 1],
[0, 0, 2]])
x.size:
torch.Size([2, 3])
--------------------------------------------------
x[..., 0]:
tensor([2, 0])
x[..., 0].size:
torch.Size([2])
--------------------------------------------------
mask:
tensor([ True, False])
mask.size:
torch.Size([2])
--------------------------------------------------
filtered_x:
tensor([[2, 2, 1]])
filtered_x.size:
torch.Size([1, 3])
mask负责筛选"列", x[mask]负责取出符合条件的行, 且这个行是一个2D tensor.
结果2:
x:
tensor([[0, 1, 0],
[1, 0, 0]])
x.size:
torch.Size([2, 3])
--------------------------------------------------
x[..., 0]:
tensor([0, 1])
x[..., 0].size:
torch.Size([2])
--------------------------------------------------
mask:
tensor([False, False])
mask.size:
torch.Size([2])
--------------------------------------------------
filtered_x:
tensor([], size=(0, 3), dtype=torch.int64)
filtered_x.size:
torch.Size([0, 3])
mask负责筛选"列", x[mask]负责取出符合条件的行, 且这个行是一个2D tensor.
我们将x的维度提升:
import torch
x = torch.randint(low=0, high=3, size=[2, 3, 2])
mask = x[..., 0] > 1 # 最后一个维度中的第一个元素如果大于1, 则前面的维度返回True, 否则返回False
filtered_x = x[mask]
print(f"x:\n{
x}\n")
print(f"x.size:\n{
x.size()}\n")
print("-" * 50)
print(f"x[..., 0]:\n{
x[..., 0]}\n")
print(f"x[..., 0].size:\n{
x[..., 0].size()}\n")
print("-" * 50)
print(f"mask:\n{
mask}\n")
print(f"mask.size:\n{
mask.size()}\n")
print("-" * 50)
print(f"filtered_x:\n{
filtered_x}\n")
print(f"filtered_x.size:\n{
filtered_x.size()}\n")
结果1:
x:
tensor([[[0, 2],
[0, 2],
[0, 2]],
[[2, 2],
[1, 0],
[1, 2]]])
x.size:
torch.Size([2, 3, 2])
--------------------------------------------------
x[..., 0]:
tensor([[0, 0, 0],
[2, 1, 1]])
x[..., 0].size:
torch.Size([2, 3])
--------------------------------------------------
mask:
tensor([[False, False, False],
[ True, False, False]])
mask.size:
torch.Size([2, 3])
--------------------------------------------------
filtered_x:
tensor([[2, 2]])
filtered_x.size:
torch.Size([1, 2])
结果2:
x:
tensor([[[1, 0],
[2, 0],
[2, 1]],
[[2, 0],
[2, 0],
[2, 1]]])
x.size:
torch.Size([2, 3, 2])
--------------------------------------------------
x[..., 0]:
tensor([[1, 2, 2],
[2, 2, 2]])
x[..., 0].size:
torch.Size([2, 3])
--------------------------------------------------
mask:
tensor([[False, True, True],
[ True, True, True]])
mask.size:
torch.Size([2, 3])
--------------------------------------------------
filtered_x:
tensor([[2, 0],
[2, 1],
[2, 0],
[2, 0],
[2, 1]])
filtered_x.size:
torch.Size([5, 2])
我们可以发现, 结论 mask负责筛选"列", x[mask]负责取出符合条件的行, 且这个行是一个2D tensor 依然是符合的, 我们再扩充一下维度:
import torch
x = torch.randint(low=0, high=3, size=[2, 3, 2, 2])
mask = x[..., 0] > 1 # 最后一个维度中的第一个元素如果大于1, 则前面的维度返回True, 否则返回False
filtered_x = x[mask]
print(f"x:\n{
x}\n")
print(f"x.size:\n{
x.size()}\n")
print("-" * 50)
print(f"x[..., 0]:\n{
x[..., 0]}\n")
print(f"x[..., 0].size:\n{
x[..., 0].size()}\n")
print("-" * 50)
print(f"mask:\n{
mask}\n")
print(f"mask.size:\n{
mask.size()}\n")
print("-" * 50)
print(f"filtered_x:\n{
filtered_x}\n")
print(f"filtered_x.size:\n{
filtered_x.size()}\n")
结果1:
x:
tensor([[[[0, 0],
[0, 1]],
[[1, 1],
[0, 0]],
[[0, 1],
[2, 1]]],
[[[2, 2],
[0, 1]],
[[0, 2],
[0, 2]],
[[0, 0],
[2, 2]]]])
x.size:
torch.Size([2, 3, 2, 2])
--------------------------------------------------
x[..., 0]:
tensor([[[0, 0],
[1, 0],
[0, 2]],
[[2, 0],
[0, 0],
[0, 2]]])
x[..., 0].size:
torch.Size([2, 3, 2])
--------------------------------------------------
mask:
tensor([[[False, False],
[False, False],
[False, True]],
[[ True, False],
[False, False],
[False, True]]])
mask.size:
torch.Size([2, 3, 2])
--------------------------------------------------
filtered_x:
tensor([[2, 1],
[2, 2],
[2, 2]])
filtered_x.size:
torch.Size([3, 2])
结果2:
x:
tensor([[[[2, 2],
[2, 2]],
[[1, 0],
[0, 2]],
[[0, 2],
[2, 2]]],
[[[0, 0],
[1, 0]],
[[1, 1],
[0, 1]],
[[2, 1],
[1, 0]]]])
x.size:
torch.Size([2, 3, 2, 2])
--------------------------------------------------
x[..., 0]:
tensor([[[2, 2],
[1, 0],
[0, 2]],
[[0, 1],
[1, 0],
[2, 1]]])
x[..., 0].size:
torch.Size([2, 3, 2])
--------------------------------------------------
mask:
tensor([[[ True, True],
[False, False],
[False, True]],
[[False, False],
[False, False],
[ True, False]]])
mask.size:
torch.Size([2, 3, 2])
--------------------------------------------------
filtered_x:
tensor([[2, 2],
[2, 2],
[2, 2],
[2, 1]])
filtered_x.size:
torch.Size([4, 2])
结论依然存在!
4. 结论
到现在我们终于明白了,
output = net(input) # [N, H, W, 3, 8]
mask = output[..., 0] > thresh # [N, H, W, 3]
mask: 取出的是符合条件的列 (判断用的维度就消失了, 所以[N, H, W, 3, 8]->[N, H, W, 3])output[mask]: 取出符合条件的行 (是一个2-Dtensor)
举个例子:
def get_idx_and_info(self, output, thresh):
output = output.permute(0, 2, 3, 1) # [N, 24, H, W] -> [N, H, W, 3*8]
N, H, W, _ = output.size()
output = output.reshape(N, H, W, 3, -1) # N, H, W, 24] -> N, H, W, 3, 8]
# 定义掩码(符合条件的行)
mask = output[..., 0] > thresh # 置信度 > thresh # [N, H, W, 3] (这里应该是自动squeeze了)
idx = mask.nonzero() # size -> [符合条件数的个数, 4] # 因为mask的维度个数有4个, 所以这里是4,
info = output[mask] # size -> [符合条件数的个数, 8] # 8 = c + loc + cls
return idx, info
边栏推荐
- [Happy Qixi Festival] How does Nacos realize the service registration function?
- After another 3 days, I have sorted out 90 NumPy examples, and I can't help but bookmark it!
- Cython
- Mysql_12 多表查询
- leetcode:269. 火星词典
- 00、数组及字符串常用的 API(详细剖析)
- 游戏3D建模入门,有哪些建模软件可以选择?
- matlab中rcosdesign函数升余弦滚降成型滤波器
- 统计单词(DAY 101)华中科技大学考研机试题
- 【LeetCode】矩阵模拟相关题目汇总
猜你喜欢
随机推荐
LeetCode Hot 100
MAUI Blazor 权限经验分享 (定位,使用相机)
KT148A语音芯片怎么烧录语音进入芯片里面通过串口和电脑端的工具
Cython
MongoDB权限验证开启与mongoose数据库配置
什么是次世代建模(附学习资料)
【七夕情人节特效】-- canvas实现满屏爱心
KT6368A蓝牙的认证问题_FCC和BQB_CE_KC认证或者其它说明
统计单词(DAY 101)华中科技大学考研机试题
Mysql based
怎样进行在不改变主线程执行的时候,进行日志的记录
redis可视化管理软件Redis Desktop Manager2022
Senior game modelers tell newbies, what are the necessary software for game scene modelers?
翁恺C语言程序设计网课笔记合集
Basic web in PLSQL
如何写好测试用例
Security software Avast and Symantec NortonLifeLock merge with UK approval, market value soars 43%
The master teaches you the 3D real-time character production process, the game modeling process sharing
软件质量评估的通用模型
【云原生--Kubernetes】Pod控制器









