Pytorch学习笔记(III)——提取特征

2023-11-18

一、引言

  深度学习在许多任务中主要充当着特征学习的作用,而学习完的特征才是后续应用的一个关键。本文将主要介绍,如何提取任意目标层的特征图。
  本文以输入数据为图片为例。

二、具体步骤

1、参数模型

博主使用了ResNet50训练了一个人脸识别的网络

  训练完成的深度学习模型,我们会保存一个参数文件,文件中保存的是前期训练过的网络模型参数,如下图:

在这里插入图片描述

2、网络结构

  提取特征的时候又要分为两种情况,一种是只提取一层特征,另一种是提取多层特征。
一层特征:
  在提取一层特征的时候,我们不需要完整的网络结构,只需要在forward的时候截止到我们想要的那一层为止。从下述代码可以看到,我注释了fclass2这一层,因为这一层是在训练的时候用来计算损失,并不是我想要的。
所以我提取的是fclass1这一层的特征

class CNN(nn.Module):

    def __init__(self, block, layers, num_classes=10000):
        self.inplanes = 64
        super(CNN, self).__init__()
        self.conv1 = nn.Conv2d(3, 64, kernel_size=7, stride=2, padding=3,
                               bias=False)
        self.bn1 = nn.BatchNorm2d(64)
        self.relu = nn.ReLU(inplace=True)
        self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1)
        self.layer1 = self._make_layer(block, 64, layers[0])
        self.layer2 = self._make_layer(block, 128, layers[1], stride=2)
        self.layer3 = self._make_layer(block, 256, layers[2], stride=2)
        self.layer4 = self._make_layer(block, 512, layers[3], stride=2)
        self.avgpool = nn.AdaptiveAvgPool2d(output_size=(1,1))
        self.fclass1 = nn.Linear(2048, 199)
        # self.fclass2 = nn.Linear(199, num_classes)

        for m in self.modules():
            if isinstance(m, nn.Conv2d):
                n = m.kernel_size[0] * m.kernel_size[1] * m.out_channels
                m.weight.data.normal_(0, math.sqrt(2. / n))
            elif isinstance(m, nn.BatchNorm2d):
                m.weight.data.fill_(1)
                m.bias.data.zero_()

    def _make_layer(self, block, planes, blocks, stride=1):
        downsample = None
        if stride != 1 or self.inplanes != planes * block.expansion:
            downsample = nn.Sequential(
                nn.Conv2d(self.inplanes, planes * block.expansion,
                            kernel_size=1, stride=stride, bias=False),
                nn.BatchNorm2d(planes * block.expansion),
            )

        layers = []
        layers.append(block(self.inplanes, planes, stride, downsample))
        self.inplanes = planes * block.expansion
        for i in range(1, blocks):
            layers.append(block(self.inplanes, planes))

        return nn.Sequential(*layers)

    def forward(self, x):
        x = self.conv1(x)
        x = self.bn1(x)
        x = self.relu(x)
        x = self.maxpool(x)
        x = self.layer1(x)
        x = self.layer2(x)
        x = self.layer3(x)
        x = self.layer4(x)
        x = self.avgpool(x)
        x = x.view(x.size(0), -1)

        x = self.fclass1(x)
        # x = self.fclass2(x)

        return x

多层特征:
  多层特征其实只要在forward的时候,return出不同层的值就可以了,具体就不多说了

3、参数载入

  其实这一步和我之前博客写的差不多,就是将.pkl文件中的网络参数,载入到本实验的程序中,不明白的地方,可以看之前的博客。

cnn = CNN(Bottleneck, [3, 4, 6, 3])
pretrained_dict = torch.load('/model/recognition/res50_net_params_253.pkl')
model1_dict = cnn.state_dict()
pretrained_dict = {k: v for k, v in pretrained_dict.items() if k in model1_dict}
model1_dict.update(pretrained_dict)
cnn.load_state_dict(model1_dict)
cnn = cnn.cuda()

4、特征提取器

  准备工作做完之后,我们就要设计一个特征提取器了,我是写成了子程序的形式,你也可以直接写在主程序中。

