当前位置:网站首页>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
边栏推荐
- typeScript - Partially apply a function
- Implementation principle of golang coroutine
- mysql基础
- 电赛必备技能___定时ADC+DMA+串口通信
- 对写作的一些感悟
- Develop a SpaceX website based on the Appian low-code platform
- Mathematical Principles of Matrix
- 性能测试如何准备测试数据
- 怎么将自己新文章自动推送给自己的粉丝(巨简单,学不会来打我)
- After another 3 days, I have sorted out 90 NumPy examples, and I can't help but bookmark it!
猜你喜欢
随机推荐
【CVA估值训练营】财务建模指南——第一讲
关于我仔细检查审核过关于工作人员页面,返回一个所属行业问题
【七夕情人节特效】-- canvas实现满屏爱心
First, the basic concept of reptiles
leetcode:269. 火星词典
GO中sync包自由控制并发的方法
Flutter启动流程(Skia引擎)介绍与使用
KT148A电子语音芯片ic方案适用的场景以及常见产品类型
Couple Holding Hands [Greedy & Abstract]
大师教你3D实时角色制作流程,游戏建模流程分享
三、实战---爬取百度指定词条所对应的结果页面(一个简单的页面采集器)
2022 Niu Ke Summer Multi-School Training Camp 5 (BCDFGHK)
建模师经验分享:模型学习方法
标识符、关键字、常量 和变量(C语言)
E - Many Operations (按位考虑 + dp思想记录操作后的结果
QSunSync 七牛云文件同步工具,批量上传
jenkins send mail system configuration
Huggingface入门篇 II (QA)
leetcode经典例题——单词拆分
【无标题】








