GaitSet学习笔记(不包括三元数损失,仅含主干网络)

2024-01-24 19:10

本文主要是介绍GaitSet学习笔记(不包括三元数损失,仅含主干网络),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

论文

1 Introduction

1.1 旧方法

​ ① 将步态轮廓压缩为一张图(损失了时序信息与细粒度系信息)

​ ② 直接从原始步态轮廓序列中提取特征(极易受到外部条件影响)

image-20220209154551228

1.2 我们提出的方法

​ 步态序列可以看做一个周期,而特定帧有其特定的步态形态,人类很容易可以复原打乱的步态序列的顺序。因此,顺序信息不必需提供给网络,而将步态序列帧看做一个个具有位置信息的帧组成的集合,网络可以通过学习得到序列的时序信息。

image-20220209163759154

​ 基于步态具有位置信息的假设,我们提出了一个端到端的网络,并且具有以下的三大优点:

​ ① 灵活:输入不受到约束

​ ② 快速:直接对二维剪影序列进行特征提取,减少计算(相比于机器学习方法)

​ ③ 高效:缓解协变量影响,提高鲁棒性与泛化能力

image-20220209162309344

2 Related Work

​ 受到PointNet(处理点云信息)的启发,采用了无序集作为网路输入数据。点云模型是三维图形的一种表示模型,点云具有顺序无关性。PointNet利用无序集可以避免量化带来的噪声和数据扩展,并获得高性能。

image-20220209165029696

3 GaitSet

3.1 主干网络简介

​ F:通过卷积层,得到序列的帧级别特征

​ G:通过集合池化(Set Pooling),将帧级别特征映射到集合级别特征

​ H:通过水平金字塔映射,学习集合级别特征的判别性表示

image-20220209170923224

image-20220209191537282

3.2 集合池化(Set Pooling)

​ 作用:集合元素的步态信息,将帧级别特征映射为集合级别特征

​ 两个限制:

​ ① 必须是排列不变函数

​ ② 接受任何数量的集合输入

​ SP的几个实例:

​ ① Statistical Functions:为了满足排列不变,可以引入max,mean和median这类统计函数

​ ② Joint Functions:上述统计函数的两种连接方式

image-20220209174810359

​ ③ Attention:利用全局信息为每个帧级特征学习一个元素级的注意映射,并对其进行细化

image-20220209180742069

3.3 水平金字塔映射(Horizontal Pyramid Mapping)

image-20220209183018802

image-20220210150701061

​ ① 通过划分水平条的方式来获得多尺度的特征,该算法通常划分为S个尺度,由集合池化提取后的特征图在高度尺寸上被分成2^(k-1)条

​ ② 不同的水平条在不同的尺度上描述着不同的感受野,同时在每个尺度上描述不同空间位置的运动特征

​ ③ 结合使用平均与最大池化策略对不同尺度的空间条信息进行提取:平均池化可以感知空间条的全局信息最大池化可以提取最具判别性的信息,结合两种池化得到的融合特征将具有更强的判别能力

​ ④ 通过独立权重的全连接层将特征映射到更具判别力的空间,从而获得步态特征的判别性表示

⑤ MGP模块和主网络模块分别经过HPP操作,宽度和高度这两个维度被压缩成1,2,4,8,16这样的1个维度

3.4 多层全局管道(MGP)

MGP

​ 众所周知,浅层的网络学习局部信息以及细粒度信息,深层网络学习全局信息以及粗粒度信息。MGP的提出正是为了收集不同层次网络的集合级别特征信息

​ 注意,MGP后的HPM与主干网后的HPM不共享参数。

代码

1 主干网卷积网

image-20220210144357377

# 基本卷积核
class BasicConv2d(nn.Module):def __init__(self, in_channels, out_channels, kernel_size, **kwargs):super(BasicConv2d, self).__init__()self.conv = nn.Conv2d(in_channels, out_channels, kernel_size, bias=False, **kwargs)def forward(self, x):x = self.conv(x)return F.leaky_relu(x, inplace=True)# 卷积核 + 池化层
class SetBlock(nn.Module):def __init__(self, forward_block, pooling=False):super(SetBlock, self).__init__()self.forward_block = forward_blockself.pooling = poolingif pooling:self.pool2d = nn.MaxPool2d(2)  # 2×2池化def forward(self, x):n, s, c, h, w = x.size()  # n人物数量,s序列数量,c通道数量,h图片高,w图片宽x = self.forward_block(x.view(-1, c, h, w))  # [bs, 30, 1, 64, 44] => [bs * 30, 1, 64, 44]if self.pooling:x = self.pool2d(x)_, c, h, w = x.size()return x.view(n, s, c, h ,w)_set_in_channels = 1
_set_channels = [32, 64, 128]
self.set_layer1 = SetBlock(BasicConv2d(_set_in_channels, _set_channels[0], 5, padding=2))  # C1:1, 32, 5, 2
self.set_layer2 = SetBlock(BasicConv2d(_set_channels[0], _set_channels[0], 3, padding=1), True)  # C2:32, 32, 3, 1 + pooling
self.set_layer3 = SetBlock(BasicConv2d(_set_channels[0], _set_channels[1], 3, padding=1))  # C3:32, 64, 3, 1
self.set_layer4 = SetBlock(BasicConv2d(_set_channels[1], _set_channels[1], 3, padding=1), True)  # C4:64, 64, 3, 1 + pooling
self.set_layer5 = SetBlock(BasicConv2d(_set_channels[1], _set_channels[2], 3, padding=1))  # C5:64, 128, 3, 1
self.set_layer6 = SetBlock(BasicConv2d(_set_channels[2], _set_channels[2], 3, padding=1))  # C6:128, 128, 3, 1

