自监督行为识别-时空线索解耦(论文复现)
自监督行为识别-时空线索解耦(论文复现)
本文所涉及所有资源均在传知代码平台可获取
文章目录
- 自监督行为识别-时空线索解耦(论文复现)
- 引言
- 论文概述
- 核心创新点
- 双向解耦编码器
- 跨域对比损失的构建
- 结构化数据增强
- 项目部署
- 准备工作
- 数据准备
- 生成数据
- 训练&测试
- 训练
- 测试
- bug修改
引言
自监督骨架行为识别是一种利用未标记的骨架数据进行行为识别的方法。传统的行为识别方法通常需要大量标记好的数据进行训练,但标记数据的获取成本高昂。自监督学习通过设计自动生成标签的任务,可以在缺乏标记数据的情况下进行训练
在自监督骨架行为识别中,骨架数据可以通过传感器或深度摄像头等设备获取。这些数据包含了人体关节的位置和运动信息。自监督学习任务的关键是设计一种能够从未标记的骨架数据中自动生成标签的方法。
在训练过程中,使用未标记的骨架数据进行自监督学习,生成伪标签。然后,将生成的伪标签用于监督骨架行为识别模型的训练。通过这种方式,自监督学习可以在缺乏标记数据的情况下,提供一种有效的方法进行骨架行为识别。
那么目前自监督骨架行为还面临哪些挑战呢?
- 挑战1. 时空信息的混淆
编码器负责将输入映射到可以进行对比的潜在空间。而之前的大多数方法专注于通过常用的时空建模网络获得统一的信息。他们的设计导致了时间、空间信息的纠缠,无法为随后的对比措施提供明确的指示。
- 挑战2.数据增强的局限性
此外,现有技术往往局限于规模转换(常见的增强策略,比如裁剪、旋转),这导致无法充分利用数据增强的潜力。
- 挑战3. 未考虑方法的可迁移性
优化过程中,大多数方法都专注于在相同的表示水平上构建对比对;忽略域之间的差距(同一任务下或数据集中)
论文概述
SCD-NET(SCD-Net: Spatio temporal Clues Disentanglement Network for
Self-Supervised Skeleton-Based Action Recognition AAAI2024)引入了一种新的对比学习框架,即时空线索解耦网络(SCD-Net)。
具体来说,将解耦模块与特征提取器相结合,分别从空间和时间域获得明确的线索。对于SCD-Net的训练,构建了一个全局锚点,鼓励锚点与提取的线索相互作用。此外,本文提出了一种具有结构约束的新的掩码策略,以加强上下文关联,利用掩码图像建模到所提出的SCD-Net。
从实验结果来看,在NTU-RGB+D(60&120)和PKUMMD (I&II)数据集进行了广泛的评估,涵盖了各种下游任务,如动作识别、动作检索、迁移学习和半监督学习。实验结果证明了该方法的有效性,显著优于现有的最先进(SOTA)方法
核心创新点
为了解决自监督在面临的三个挑战,该文分别提出三种方法分别应对。首先在时空信息混淆的问题上,作者提出双向接口编码器;数据增强方面,分别在时间、空间上分设置不同的数据增强策略;方法的可迁移性方面设置了跨越对比损失,详细架构可见下文。
SCD-NET整体架构如下所示:骨架数据->数据增强(data augmentation)后,分别送入编码器层(encoder)以及动量编码器层(Momentum encoder).每个编码器都使用了双向解耦编码器,在经过特征抽取器(feature extractor)后,分别对空间解耦(spatial decoupling)、时间解耦(temporal decoupling)操作,获取不同维度的特征。动量编码器得到的输出作为键向量,正常编码器得到的输出作为查询向量,最后将键向量、查询向量进行对比学习
双向解耦编码器
一般来说,从骨架序列中提取的特征被描述为描述动作的复杂时空关联。然而,本文认为这种范式并不适用于对比学习。由于信息的纠缠性很大,很难为后续的比较提供明确的指导。在SCD-Net中,本文提倡一种双路解耦编码器,从复杂的序列信息中分别提取出时间、空间信息以获得更好的判别性表示。
双向解耦编码器构造如下图:分为建模(projection)和细化(refinement)阶段,空间部分对CT维度进行合并,保留V(代表骨骼关节)维度,而后进行嵌入操作得到骨架图->序列化–>transformer 编码器->空间池化->空间特征;时间部分对CC维度进行合并,保留T(代表视频帧)维度,而后进行嵌入操作得到关节序列->序列化–>transformer 编码器->时间池化->时间特征
# 双向解耦编码器vt = self.gcn_t(x)vt = rearrange(vt, '(B M) C T V -> B T (M V C)', M=2)vt = self.channel_t(vt)vs = self.gcn_s(x)vs = rearrange(vs, '(B M) C T V -> B (M V) (T C)', M=2)vs = self.channel_s(vs)vt = self.t_encoder(vt) # B T Cvs = self.s_encoder(vs)# implementation using amax for the TMP runs faster than using MaxPool1D# not support pytorch < 1.7.0vt = vt.amax(dim=1)vs = vs.amax(dim=1)return vt, vs
跨域对比损失的构建
# 正负样本以及损失函数的设计def forward(self, q_input, k_input):三种查询向量的定义qt, qs, qi = self.encoder_q(q_input) # queries: NxCqt = nn.functional.normalize(qt, dim=1)qs = nn.functional.normalize(qs, dim=1)qi = nn.functional.normalize(qi, dim=1)# 计算key特征with torch.no_grad(): # no gradient to keysself._momentum_update_key_encoder() # update the key encoderkt, ks, ki = self.encoder_k(k_input) # keys: NxCkt = nn.functional.normalize(kt, dim=1)ks = nn.functional.normalize(ks, dim=1)ki = nn.functional.normalize(ki, dim=1)# 正负样本l_pos_ti = torch.einsum('nc,nc->n', [qt, ki]).unsqueeze(1)l_pos_si = torch.einsum('nc,nc->n', [qs, ki]).unsqueeze(1)l_pos_it = torch.einsum('nc,nc->n', [qi, kt]).unsqueeze(1)l_pos_is = torch.einsum('nc,nc->n', [qi, ks]).unsqueeze(1)l_neg_ti = torch.einsum('nc,ck->nk', [qt, self.i_queue.clone().detach()])l_neg_si = torch.einsum('nc,ck->nk', [qs, self.i_queue.clone().detach()])l_neg_it = torch.einsum('nc,ck->nk', [qi, self.t_queue.clone().detach()])l_neg_is = torch.einsum('nc,ck->nk', [qi, self.s_queue.clone().detach()])# 损失函数logits_ti = torch.cat([l_pos_ti, l_neg_ti], dim=1)logits_si = torch.cat([l_pos_si, l_neg_si], dim=1)logits_it = torch.cat([l_pos_it, l_neg_it], dim=1)logits_is = torch.cat([l_pos_is, l_neg_is], dim=1)logits_ti /= self.Tlogits_si /= self.Tlogits_it /= self.Tlogits_is /= self.T
结构化数据增强
本位在空间、时间部分分别提出了不同的增强策略,空间部分提出结构引导的空间掩码,时间部分提出基于管道的时间掩码
- 结构引导的空间掩码
考虑到骨架的物理结构,当选择某个关节进行掩码时,模型可能通过周围的点学习到相关信息,掩码效果不佳。通过施加结构约束,本文的方法在当前随机选择的关节或框架周围的局部区域内应用掩码操作,而不是仅依赖于孤立的点本文同时对其相邻区域的进行掩码。让本文用矩阵p来表示邻接关系,如果关节i和j连通,则Pij = 1,否则Pij= 0。令D = Pn。为了施加结构约束,当节点i被选中时,本文对Dij != 0的所有节点j执行相同的增强操作。
- 基于管道的时间掩码
基于管道的时间掩码的核心思想是通过将时间序列数据分为多个管道,并为每个管道生成对应的时间掩码,来提取关键的行为特征。具体而言,时间掩码是一种二进制序列,用于指示时间序列中的重要时间段。通过对时间序列数据进行分割,并根据具体的行为任务和特征需求,选择性地将时间掩码应用于每个管道。结构图图下:
这种方法的优势在于,它可以将注意力集中在对行为识别最有用的时间段上,从而提高模型对关键动作的感知能力。时间掩码的生成可以根据不同的策略进行,如基于阈值、基于能量或基于模式识别等方法。生成的时间掩码可以作为输入数据的权重,用于调整模型对不同时间段的重视程度
项目部署
准备工作
- Pytorch环境
- 安装依赖包,运行以下命令即可
pip install -r requirements.txt
数据准备
生成数据
下载数据集
- NTU-RGB+D
- PKU-MMD
数据处理
- 用以下代码处理数据:
python ntu_gendata.py
训练&测试
训练
训练 NTU-RGB+D 60数据集 在 Cross-Subject 评价标准下的预训练模型, 运行以下命令
python ./pretraining.py --lr 0.01 --batch-size 64 --encoder-t 0.2 --encoder-k 8192 \--checkpoint-path ./checkpoints/pretrain/ \--schedule 351 --epochs 451 --pre-dataset ntu60 \--protocol cross_subject --skeleton-representation joint
测试
测试论文给出模型在行为识别任务下NTU-RGB+D 60 数据集 Cross-Subject 评价标准上的结果, 运行以下命令
python ./action_classification.py --lr 2 --batch-size 1024 \--pretrained ./checkpoints/pretrain/checkpoint.pth.tar \--finetune-dataset ntu60 --protocol cross_subject --finetune_skeleton_representation joint
测试论文给出模型在行为检索任务下NTU-RGB+D 60 数据集 Cross-Subject 评价标准上的结果, 运行以下命令
python ./action_retrieval.py --knn-neighbours 1 \--pretrained ./checkpoints/pretrain/checkpoint.pth.tar \--finetune-dataset ntu60 --protocol cross_subject --finetune-skeleton-representation joint
bug修改
在复现原文代码的时候,直接运行运行./pretraining文件,会出现如下错误
- 错误如下:
TypeError: init() got an unexpected keyword argument ‘batch_first’
- 原因分析:
init方法没有参数‘batch_first’,所以将batch_first删去即可。在更改batch_first参数的请务必同时输入数据进行同步调整。具体来说,batch_first=True时的输入维度为 (batch, seq, feature),否则对应的输入维度需要调整为(seq, batch, feature)
- 解决方法:
将报错代码中encoder_layer部分替换为如下代码,即可正常运行
encoder_layer = TransformerEncoderLayer(self.d_model, num_head, self.d_model)self.t_encoder = TransformerEncoder(encoder_layer, num_layer)self.s_encoder = TransformerEncoder(encoder_layer, num_layer)def forward(self, x):vt = self.gcn_t(x)vt = rearrange(vt, '(B M) C T V -> B T (M V C)', M=2)vt = self.channel_t(vt)vs = self.gcn_s(x)vs = rearrange(vs, '(B M) C T V -> B (M V) (T C)', M=2)vs = self.channel_s(vs)# batch_first=True时的输入维度为 (batch, seq, feature),# 否则对应的输入维度需要调整为(seq, batch, feature)# 通过transpose函数调整维度vt = vt.transpose(0, 1) # 调整为 (T, B, M*V*C)vs = vs.transpose(0, 1) # 调整为 (T, B*M*V, C)vt = self.t_encoder(vt) # vs = self.s_encoder(vs) #vt = vt.amax(dim=1)vs = vs.amax(dim=1)return vt, vs
文章代码资源点击附件获取
相关文章:

自监督行为识别-时空线索解耦(论文复现)
自监督行为识别-时空线索解耦(论文复现) 本文所涉及所有资源均在传知代码平台可获取 文章目录 自监督行为识别-时空线索解耦(论文复现)引言论文概述核心创新点双向解耦编码器跨域对比损失的构建结构化数据增强项目部署准备工作数据…...
MyBatisPlus:自定义SQL
由于SQL不能写在业务层,所以可以利用MyBatisPlus的Wrapper来构建复杂的Where条件,然后自己定义SQL语句中剩下的部分 ①基于Wrapper 构建Where条件 Testpublic void test7(){//需求:将id满足ids的数据项的balance字段减200int amount200;List…...

变电站谐波治理设备有哪些
在变电站中,由于非线性负载(如电力电子设备、变频器等)会引入谐波,对电网造成干扰,因此需要进行谐波治理。以下是常见的变电站谐波治理设备及其特点: 1、静止无功发生器(SVG) 工作原…...

Mybatis全局配置介绍
【mybatis全局配置介绍】 mybatis-config.xml,是MyBatis的全局配置文件,包含全局配置信息,如数据库连接参数、插件等。整个框架中只需要一个即可。 1、mybatis全局配置文件是mybatis框架的核心配置,整个框架只需一个;…...
error: cannot find symbol import android.os.SystemProperties;
背景:AS独立编译系统工程应用,使用了hide接口,导致编译不过。 尽管使用了framework.jar依赖。依然编译不过,导致各种类找不到。 例如: /SettingsLib/src/main/java/com/android/settingslib/location/RecentLocatio…...
债券市场金融基础设施 (2020版)
前言:我国债券市场格局简介 我国金融市场主要包括货币市场、资本市场、外汇市场、金融衍生工具市场等,其中,资本市场是金融市场重要组成部分,承担着实体经济直接融资的重责,做大做强资本市场对整个国民经济具有重要意义。债券市场是资本市场两大组成部分之一,对提高直接…...

OpenCV高级图形用户界面(8)在指定的窗口中显示一幅图像函数imshow()的使用
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 在指定的窗口中显示一幅图像。 函数 imshow 在指定的窗口中显示一幅图像。如果窗口是以 cv::WINDOW_AUTOSIZE 标志创建的,图像将以原…...

for循环和while循环的区别
for循环和while循环的主要区别在于使用场景和结构。for循环适合已知循环次数的情况,而while循环则更灵活,适用于条件动态变化的情况。 for循环的特点 1. 已知迭代次数:for循环在开始前就需要知道具体的迭代次数。例如,遍历一个列…...
机器学习和神经网络的研究与传统物理学的关系
机器学习和神经网络的研究与传统物理学的关系 机器学习和神经网络是现代科学研究中非常热门的领域,它们与传统物理学在某些方面有着密切的关系,在人类科学研究中相互影响和促进作用也越来越显著。 首先,机器学习和神经网络在物理学研究中具…...

LabVIEW提高开发效率技巧----事件触发模式
事件触发模式在LabVIEW开发中是一种常见且有效的编程方法,适用于需要动态响应外部或内部信号的场景。通过事件结构(Event Structure)和用户自定义事件(User Events),开发者可以设计出高效的事件驱动程序&am…...

Kimi AI助手重大更新:语音通话功能闪亮登场!
Kimi人工智能助手近日发布了一项令人瞩目的重大更新,其中最引人注目的是新增的语音通话功能。这一创新不仅拓展了用户与AI互动的方式,还为学习和工作场景提供了突破性的解决方案。 Ai 智能办公利器 - Ai-321.com 人工智能 - Ai工具集 - 全球热门人工智能…...

Linux——进程管理
目录 进程基础 ps 显示系统执行的进程 终止进程 kill 和 killall pstree 查看进程树 服务(service)管理 service 管理指令 服务的运行级别(runlevel) chkconfig 设置服务在不同运行级别下是否开启自启动 systemctl 管理…...
【ARM 嵌入式 编译系列 2.9 -- GCC 编译如何避免赋值判断 if ( x = 0)】
> ARM GCC 编译精讲系列课程链接 < 文章目录 GCC 编译避免赋值判断参数说明示例编译命令解决方法 GCC 编译避免赋值判断 在 GCC 编译中,为了避免误将赋值操作用于条件判断(例如 if (break_var 0x0))导致的错误,可以使用 -…...

PyTorch搭建GNN(GCN、GraphSAGE和GAT)实现多节点、单节点内多变量输入多变量输出时空预测
目录 I. 前言II. 数据集说明III. 模型3.1 GCN3.2 GraphSAGE3.3 GAT IV. 训练与测试V. 实验结果 I. 前言 前面已经写了很多关于时间序列预测的文章: 深入理解PyTorch中LSTM的输入和输出(从input输入到Linear输出)PyTorch搭建LSTM实现时间序列…...

51单片机快速入门之数码管的拓展应用2024/10/15
51单片机快速入门之数码管的拓展应用 在前面的文章中,我们已经了解到数码管的基础应用,今天来讲讲拓展应用 我们知道单个数码管分为以下 但是当我们碰到 如下这种数码管的时候又应该如何去控制呢? 这里就不得不说其拓展应用之-----------扫描显示 扫描显示: 扫描显示,又称…...
vue 音频播放控件封装
<template> <div> <audio @timeupdate="updateProgress" controls ref="audioRef" style="display: none" > <source :src="audioUrl" type="audio/mpeg" /> 您的浏览器不支持音频播放 </audio&…...

秋招面试题记录
嵌入式软件开发 网上搜集的题目 1.Static关键词的作用? static 关键字有三个主要作用: 局部变量:在函数内部,static 局部变量只初始化一次,且在函数调用结束后仍然保留其值。全局变量/函数:在文件内部&a…...

金字塔流(Pyramid Flow): 用于生成人工智能长视频的新文本-视频开源模型
在 "生成式人工智能 "中的文本生成模型和图像生成模型大行其道之后,现在该是文本-视频模型大显身手的时候了,这个列表中的新模型就是 pyramid-flow-sd3,它是一个开源模型,用于从文本或图像生成长达 10 秒的视频…...

施磊C++ | 进阶学习笔记 | 5.设计模式
五、设计模式 文章目录 五、设计模式1.设计模式三大类型概述一、创建型设计模式二、结构型设计模式三、行为型设计模式 2.设计模式三大原则3.单例模式1.饿汉单例模式2.懒汉单例模式 4.线程安全的懒汉单例模式1.锁双重判断2.简洁的线程安全懒汉单例模式 5.简单工厂(Simple Facto…...

智绘城市地图:使用百度地图 API 实现智能定位
✨✨ 欢迎大家来访Srlua的博文(づ ̄3 ̄)づ╭❤~✨✨ 🌟🌟 欢迎各位亲爱的读者,感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua小谢,在这里我会分享我的知识和经验。&am…...
渲染学进阶内容——模型
最近在写模组的时候发现渲染器里面离不开模型的定义,在渲染的第二篇文章中简单的讲解了一下关于模型部分的内容,其实不管是方块还是方块实体,都离不开模型的内容 🧱 一、CubeListBuilder 功能解析 CubeListBuilder 是 Minecraft Java 版模型系统的核心构建器,用于动态创…...

html css js网页制作成品——HTML+CSS榴莲商城网页设计(4页)附源码
目录 一、👨🎓网站题目 二、✍️网站描述 三、📚网站介绍 四、🌐网站效果 五、🪓 代码实现 🧱HTML 六、🥇 如何让学习不再盲目 七、🎁更多干货 一、👨…...
【无标题】路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论
路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论 一、传统路径模型的根本缺陷 在经典正方形路径问题中(图1): mermaid graph LR A((A)) --- B((B)) B --- C((C)) C --- D((D)) D --- A A -.- C[无直接路径] B -…...
【JavaSE】多线程基础学习笔记
多线程基础 -线程相关概念 程序(Program) 是为完成特定任务、用某种语言编写的一组指令的集合简单的说:就是我们写的代码 进程 进程是指运行中的程序,比如我们使用QQ,就启动了一个进程,操作系统就会为该进程分配内存…...

数学建模-滑翔伞伞翼面积的设计,运动状态计算和优化 !
我们考虑滑翔伞的伞翼面积设计问题以及运动状态描述。滑翔伞的性能主要取决于伞翼面积、气动特性以及飞行员的重量。我们的目标是建立数学模型来描述滑翔伞的运动状态,并优化伞翼面积的设计。 一、问题分析 滑翔伞在飞行过程中受到重力、升力和阻力的作用。升力和阻力与伞翼面…...

tauri项目,如何在rust端读取电脑环境变量
如果想在前端通过调用来获取环境变量的值,可以通过标准的依赖: std::env::var(name).ok() 想在前端通过调用来获取,可以写一个command函数: #[tauri::command] pub fn get_env_var(name: String) -> Result<String, Stri…...

【C++】纯虚函数类外可以写实现吗?
1. 答案 先说答案,可以。 2.代码测试 .h头文件 #include <iostream> #include <string>// 抽象基类 class AbstractBase { public:AbstractBase() default;virtual ~AbstractBase() default; // 默认析构函数public:virtual int PureVirtualFunct…...

spring Security对RBAC及其ABAC的支持使用
RBAC (基于角色的访问控制) RBAC (Role-Based Access Control) 是 Spring Security 中最常用的权限模型,它将权限分配给角色,再将角色分配给用户。 RBAC 核心实现 1. 数据库设计 users roles permissions ------- ------…...

客户案例 | 短视频点播企业海外视频加速与成本优化:MediaPackage+Cloudfront 技术重构实践
01技术背景与业务挑战 某短视频点播企业深耕国内用户市场,但其后台应用系统部署于东南亚印尼 IDC 机房。 随着业务规模扩大,传统架构已较难满足当前企业发展的需求,企业面临着三重挑战: ① 业务:国内用户访问海外服…...

Qt的学习(二)
1. 创建Hello Word 两种方式,实现helloworld: 1.通过图形化的方式,在界面上创建出一个控件,显示helloworld 2.通过纯代码的方式,通过编写代码,在界面上创建控件, 显示hello world; …...