## 这段代码,一次只处理一张图片。img_path为图片的路径,save_path是特征保存的npy文件的路径,net就是我们的网络了
def extractors(img_path, sava_path, net):
#在上一篇博客有提到,pytorch处理的数据一定要是tensor的形式,所以transform就是将图片转为tensor,必须加,加多少看需要
    transform = transforms.Compose([
        # transforms.Resize(256),
        # transforms.CenterCrop(224),
        transforms.ToTensor()]
    )
    img = Image.open(img_path)
    img = transform(img)
    #在训练的时候,数据的第一维代表的是batch_size,虽然我们这里只处理一张图,但是维度必须和原来保持一致,即下面这一行
    x = Variable(torch.unsqueeze(img, dim=0).float(), requires_grad=False)
    x = x.cuda()
    y = net(x)
    y = torch.squeeze(y)
    #由于numpy的操作是在cpu上进行的,本博客的网络都是用GPU处理的,所以需要将tensor从GPU转至CPU再变成numpy的形式进行保存
    y = y.cpu().detach().numpy()
    np.save(save_path, y)
    ##如果是保存图片,
    # unloader = transforms.ToPILImage()
    # image = y.cpu().clone()
    # image = image.squeeze(0)
    # image = unloader(image)
    # image.save(save_path)

5、读取图片

  这一步就没那么多讲究了,就按照你图片的存放方式去读取就好了。主要就是别忘了保存路径。

data_dir = '/faceSD/S/'
fea_dir = '/faceSDfea/S/'
data_list = os.listdir(data_dir)

for i in range(len(data_list)):
    group_dir = data_dir + data_list[i] + '/'
    group_list = os.listdir(group_dir)
    save_dir = fea_dir + data_list[i] + '/'
    if os.path.exists(save_dir) == False:
        os.makedirs(save_dir)
    for j in range(2):
        img_path = group_dir + group_list[j]
        save_path = save_dir + group_list[j][0:-3] + 'npy'
        extractors(img_path,save_path,cnn)

三、完整代码

import torch
import torch.nn as nn
from torch.autograd import Variable
from torchvision import models, transforms
from PIL import Image
import numpy as np
import os, glob
import math
os.environ["CUDA_VISIBLE_DEVICES"] = "2"

class Bottleneck(nn.Module):
    expansion = 4

    def __init__(self, inplanes, planes, stride=1, downsample=None):
        super(Bottleneck, self).__init__()
        self.conv1 = nn.Conv2d(inplanes, planes, kernel_size=1, bias=False)
        self.bn1 = nn.BatchNorm2d(planes)
        self.conv2 = nn.Conv2d(planes, planes, kernel_size=3, stride=stride,
                               padding=1, bias=False)
        self.bn2 = nn.BatchNorm2d(planes)
        self.conv3 = nn.Conv2d(planes, planes * 4, kernel_size=1, bias=False)
        self.bn3 = nn.BatchNorm2d(planes * 4)
        self.relu = nn.ReLU(inplace=True)
        self.downsample = downsample
        self.stride = stride

    def forward(self, x):
        residual = x

        out = self.conv1(x)
        out = self.bn1(out)
        out = self.relu(out)

        out = self.conv2(out)
        out = self.bn2(out)
        out = self.relu(out)

        out = self.conv3(out)
        out = self.bn3(out)

        if self.downsample is not None:
            residual = self.downsample(x)

        out += residual
        out = self.relu(out)

        return out
class CNN(nn.Module):

    def __init__(self, block, layers, num_classes=10000):
        self.inplanes = 64
        super(CNN, self).__init__()
        self.conv1 = nn.Conv2d(3, 64, kernel_size=7, stride=2, padding=3,
                               bias=False)
        self.bn1 = nn.BatchNorm2d(64)
        self.relu = nn.ReLU(inplace=True)
        self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1)
        self.layer1 = self._make_layer(block, 64, layers[0])
        self.layer2 = self._make_layer(block, 128, layers[1], stride=2)
        self.layer3 = self._make_layer(block, 256, layers[2], stride=2)
        self.layer4 = self._make_layer(block, 512, layers[3], stride=2)
        self.avgpool = nn.AdaptiveAvgPool2d(output_size=(1,1))
        self.fclass1 = nn.Linear(2048, 199)
        # self.fclass2 = nn.Linear(199, num_classes)

        for m in self.modules():
            if isinstance(m, nn.Conv2d):
                n = m.kernel_size[0] * m.kernel_size[1] * m.out_channels
                m.weight.data.normal_(0, math.sqrt(2. / n))
            elif isinstance(m, nn.BatchNorm2d):
                m.weight.data.fill_(1)
                m.bias.data.zero_()

    def _make_layer(self, block, planes, blocks, stride=1):
        downsample = None
        if stride != 1 or self.inplanes != planes * block.expansion:
            downsample = nn.Sequential(
                nn.Conv2d(self.inplanes, planes * block.expansion,
                            kernel_size=1, stride=stride, bias=False),
                nn.BatchNorm2d(planes * block.expansion),
            )

        layers = []
        layers.append(block(self.inplanes, planes, stride, downsample))
        self.inplanes = planes * block.expansion
        for i in range(1, blocks):
            layers.append(block(self.inplanes, planes))

        return nn.Sequential(*layers)

    def forward(self, x):
        x = self.conv1(x)
        x = self.bn1(x)
        x = self.relu(x)
        x = self.maxpool(x)

        x = self.layer1(x)
        x = self.layer2(x)
        x = self.layer3(x)
        x = self.layer4(x)

        x = self.avgpool(x)
        x = x.view(x.size(0), -1)

        x = self.fclass1(x)
        # x = self.fclass2(x)

        return x