2 MGP

image-20220210150905085

_gl_in_channels = 32
_gl_channels = [64, 128]
self.gl_layer1 = BasicConv2d(_gl_in_channels, _gl_channels[0], 3, padding=1)  # 32, 64, 3, 1
self.gl_layer2 = BasicConv2d(_gl_channels[0], _gl_channels[0], 3, padding=1)  # 64, 64, 3, 1
self.gl_layer3 = BasicConv2d(_gl_channels[0], _gl_channels[1], 3, padding=1)  # 64, 128, 3, 1
self.gl_layer4 = BasicConv2d(_gl_channels[1], _gl_channels[1], 3, padding=1)  # 128, 128 3, 1
self.gl_pooling = nn.MaxPool2d(2)

3 Set Pooling

image-20220210145813534

def frame_max(self, x):return torch.max(x, 1)  # 第二维度(frame)的最大值。论文表示,利用max作为SP,且不采用1×1卷积的综合效果最好:

image-20220210145716585

image-20220210150539624

4 HPM + FC

self.bin_num = [1, 2, 4, 8, 16]  # 水平条的尺度
# 全连接层,hidden_dim = 256
# sum(self.bin_num) * 2, 128, hidden_dim = 31 * 2, 128, 256 = 62, 128, 256
# 反向传播过程中,利用该全连接矩阵与最后特征做tensor乘法以实现维度扩展,注意实现参数初始化
self.fc_bin = nn.ParameterList([nn.Parameter(nn.init.xavier_uniform_(torch.zeros(sum(self.bin_num) * 2, 128, hidden_dim)))])

5 参数初始化

for m in self.modules():if isinstance(m, (nn.Conv2d, nn.Conv1d)):nn.init.xavier_uniform_(m.weight.data)elif isinstance(m, nn.Linear):nn.init.xavier_uniform_(m.weight.data)nn.init.constant(m.bias.data, 0.0)elif isinstance(m, (nn.BatchNorm2d, nn.BatchNorm1d)):nn.init.normal(m.weight.data, 1.0, 0.02)nn.init.constant(m.bias.data, 0.0)

6 前向传播过程

6.1 主干网 + MGP

image-20220210153031588

'''bs: batch_size'''x = silho.unsqueeze(2) # [bs, 30, 64, 44] => [bs, 30, 1, 64, 44]  扩展通道# 主干网卷积层1
x = self.set_layer1(x)  # 1:[bs, 30, 32, 64, 44] Conv
x = self.set_layer2(x)  # 2: [bs, 30, 32, 32, 22] Conv + Pooling# MGP卷积层1
gl = self.gl_layer1(self.frame_max(x)[0]) # 3: [bs, 64, 32, 22] SP + Conv
gl = self.gl_layer2(gl)  # 4: [bs, 64, 32, 22] Conv
gl = self.gl_pooling(gl)  # 5: [bs, 64, 16, 22] Pooling# 主干网卷积层2
x = self.set_layer3(x)  # 6: [bs, 30, 64, 32, 22] Conv
x = self.set_layer4(x)  # 7: [bs, 30, 64, 16, 11] Conv + Pooling # MGP卷积层2
gl = self.gl_layer3(gl + self.frame_max(x)[0])  # 8: [bs, 128, 16, 11] SP + Concat + Conv
gl = self.gl_layer4(gl)  # 9: [bs, 128, 16, 11] Conv# 主干网卷积层3
x = self.set_layer5(x)  # 10: [bs, 30, 128, 16, 11] Conv
x = self.set_layer6(x)  # 11: [bs, 30, 128, 16, 11] Conv
x = self.frame_max(x)[0]  # 12:[bs, 128, 16, 11] SPgl = gl + x  # 13: [bs, 128, 16, 11] Concat

6.2 HPM + FC

image-20220210155612583

image-20220210155359324

