Python 如何从Pytorch中的单个图像中提取特征向量?

Python 如何从Pytorch中的单个图像中提取特征向量?,python,computer-vision,pytorch,feature-extraction,Python,Computer Vision,Pytorch,Feature Extraction,我正试图了解更多关于计算机视觉模型的知识,并试图探索它们是如何工作的。为了更好地理解如何解释特征向量,我尝试使用Pytorch来提取特征向量。下面是我从不同地方拼凑的代码 import torch import torch.nn as nn import torchvision.models as models import torchvision.transforms as transforms from torch.autograd import Variable from PIL impo

我正试图了解更多关于计算机视觉模型的知识,并试图探索它们是如何工作的。为了更好地理解如何解释特征向量,我尝试使用Pytorch来提取特征向量。下面是我从不同地方拼凑的代码

import torch
import torch.nn as nn
import torchvision.models as models
import torchvision.transforms as transforms
from torch.autograd import Variable
from PIL import Image



img=Image.open("Documents/01235.png")

# Load the pretrained model
model = models.resnet18(pretrained=True)

# Use the model object to select the desired layer
layer = model._modules.get('avgpool')

# Set model to evaluation mode
model.eval()

transforms = torchvision.transforms.Compose([
        torchvision.transforms.Resize(256),
        torchvision.transforms.CenterCrop(224),
        torchvision.transforms.ToTensor(),
        torchvision.transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),
    ])
    
def get_vector(image_name):
    # Load the image with Pillow library
    img = Image.open("Documents/Documents/Driven Data Competitions/Hateful Memes Identification/data/01235.png")
    # Create a PyTorch Variable with the transformed image
    t_img = transforms(img)
    # Create a vector of zeros that will hold our feature vector
    # The 'avgpool' layer has an output size of 512
    my_embedding = torch.zeros(512)
    # Define a function that will copy the output of a layer
    def copy_data(m, i, o):
        my_embedding.copy_(o.data)
    # Attach that function to our selected layer
    h = layer.register_forward_hook(copy_data)
    # Run the model on our transformed image
    model(t_img)
    # Detach our copy function from the layer
    h.remove()
    # Return the feature vector
    return my_embedding

pic_vector = get_vector(img)
当我执行此操作时,会出现以下错误:

RuntimeError: Expected 4-dimensional input for 4-dimensional weight [64, 3, 7, 7], but got 3-dimensional input of size [3, 224, 224] instead
我确信这是一个基本的错误,但我似乎不知道如何解决这个问题。我的印象是,totensor转换将使我的数据变成4-d,但它似乎要么工作不正常,要么我误解了它。感谢任何帮助或资源,我可以用来了解更多关于这一点

pytorch中的所有默认nn.模块都需要一个额外的批处理维度。如果模块的输入是形状B。。。然后输出为B。。。尽管后面的尺寸可能会根据图层的不同而变化。此行为允许同时对B批输入进行有效推断。为了使你的代码一致,你可以在t_img张量的前面加上一个幺正维,然后将它发送到你的模型中,使它成为1。。。张量。如果您想将层的输出复制到一维my_嵌入张量中,您还需要在存储它之前对其进行修改

还有几件事:

您应该在torch.no_grad上下文中进行推断,以避免计算渐变,因为您不需要它们注意model.eval只是更改某些层的行为,如退出和批处理规范化,它不会禁用计算图的构造,但torch.no_grad会禁用

我假设这只是一个复制粘贴问题,但transforms是导入模块的名称以及全局变量

o、 数据只是返回o的一个副本。在PyTorch 0.3.1和更早版本的旧变量接口中,这曾经是必要的,但变量接口早在PyTorch中就已经存在,不再做任何有用的事情;现在它的使用只会造成混乱。不幸的是,许多教程仍在使用这个旧的和不必要的界面编写

更新后的代码如下所示:

进口火炬 进口火炬视觉 将torchvision.models导入为模型 从PIL导入图像 img=Image.openDocuments/01235.png 加载预训练模型 model=models.resnet18pretrained=True 使用模型对象选择所需图层 层=模型。\u模块。获取“avgpool” 将模型设置为评估模式 模型评估 transforms=torchvision.transforms.Compose[ torchvision.transforms.Resize256, torchvision.transforms.CenterCrop224, torchvision.transforms.ToTensor, torchvision.transforms.Normalizemean=[0.485,0.456,0.406],标准=[0.229,0.224,0.225], ] def get_矢量图像: 用变换后的图像创建PyTorch张量 t_img=转换图像 创建一个包含零的向量,它将保存我们的特征向量 “avgpool”层的输出大小为512 my_嵌入=torch.zeros512 定义一个复制图层输出的函数 def复制_数据M、i、o:
非常感谢您的精彩解释。作为后续,我想知道如何最好地解释特征向量。我认为,向量中的每一个值都代表了关于图片的某些信息。有没有办法从resnet的文档中大致了解512个值中的每一个都在描述什么?我好像什么也找不到。作为推论,如果我在两个不同的图像上运行相同的过程,每个结果picu向量中的第一个值是否对应于相同的特征?如果这对于后续工作来说太多了,我理解,谢谢。这有点抽象,但简短的回答是否定的。该功能是输入图像在512维空间中的抽象表示。要素空间的主要特征是,如果比较来自相同类型对象的图像的要素,它们应该彼此靠近,而不同类型的对象将彼此远离。这一特点是网络培训目标的结果。此外,我们通常指的是余弦相似性接近1,到目前为止,我们指的是余弦相似性不接近1。特征中的单个值通常意义不大。例如,可以对特征空间应用任何刚性变换而不进行平移,并且特征之间仍然具有完全相同的余弦相似性,尽管这将完全更改特征向量的各个值。也就是说,有一些方法可以学习从特征向量中提取特定信息,但这通常需要学习与不同属性相关的特征的变换,这需要额外的训练。另一种看待它的方式是抽象层次。对于靠近输入的层,可能表示较低的l
水平概念,如线和边,向上移动一层或两层,也许它代表了一些东西,如角,再往前走一点,你会得到一些特征,这些特征代表了构建块,如轮子和砖块等等。最后,当您到达终点时,特征代表最终目标,在这种情况下,对象类,例如汽车、猫、人等……这更多的是一种解释,而不是一条硬性规则。目标函数中没有明确要求学习这种表示法的东西,但研究和实验表明,这是对正在发生的事情的合理解释。