#载入模型参数
cnn = CNN(Bottleneck, [3, 4, 6, 3])
pretrained_dict = torch.load('/model/recognition/res50_net_params_253.pkl')
model1_dict = cnn.state_dict()
pretrained_dict = {k: v for k, v in pretrained_dict.items() if k in model1_dict}
model1_dict.update(pretrained_dict)
cnn.load_state_dict(model1_dict)
cnn = cnn.cuda()
##################################################################################################################
def extractors(img_path, sava_path, net):
    transform = transforms.Compose([
        # transforms.Resize(256),
        # transforms.CenterCrop(224),
        transforms.ToTensor()]
    )
    img = Image.open(img_path)
    img = transform(img)
    # print(img.shape)
    x = Variable(torch.unsqueeze(img, dim=0).float(), requires_grad=False)
    # print(x.shape)
    x = x.cuda()

    y = net(x)
    y = torch.squeeze(y)
    y = y.cpu().detach().numpy()
    np.save(save_path, y)

##################################################################################
data_dir = '/faceSD/S/'
fea_dir = '/faceSDfea/S/'
data_list = os.listdir(data_dir)

for i in range(len(data_list)):
    group_dir = data_dir + data_list[i] + '/'
    group_list = os.listdir(group_dir)
    save_dir = fea_dir + data_list[i] + '/'
    if os.path.exists(save_dir) == False:
        os.makedirs(save_dir)
    for j in range(2):
        img_path = group_dir + group_list[j]
        save_path = save_dir + group_list[j][0:-3] + 'npy'
        extractors(img_path,save_path,cnn)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Pytorch学习笔记(III)——提取特征 的相关文章

