当前位置:网站首页>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
边栏推荐
猜你喜欢

2022 Niu Ke Summer Multi-School Training Camp 5 (BCDFGHK)

Three tips for you to successfully get started with 3D modeling

【云原生--Kubernetes】调度约束

大师教你3D实时角色制作流程,游戏建模流程分享

学会反射后,我被录取了(干货)

jenkins send mail system configuration

从单体架构迁移到 CQRS 后,我觉得 DDD 并不可怕
![[LeetCode] Summary of Matrix Simulation Related Topics](/img/80/bd71ca5211cce5805909015a642893.jpg)
[LeetCode] Summary of Matrix Simulation Related Topics

性能测试如何准备测试数据
![[CVA Valuation Training Camp] Financial Modeling Guide - Lecture 1](/img/8b/360df9a9094037dc358cb21c60cdc8.png)
[CVA Valuation Training Camp] Financial Modeling Guide - Lecture 1
随机推荐
建模师经验分享:模型学习方法
Some thoughts on writing
Mysql based
.net(C#)获取两个日期间隔的年月日
KT6368A蓝牙的认证问题_FCC和BQB_CE_KC认证或者其它说明
10 个关于 Promise 和 setTimeout 知识的面试题,通过图解一次说透彻
一、爬虫基本概念
图解 Canvas 入门
leetcode:266. 回文全排列
Cloud native - Kubernetes 】 【 scheduling constraints
[Happy Qixi Festival] How does Nacos realize the service registration function?
【Unity编译器扩展之进度条】
golang 协程的实现原理
Chinese and Japanese color style
关于我仔细检查审核过关于工作人员页面,返回一个所属行业问题
[230]连接Redis后执行命令错误 MISCONF Redis is configured to save RDB snapshots
【云原生--Kubernetes】Pod控制器
在线中文姓名生成工具推荐
The role of the annotation @ EnableAutoConfiguration and how to use
STC89C52RC的P4口的应用问题