特征图输出类型 Tensor或Tuple

Posted 一颗小树x

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了特征图输出类型 Tensor或Tuple相关的知识,希望对你有一定的参考价值。

前言

最近在修改网络模型时,发现有些特征图输出的类型是Tensor,有的特征图输出的类型却是Tuple,一开始不知到为什么是这样的,苦恼了半天,后来上网查询后发现了基本的规律,本文分享一下。

一、为什么特征图输出类型是Tensor或Tuple

在深度学习模型中,有些层或模块输出的特征图是一个张量(Tensor),而有些输出的是一个元组(Tuple)。这通常是由于模型的设计不同导致的。

模型输出的特征图可能是由多个Tensor组成的Tuple,也可能只是一个单独的Tensor。这取决于模型的设计和输出。

一些模型在输出时可能需要返回多个特征图,这些特征图会被打包成一个Tuple返回。

  • 对于输出为元组的模块,则通常表示模块的输出不止一个。这种情况下,通常需要使用元组的方式来保存不同的特征图。例如,在目标检测任务中,YOLOv3模型的输出是一个元组,其中包含3个张量,分别对应不同尺度下的检测结果。
  • 在物体检测模型中,模型可以输出包括目标类别、位置、置信度等信息的张量Tensor,以及一些中间特征图的张量Tensor,如特征金字塔。这两个Tensor张量通常被组合成一个元组返回,以便更容易地处理和分析输出。
  • 在图像分割任务中,模型可能需要同时预测目标掩模像素分类,因此输出将是一个Tuple,其中包含两个Tensor,分别表示掩模和分类结果。

二、特征图输出类型Tensor

这里写一个简单的示例程序,模型最终输出特征图类型是Tensor;

import torch
import torch.nn as nn

class SimpleModelTuple(nn.Module):
    def __init__(self):
        super(SimpleModelTuple, self).__init__()
        self.conv1 = nn.Conv2d(3, 16, kernel_size=3, padding=1)
        self.pool1 = nn.MaxPool2d(kernel_size=2, stride=2)
        self.conv2 = nn.Conv2d(16, 32, kernel_size=3, padding=1)
        self.pool2 = nn.MaxPool2d(kernel_size=2, stride=2)

    def forward(self, x):
        x = self.conv1(x)
        x = nn.functional.relu(x)
        x = self.pool1(x)
        x = self.conv2(x)
        x = nn.functional.relu(x)
        x = self.pool2(x)
        return (x) # 返回一个tensor

# 测试输出
model = SimpleModelTuple()
x = torch.randn(1, 3, 32, 32)
output = model(x)
print(type(output)) # 输出的类型是tensor
print(output)

这个程序中模型只有一个输出,通过常见的卷积层、池化层等,其输出是一个张量。

三、特征图输出类型Tuple

这里写一个简单的示例程序,模型最终输出特征图类型是Tuple,它由两个一样的Tensor组成;

import torch
import torch.nn as nn

class SimpleModelTuple(nn.Module):
    def __init__(self):
        super(SimpleModelTuple, self).__init__()
        self.conv1 = nn.Conv2d(3, 16, kernel_size=3, padding=1)
        self.pool1 = nn.MaxPool2d(kernel_size=2, stride=2)
        self.conv2 = nn.Conv2d(16, 32, kernel_size=3, padding=1)
        self.pool2 = nn.MaxPool2d(kernel_size=2, stride=2)

    def forward(self, x):
        x = self.conv1(x)
        x = nn.functional.relu(x)
        x = self.pool1(x)
        x = self.conv2(x)
        x = nn.functional.relu(x)
        x = self.pool2(x)
        return (x,x) # 返回两个一样的tensor结果

# 测试输出
model = SimpleModelTuple()
x = torch.randn(1, 3, 32, 32)
output = model(x)
print(type(output)) # 输出的类型是tuple
print(output)

这里再写一个简单的示例程序,模型最终输出特征图类型是Tuple,它由两Tensor组成;

  • 一个Tensor是只进行了一次卷积、激活、池化操作,对应特征图x1;
  • 另一个Tensor是只进行了两次卷积、激活、池化操作,对应特征图x2;
import torch
import torch.nn as nn

class SimpleModelTuple(nn.Module):
    def __init__(self):
        super(SimpleModelTuple, self).__init__()
        self.conv1 = nn.Conv2d(3, 16, kernel_size=3, padding=1)
        self.pool1 = nn.MaxPool2d(kernel_size=2, stride=2)
        self.conv2 = nn.Conv2d(16, 32, kernel_size=3, padding=1)
        self.pool2 = nn.MaxPool2d(kernel_size=2, stride=2)

    def forward(self, x):
        x1 = self.conv1(x)
        x1 = nn.functional.relu(x1)
        x1 = self.pool1(x)

        x2 = self.conv2(x1)
        x2 = nn.functional.relu(x2)
        x2 = self.pool2(x2)
        return (x1,x2) # 返回两个不同的tensor结果

# 测试输出
model = SimpleModelTuple()
x = torch.randn(1, 3, 32, 32)
output = model(x)
print(type(output)) # 输出的类型是tuple
print(output)

小结一下:

在深度学习模型中,有些层或模块输出的特征图是一个张量(Tensor),而有些输出的是一个元组(Tuple)。这通常是由于模型的设计不同导致的。

模型输出的特征图可能是由多个Tensor组成的Tuple,也可能只是一个单独的Tensor。这取决于模型的设计和输出。

一些模型在输出时可能需要返回多个特征图,这些特征图会被打包成一个Tuple返回。

  • 对于输出为元组的模块,则通常表示模块的输出不止一个。这种情况下,通常需要使用元组的方式来保存不同的特征图。例如,在目标检测任务中,YOLOv3模型的输出是一个元组,其中包含3个张量,分别对应不同尺度下的检测结果。
  • 在物体检测模型中,模型可以输出包括目标类别、位置、置信度等信息的张量Tensor,以及一些中间特征图的张量Tensor,如特征金字塔。这两个Tensor张量通常被组合成一个元组返回,以便更容易地处理和分析输出。
  • 在图像分割任务中,模型可能需要同时预测目标掩模像素分类,因此输出将是一个Tuple,其中包含两个Tensor,分别表示掩模和分类结果。

分享完成,继续改网络结构啦~

以上是关于特征图输出类型 Tensor或Tuple的主要内容,如果未能解决你的问题,请参考以下文章

DGL的图数据结构的创建图的特征dgl.batch及一些理解

如何将输出特征图保存在“转发”功能中?

R语言dataframe获取每个字段(特征)的数据类型实战:使用sapply函数获取每个字段(特征)的数据类型通过柱状图可视化特征的种类以及个数

语义分割PointRend

Python 数据可视化:分类特征统计图

nn.ConvTranspose2d的参数output_padding的作用(转)