随机推荐

  • 唯一标识一台计算机解决方法:

    首先 网上介绍最多的方法就是cpu baseboard等硬件设备的序列号 但是 这两种获取方法都有问题 wmic cpu get processorid获取的cpu序列号 其实只是某个系列的代号 并不是唯一的 比如 12代i9都用的是一个C
  • Qt学习之QList类

    QList的定义 一 简介 QList lt T gt 常用的容器类 它是一个列表 存储了给定类型的值 而这些值可以通过索引访问 二 定义 QList
  • [项目管理-27]:任务的目的,背后的原因是任务实施首要思考的问题。

    案例 无论是一个项目 还是一项任务 在实施之前 弄清楚原因 是项目经理必须有的思维模式 而不是无条件的盲目的执行 只有弄清楚目的和原因 才能在执行过程中 遇到问题时 发挥主观能动性 采用各种灵活变通的方法解决问题 最后确保项目的成功 另一方
  • Android Studio设计APP实现与51单片机通过WIFI模块(ESP8266-01S)通讯控制LED灯亮灭的设计源码【详解】

    目录 一 前言 二 效果展示 1 APP界面展示 2 C51硬件展示 三 Android Studio APP源代码 1 AndroidManifest xml 1 请求联网 2 开放明文传输 2 MainActivity java 3 L
  • python同步系统时间

    公司的电脑比较老旧 主板上的电池也没电了 每天都得手动调时间 自动同步也因为日期每天都被重置了而无法同步ntp服务器 想拆开换电池发现机箱也打开不了 emmm 无奈之下 自己做一个同步时间的脚本吧 然后用bat运行 加入开机启动项每天开机自
  • 员工分组-STL案例

    案例描述 1 公司今天招聘了10个员 ABCDEFGHUIJ 10名员工进入公司后 需要指派员工在那个部门工作 2 员工信息有 姓名 工资组成 部门分为 策划 美术 研发 3 随机给10名员工分配部门和工资 4 通过multimap进行信息
  • MySQL必知必会-笔记-Part3

    MySQL必知必会 笔记 Part3 Cha7 数据过滤 本章讲授如何组合WHERE子句以建立功能更强的更高级的搜索条件 以及NOT和IN操作符的使用 7 1 组合WHERE子句 第6章中介绍的所有WHERE子句在过滤数据时使用的都是单一的
  • JVM系列笔记(一)

    JVM的位置 JVM是运行在操作系统之上的 它与硬件没有直接的交互 JVM的整体结构 HotSpot VM是目前市面上高性能虚拟机的代表作之一 它采用解释器与即时编译器并存的架构 在今天 Java程序的运行性能早已脱胎换股 已经达到了可以和
  • xmind使用学习

    1 Background 这年头不画个思维导图都不好意思搬砖了 闲暇之余学习了下用xmind来画图 记录于此 2 Concept 主题 有中心主题和分支主题 子主题 一个主题的下一级主题叫子主题 自由主题 独立于中心主题 分支主题外的主题
  • 中山三院挂号服务器维护中,于广州中山三院的一次郁闷就诊

    最近不时地看到关于医院不负责任的报道 感叹的同时总觉得不可思议 那一直以为很神圣的地方现在对待生命的态度真的有这么随便么 没想到 一不小心 自己竟成为了被随便对待的那一个 事情的经过是这样的 这几天妈妈的胃一直很不舒服 于是10月8日早上陪
  • Matlab中readmatrix用法

    目录 语法 说明 示例 从文本文件中读取矩阵 从电子表格文件中读取矩阵 使用导入选项从指定的工作表和范围中读取矩阵 从指定的工作表和范围中读取矩阵 readmatrix是从文件中读取矩阵 语法 A readmatrix filename A
  • Minimal API in .NET 6 Using Dapper and SQL - Minimal API Project

    快捷键 prop public int MyProperty get set property ctor 创建一个构造函数 constructor part1 数据库 存储过程处理 最小的API 这里新建项目的时候没有用控制器 创建数据库文
  • position:absolute详解

    position absolute 日常开发中经常涉及元素的定位 我们都知道 绝对定位相对于最近position不为static的父级元素来定位 但其中定位的位置还是有细微的差别的 绝对定位根据left和top属性来规定绝对定位元素的位置
  • 使用克拉默法则进行三点定圆(三维)

    目录 1 三维圆 2 python代码 3 计算结果 本文由CSDN点云侠原创 爬虫网站请自重 1 三维圆 已知不共线的三个点 设其坐标为 x 1 y 1
  • 斯坦福cs224n教程--- 学习笔记1

    一 前言 自然语言是人类智慧的结晶 自然语言处理是人工智能中最为困难的问题之一 而对自然语言处理的研究也是充满魅力和挑战的 通过经典的斯坦福cs224n教程 让我们一起和自然语言处理共舞 也希望大家能够在NLP领域有所成就 二 先修知识 学
  • Python爬虫市场简单分析

    Python爬虫是目前互联网行业中最重要的组成部分之一 Python作为一门易学易懂的编程语言 不需要过多的软件环境和部署条件 基本覆盖了爬虫开发的大部分需求 是网络数据爬取和处理的首选技术之一 Python通过一系列优秀的爬虫框架和库的支
  • 设计模式三: 代理模式(Proxy) -- JDK的实现方式

    简介 代理模式属于行为型模式的一种 控制对其他对象的访问 起到中介作用 代理模式核心角色 真实角色 代理角色 按实现方式不同分为静态代理和动态代理两种 意图 控制对其它对象的访问 类图 实现 JDK自带了Proxy的实现 下面我们先使用JD
  • 从零到英雄:Vue CLI 让你成为前端开发高手(一)

    前言 作者主页 雪碧有白泡泡 个人网站 雪碧的个人网站 推荐专栏 java一站式服务 前端炫酷代码分享 uniapp 从构建到提升 从0到英雄 vue成神之路 解决算法 一个专栏就够了 架构咱们从0说 数据流通的精妙之道 文章目录 前言 1
  • 学习方法小结:

    好的学习方法 好的算法 高效率学习 gt 努力学习 1 学习要有目标不能太盲目 2 笔记很重要 整理笔记更重要 3 博客 论坛的运用十分关键 从量变到质变的过程需要去坚持 4 不要忘记复习 不能太依赖老师和他人的帮助 5 多提问 善于发现问
  • Pytorch学习笔记(III)——提取特征

    目录 一 引言 二 具体步骤 1 参数模型 2 网络结构 3 参数载入 4 特征提取器 5 读取图片 三 完整代码 一 引言 深度学习在许多任务中主要充当着特征学习的作用 而学习完的特征才是后续应用的一个关键 本文将主要介绍 如何提取任意目