feature = list()
n, c, h, w = gl.size()  # 8, 128, 16, 11for num_bin in self.bin_num:  # 1 2 4 8 16,不同尺度的感受野# 主干网 + HPPz = x.view(n, c, num_bin, -1)  # 将长和宽压缩为一维,16*11 => 1,2,4,8,16  # [bs, 128, 1, 176], [bs, 128, 2, 88], [bs, 128, 4, 44], [bs, 128, 8, 22], [bs, 128, 16, 11]z = z.mean(3) + z.max(3)[0]  # 第四维度的平均池化 + 最大池化  # [bs, 128, 1], [bs, 128, 2], [bs, 128, 4], [bs, 128, 8], [bs, 128, 16]feature.append(z)  # 将水平条放入feature列表# 主干网 + MGP + HPPz = gl.view(n, c, num_bin, -1)  # 操作同上z = z.mean(3) + z.max(3)[0]feature.append(z)feature = torch.cat(feature, 2).permute(2, 0, 1).contiguous()  # [62, bs, 128] 连接水平条并对换维度
feature = feature.matmul(self.fc_bin[0])  # [62, bs, 256] 使用矩阵乘法实现全连接层
feature = feature.permute(1, 0, 2).contiguous()  # [bs, 62, 256]  对换维度,得到最终网络输出

这篇关于GaitSet学习笔记(不包括三元数损失,仅含主干网络)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/640703

相关文章

Linux中压缩、网络传输与系统监控工具的使用完整指南

《Linux中压缩、网络传输与系统监控工具的使用完整指南》在Linux系统管理中,压缩与传输工具是数据备份和远程协作的桥梁,而系统监控工具则是保障服务器稳定运行的眼睛,下面小编就来和大家详细介绍一下它... 目录引言一、压缩与解压:数据存储与传输的优化核心1. zip/unzip:通用压缩格式的便捷操作2.

Go学习记录之runtime包深入解析

《Go学习记录之runtime包深入解析》Go语言runtime包管理运行时环境,涵盖goroutine调度、内存分配、垃圾回收、类型信息等核心功能,:本文主要介绍Go学习记录之runtime包的... 目录前言:一、runtime包内容学习1、作用:① Goroutine和并发控制:② 垃圾回收:③ 栈和

Android学习总结之Java和kotlin区别超详细分析

《Android学习总结之Java和kotlin区别超详细分析》Java和Kotlin都是用于Android开发的编程语言,它们各自具有独特的特点和优势,:本文主要介绍Android学习总结之Ja... 目录一、空安全机制真题 1:Kotlin 如何解决 Java 的 NullPointerExceptio

Linux网络配置之网桥和虚拟网络的配置指南

《Linux网络配置之网桥和虚拟网络的配置指南》这篇文章主要为大家详细介绍了Linux中配置网桥和虚拟网络的相关方法,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 一、网桥的配置在linux系统中配置一个新的网桥主要涉及以下几个步骤:1.为yum仓库做准备,安装组件epel-re

python如何下载网络文件到本地指定文件夹

《python如何下载网络文件到本地指定文件夹》这篇文章主要为大家详细介绍了python如何实现下载网络文件到本地指定文件夹,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下...  在python中下载文件到本地指定文件夹可以通过以下步骤实现,使用requests库处理HTTP请求,并结合o

重新对Java的类加载器的学习方式

《重新对Java的类加载器的学习方式》:本文主要介绍重新对Java的类加载器的学习方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、介绍1.1、简介1.2、符号引用和直接引用1、符号引用2、直接引用3、符号转直接的过程2、加载流程3、类加载的分类3.1、显示

Linux高并发场景下的网络参数调优实战指南

《Linux高并发场景下的网络参数调优实战指南》在高并发网络服务场景中,Linux内核的默认网络参数往往无法满足需求,导致性能瓶颈、连接超时甚至服务崩溃,本文基于真实案例分析,从参数解读、问题诊断到优... 目录一、问题背景:当并发连接遇上性能瓶颈1.1 案例环境1.2 初始参数分析二、深度诊断:连接状态与

Qt实现网络数据解析的方法总结

《Qt实现网络数据解析的方法总结》在Qt中解析网络数据通常涉及接收原始字节流,并将其转换为有意义的应用层数据,这篇文章为大家介绍了详细步骤和示例,感兴趣的小伙伴可以了解下... 目录1. 网络数据接收2. 缓冲区管理(处理粘包/拆包)3. 常见数据格式解析3.1 jsON解析3.2 XML解析3.3 自定义

Java学习手册之Filter和Listener使用方法

《Java学习手册之Filter和Listener使用方法》:本文主要介绍Java学习手册之Filter和Listener使用方法的相关资料,Filter是一种拦截器,可以在请求到达Servl... 目录一、Filter(过滤器)1. Filter 的工作原理2. Filter 的配置与使用二、Listen

利用Python快速搭建Markdown笔记发布系统

《利用Python快速搭建Markdown笔记发布系统》这篇文章主要为大家详细介绍了使用Python生态的成熟工具,在30分钟内搭建一个支持Markdown渲染、分类标签、全文搜索的私有化知识发布系统... 目录引言:为什么要自建知识博客一、技术选型:极简主义开发栈二、系统架构设计三、核心代码实现(分步解析