基于CLIP4Clip的DRL的WTI模块实现

关于DRL的WTI模块:

  • Weighted Token-wise Interaction:
    直觉上,并非所有的单词和视频帧都同等重要。我们提供一种自适应方法,来调整每个标记的权重大小:
    在这里插入图片描述
    注:其中两个f函数都是MLP和softmax构成。

WTI的算法流程图:
在这里插入图片描述

  • 输入video和text之后分别通过encoder,得到representation
  • 之后使用fusion weights网络计算权重(在这个算法中,文本和视频的嵌入经过文本权重网络和视频权重网络,分别进行 Softmax 操作得到权重向量),
  • 之后将representation进行归一化,
  • 之后计算t2v和v2t的相关度

DRL中的WTI源代码:

def wti_interaction(self, text_feat, video_feat, text_mask, video_mask):if self.training and torch.cuda.is_available():  # 在训练时,且有 GPU 可用时进行批处理合并text_feat = allgather(text_feat, self.config)  # 合并文本特征video_feat = allgather(video_feat, self.config)  # 合并视频特征text_mask = allgather(text_mask, self.config)  # 合并文本掩码video_mask = allgather(video_mask, self.config)  # 合并视频掩码torch.distributed.barrier()  # 强制同步if self.config.interaction == 'wti':  # 如果交互方式为加权令牌级交互# 计算文本权重text_weight = self.text_weight_fc(text_feat).squeeze(2)  # B x N_t x D -> B x N_ttext_weight.masked_fill_(torch.tensor((1 - text_mask), dtype=torch.bool), float("-inf"))  # 将未激活的令牌(padding)设置为负无穷text_weight = torch.softmax(text_weight, dim=-1)  # 对文本权重进行 softmax 操作,以获取归一化的权重值# 计算视频权重video_weight = self.video_weight_fc(video_feat).squeeze(2)  # B x N_v x D -> B x N_vvideo_weight.masked_fill_(torch.tensor((1 - video_mask), dtype=torch.bool), float("-inf"))  # 将未激活的令牌(padding)设置为负无穷video_weight = torch.softmax(video_weight, dim=-1)  # 对视频权重进行 softmax 操作,以获取归一化的权重值text_feat = text_feat / text_feat.norm(dim=-1, keepdim=True)  # 对文本特征进行 L2 归一化video_feat = video_feat / video_feat.norm(dim=-1, keepdim=True)  # 对视频特征进行 L2 归一化# 计算令牌间的交互得分retrieve_logits = torch.einsum('atd,bvd->abtv', [text_feat, video_feat])  # 通过张量乘积计算交互得分retrieve_logits = torch.einsum('abtv,at->abtv', [retrieve_logits, text_mask])  # 融合文本掩码到交互得分retrieve_logits = torch.einsum('abtv,bv->abtv', [retrieve_logits, video_mask])  # 融合视频掩码到交互得分text_sum = text_mask.sum(-1)  # 文本掩码的求和结果video_sum = video_mask.sum(-1)  # 视频掩码的求和结果if self.config.interaction == 'ti':  # 如果交互方式为令牌级交互# 令牌间的交互方式是逐令牌进行t2v_logits, max_idx1 = retrieve_logits.max(dim=-1)  # 最大化视频令牌得分,获得文本到视频的交互得分v2t_logits, max_idx2 = retrieve_logits.max(dim=-2)  # 最大化文本令牌得分,获得视频到文本的交互得分t2v_logits = torch.sum(t2v_logits, dim=2) / (text_sum.unsqueeze(1))  # 对文本令牌得分进行加权平均v2t_logits = torch.sum(v2t_logits, dim=2) / (video_sum.unsqueeze(0))  # 对视频令牌得分进行加权平均retrieve_logits = (t2v_logits + v2t_logits) / 2.0  # 对文本到视频和视频到文本的交互得分进行平均elif self.config.interaction == 'wti':  # 如果交互方式为加权令牌级交互t2v_logits, max_idx1 = retrieve_logits.max(dim=-1)  # 最大化视频令牌得分,获得文本到视频的交互得分t2v_logits = torch.einsum('abt,at->ab', [t2v_logits, text_weight])  # 对文本令牌得分进行加权v2t_logits, max_idx2 = retrieve_logits.max(dim=-2)  # 最大化文本令牌得分,获得视频到文本的交互得分v2t_logits = torch.einsum('abv,bv->ab', [v2t_logits, video_weight])  # 对视频令牌得分进行加权retrieve_logits = (t2v_logits + v2t_logits) / 2.0  # 对文本到视频和视频到文本的交互得分进行平均if self.training:# 缩放检索得分logit_scale = self.clip.logit_scale.exp()retrieve_logits = logit_scale * retrieve_logits# 如果配置为 1,应用特定的损失函数if self.config.cdcr == 1:# ...(这部分代码用于特定的损失函数,返回对应的损失)# 如果配置为 2,应用另一种特定的损失函数elif self.config.cdcr == 2:# ...(这部分代码用于另一种特定的损失函数,返回对应的损失)# 如果配置为 3,应用另一种特定的损失函数elif self.config.cdcr == 3:# ...(这部分代码用于另一种特定的损失函数,返回对应的损失)else:return retrieve_logits, retrieve_logits.T, 0.0  # 返回检索得分else:return retrieve_logits, retrieve_logits.T, 0.0  # 返回检索得分

怎么把这个加进CLIP4Clip去?
发现DRL中的wit在get_similarity_logits()函数中被refer了,在modeling.py中
而CLIP4Clip中的modeling.py文件中同样含有函数get_similarity_logits(),思考怎么插入

get_similarity_logits()在DRL的调用位置:

def _run_on_single_gpu(model, t_mask_list, v_mask_list, t_feat_list, v_feat_list, mini_batch=32):sim_matrix = []  # 创建一个空列表,用于存储相似度矩阵的结果logger.info('[start] map to main gpu')  # 记录日志,表示开始将数据映射到主 GPUbatch_t_mask = torch.split(t_mask_list, mini_batch)  # 将文本掩码列表分割成小批次batch_v_mask = torch.split(v_mask_list, mini_batch)  # 将视频掩码列表分割成小批次batch_t_feat = torch.split(t_feat_list, mini_batch)  # 将文本特征列表分割成小批次batch_v_feat = torch.split(v_feat_list, mini_batch)  # 将视频特征列表分割成小批次logger.info('[finish] map to main gpu')  # 记录日志,表示完成数据映射到主 GPUwith torch.no_grad():  # 使用无梯度的上下文环境进行计算for idx1, (t_mask, t_feat) in enumerate(zip(batch_t_mask, batch_t_feat)):  # 遍历文本特征和掩码的小批次each_row = []  # 创建一个空列表,用于存储每行的结果for idx2, (v_mask, v_feat) in enumerate(zip(batch_v_mask, batch_v_feat)):  # 遍历视频特征和掩码的小批次# 计算文本特征和视频特征之间的相似度得分b1b2_logits, *_tmp = model.get_similarity_logits(t_feat, v_feat, t_mask, v_mask)# 将相似度得分转移到 CPU 上,并转换为 NumPy 数组b1b2_logits = b1b2_logits.cpu().detach().numpy()each_row.append(b1b2_logits)  # 将得到的相似度得分添加到每行的结果中# 将每个批次计算的相似度得分按照批次连接起来(水平连接)each_row = np.concatenate(tuple(each_row), axis=-1)sim_matrix.append(each_row)  # 将每行的结果添加到相似度矩阵列表中return sim_matrix  # 返回计算得到的相似度矩阵

同时,get_similarity_logits()在CLIP4Clip中的调用位置:

def _run_on_single_gpu(model, batch_list_t, batch_list_v, batch_sequence_output_list, batch_visual_output_list):sim_matrix = []  # 创建一个空列表,用于存储相似度矩阵的结果for idx1, b1 in enumerate(batch_list_t):  # 遍历文本特征列表input_mask, segment_ids, *_tmp = b1  # 解包文本特征列表的元素sequence_output = batch_sequence_output_list[idx1]  # 获取对应序列输出列表的元素each_row = []  # 创建一个空列表,用于存储每行的结果for idx2, b2 in enumerate(batch_list_v):  # 遍历视频特征列表video_mask, *_tmp = b2  # 解包视频特征列表的元素visual_output = batch_visual_output_list[idx2]  # 获取对应视觉输出列表的元素# 计算文本特征和视频特征之间的相似度得分b1b2_logits, *_tmp = model.get_similarity_logits(sequence_output, visual_output, input_mask, video_mask,loose_type=model.loose_type)# 将相似度得分转移到 CPU 上,并转换为 NumPy 数组b1b2_logits = b1b2_logits.cpu().detach().numpy()each_row.append(b1b2_logits)  # 将得到的相似度得分添加到每行的结果中each_row = np.concatenate(tuple(each_row), axis=-1)  # 将每个批次计算的相似度得分按照批次连接起来(水平连接)sim_matrix.append(each_row)  # 将每行的结果添加到相似度矩阵列表中return sim_matrix  # 返回计算得到的相似度矩阵

发现:
在这里插入图片描述
通过下图发现wti_interaction和_loose_similarity这两个函数调用都是在计算retrieve_logits
现在的工作是将wti_interaction的计算retrieval logits的步骤加入到_loose_similarity中
其实这个wti_interaction中的步骤就是上面的算法流程图的步骤

阅读CLIP4Clip代码:
发现有几个Encoder:CLIP Encoder以及Cross Encoder以及Transformer Encoder
cross encoder一般表示两个内容的相关程度

forward(): 模型的前向传播过程,在训练模式下计算损失值以进行模型训练,而在评估模式下则不返回任何损失。

感觉有点乱,因为代码中很少有注释,变量名还不是很有代表性(比如b、bs等等)
直接尝试以下移植过去怎么样。

发现CLIP4Clip和DRL的modeling.py都有以下的同步代码:

        if self.training and torch.cuda.is_available():  # batch merge heretext_feat = allgather(text_feat, self.config)video_feat = allgather(video_feat, self.config)video_mask = allgather(video_mask, self.config)torch.distributed.barrier()  # force sync

可以从这个为出发点,同步这两个代码的相同部分。

看了半天,对于二者来说,都是类似的过程:
最重要的其实是突破口在于forward函数
forward函数调用get_similarity_logits,而DRL中的get_similarity_logits中则调用了wti_interaction

CLIP4Clip中以下的计算output的代码应该对应于DRL中计算feature的代码:
sequenceDiagram_output, visual_output = self.get_sequence_visual_output(input_ids, token_type_ids, attention_mask, video, video_mask, shaped=True, video_frame=video_frame)(CLIP4Clip)
text_feat, video_feat = self.get_text_video_feat(text_ids, text_mask, video, video_mask, shaped=True)(DRL)

第一处最大的区别就是get_similarity_logits这个函数的输出不一样:
在这里插入图片描述
进入到具体的函数中发现确实是不一样:
在这里插入图片描述
发现sequence_output和text_feature是一样的,visual_output和video_feature是一样的:
在这里插入图片描述
之后计算loss的过程也都大同小异:
在这里插入图片描述
进入到get_similarity_logits函数之后,发现里面的区别在于_loose_similarity和wti_interaction
在这里插入图片描述
分别看一下loose_similarity以及wti_interaction的两个代码区别:
在这里插入图片描述
两者的输入应该是差不多的,都是两个模态的特征以及掩码mask

mean pooling的选项中,有关于其他选项的一些处理都被略过了。
首先二者都是先进行了一次同步操作
在这里插入图片描述
后面这块除了加入了平均池化之外,剩余的内容都是差不多的

运行DRL,发现它的读取json文件的标签出错了,因此报错了:

Traceback (most recent call last):File "/mnt/cloud_disk/fw/DRL/main.py", line 552, in <module>main()File "/mnt/cloud_disk/fw/DRL/main.py", line 496, in maintest_dataloader, val_dataloader, train_dataloader, train_sampler = build_dataloader(args)File "/mnt/cloud_disk/fw/DRL/main.py", line 166, in build_dataloadertrain_dataloader, train_length, train_sampler = DATALOADER_DICT[args.datatype]["train"](args, tokenizer)File "/mnt/cloud_disk/fw/DRL/tvr/dataloaders/data_dataloaders.py", line 7, in dataloader_msrvtt_trainmsrvtt_dataset = MSRVTTDataset(File "/mnt/cloud_disk/fw/DRL/tvr/dataloaders/dataloader_msrvtt_retrieval.py", line 19, in __init__super(MSRVTTDataset, self).__init__(subset, anno_path, video_path, tokenizer, max_words,File "/mnt/cloud_disk/fw/DRL/tvr/dataloaders/dataloader_retrieval.py", line 45, in __init__self.video_dict, self.sentences_dict = self._get_anns(self.subset)File "/mnt/cloud_disk/fw/DRL/tvr/dataloaders/dataloader_msrvtt_retrieval.py", line 43, in _get_annsfor itm in data['sentences']:
KeyError: 'sentences'

发现是json读取的时候标签中并没有sentences这个标签
发现这个json文件中的标签如下:
在这里插入图片描述
是data[‘annotations’]中的标签data[‘annotations’][‘caption’]以及[‘image_id’]
修改后如下:
在这里插入图片描述
重新安装numpy版本,发现以下bug:

(drl) lry@v100s003:/mnt/cloud_disk/fw/anaconda3/envs/drl/lib/python3.9/site-packages$ rm -r '~umpy.libs'
rm: cannot remove '~umpy.libs/.nfs000000008678fc7a000000d1': Device or resource busy
rm: cannot remove '~umpy.libs/.nfs000000008678fc7c000000d2': Device or resource busy
rm: cannot remove '~umpy.libs/.nfs000000008678fc7e000000d3': Device or resource busy

发现应该是我在vscode中的调试进程没有关闭,因此会有临时文件的残余被占用,无法rm;
在停止了调试进程后,就可以删除了。

事实证明DRL的文档写的真的很详细,直接照着做,就可以了(除了那个json标签出错的以及numpy需要更新版本)
在这里插入图片描述

之后发现cuda oom,结果是僵尸进程的问题:

fuser -v /dev/nvidia*

上面命令出现nvidia的僵尸进程:

(drl) xxx@v100s003:/xxx/DRL$ fuser -v /dev/nvidia*USER        PID ACCESS COMMAND
/dev/nvidia0:        xxx       3551238 F...m pythonxxx       3551797 F...m pythonxxx       3552245 F...m pythonxxx       3554186 F...m python
/dev/nvidia1:        xxx       3551238 F...m pythonxxx       3551797 F...m pythonxxx       3552245 F...m pythonxxx       3554186 F...m python
/dev/nvidia2:        xxx       3551238 F...m pythonxxx       3551797 F...m pythonxxx       3552245 F...m pythonxxx       3554186 F...m python
/dev/nvidia3:        xxx       3551238 F...m pythonxxx       3551797 F...m pythonxxx       3552245 F...m pythonxxx       3554186 F...m python
/dev/nvidia4:        xxx       3551238 F.... pythonxxx       3551797 F.... pythonxxx       3552245 F.... pythonxxx       3554186 F.... python
/dev/nvidia5:        xxx       3551238 F.... pythonxxx       3551797 F.... python.........

之后运行 kil -9 进程号 进程号 ... 即可
(详细见我的知乎回答:为什么用pytorch cuda,明明显存很够用,却报错out of memory?)

之后就可以查看DRL的tensor的size了:

        if self.config.interaction == 'wti':# print("text_feat",text_feat.size()) # [batch_size(128), 32(max_words), 512]text_weight = self.text_weight_fc(text_feat).squeeze(2)  # B x N_t x D -> B x N_t# print("text_weight_0",text_weight.size()) # [128, 32]# print("text_mask",text_mask.size()) # [128, 32]text_weight.masked_fill_(torch.tensor((1 - text_mask), dtype=torch.bool), float("-inf"))# print("text_weight_1",text_weight.size()) # [128, 32]text_weight = torch.softmax(text_weight, dim=-1)  # B x N_t# print("text_weight_2",text_weight.size()) # [128, 32]# print("video_feat",video_feat.size()) # [128, 12, 512]video_weight = self.video_weight_fc(video_feat).squeeze(2) # B x N_v x D -> B x N_v# print("video_weight_0",text_weight.size()) # [128, 32]# print("video_mask",text_mask.size()) # [128, 32]video_weight.masked_fill_(torch.tensor((1 - video_mask), dtype=torch.bool), float("-inf"))# print("video_weight_1",text_weight.size()) # [128, 32]video_weight = torch.softmax(video_weight, dim=-1)  # B x N_v# print("video_weight_2",text_weight.size()) # [128, 32]

而我们可以借此机会看一下CLIP4Clip的几个Tensor的shape是什么样的
CLIP4Clip的参数使用默认的:

DATA_PATH=[Your MSRVTT data and videos path]
python -m torch.distributed.launch --nproc_per_node=4 \
main_task_retrieval.py --do_train --num_thread_reader=0 \
--epochs=5 --batch_size=128 --n_display=50 \
--train_csv ${DATA_PATH}/MSRVTT_train.9k.csv \
--val_csv ${DATA_PATH}/MSRVTT_JSFUSION_test.csv \
--data_path ${DATA_PATH}/MSRVTT_data.json \
--features_path ${DATA_PATH}/MSRVTT_Videos \
--output_dir ckpts/ckpt_msrvtt_retrieval_looseType \
--lr 1e-4 --max_words 32 --max_frames 12 --batch_size_val 16 \
--datatype msrvtt --expand_msrvtt_sentences  \
--feature_framerate 1 --coef_lr 1e-3 \
--freeze_layer_num 0  --slice_framepos 2 \
--loose_type --linear_patch 2d --sim_header meanP \
--pretrained_clip_name ViT-B/32

我们发现video_mask的大小为torch.Size([16, 1, 12]),这个和DRL的有所不同,第一个16应该是batch_size_val那个,而为什么第二个维度是1,第三个维度是12?这个导致和后面的visual_output不兼容?

所以说我们要了解 text_weight_fcvideo_weight_fc 函数是干什么的

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/639966.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

网络安全的信息收集方法有哪些?

网络安全攻击中的信息收集是攻击者为了了解目标系统的弱点、配置、环境和潜在的防御措施而进行的活动。以下是一些常见的信息收集手段&#xff1a; 开放网络资源查询&#xff1a; 使用搜索引擎查找关于目标组织的信息&#xff0c;包括新闻稿、社交媒体帖子、官方网站等。通过W…

140:vue+leaflet加载here地图(v2软件多种形式)

第140个 点击查看专栏目录 本示例介绍如何在vue+leaflet中添加HERE地图(v2版本的软件),并且含多种的表现形式。包括地图类型,文字标记的设置、语言的选择、PPI的设定。 v3版本和v2版本有很大的区别,关键是引用方法上,请参考文章尾部的API链接。 直接复制下面的 vue+leaf…

【华为 ICT HCIA eNSP 习题汇总】——题目集7

1、一台 PC 的 MAC 地址是 5489-98FB-65D8 &#xff0c;管理员希望该 PC 从 DHCP 服务器获得指定的 IP 地址为192.168.1.11/24&#xff0c;以下命令配置正确的是&#xff08;&#xff09;。 A、dhcp static-bind ip-address 192.168.1.11 24 mac- address 5489-98FB-65D8 B、dh…

Kafka-服务端-日志存储

基本概念 首先需要了解的是&#xff0c;Kafka使用日志文件的方式保存生产者发送的消息。每条消息都有一个offset值来表示它在分区中的偏移量&#xff0c;这个offset值是逻辑值&#xff0c;并不是消息实际存放的物理地址。 offset值类似于数据库表中的主键&#xff0c;主键唯一…

亚马逊KYC审核的重要性,所需提交的文件有哪些?—站斧浏览器

亚马逊KYC审核的重要性有哪些&#xff1f; KYC审核是亚马逊对卖家身份的一种验证&#xff0c;确保卖家遵守相关法规。只有通过审核的卖家才能在欧洲平台进行销售。因此&#xff0c;正确理解和应对KYC审核对于卖家来说至关重要。 注册完成后立即触发&#xff1a;新注册的卖家可…

华为欧拉操作系统结合内网穿透实现固定公网地址SSH远程连接

文章目录 1. 本地SSH连接测试2. openEuler安装Cpolar3. 配置 SSH公网地址4. 公网远程SSH连接5. 固定连接SSH公网地址6. SSH固定地址连接测试 欧拉操作系统(openEuler, 简称“欧拉”)是面向数字基础设施的操作系统,支持服务器、云计算、边缘openEuler是面向数字基础设施的操作系…

Linux与windows互相传输文件之rzsz命令

文章目录 关于rzsz安装软件使用命令方法一&#xff1a;直接拖拽方法二&#xff1a;直接在终端输入rz 关于rzsz 这个工具用于 windows 机器和远端的 Linux 机器通过 XShell 传输文件 安装完毕之后可以通过拖拽的方式将文件上传过去 首先看一下我们的机器可以使用网络吗&#xff…

c语言-实现动态内存管理的库函数

文章目录 前言一、什么是动态内存分配&#xff1f;二、malloc()和free()2.1 malloc()介绍2.2 malloc()的使用2.3 free()介绍 三、calloc()3.1 calloc()介绍3.2 calloc()使用 四、realloc()4.1 realloc()介绍4.2 realloc()使用 总结 前言 本篇文章介绍c语言中实现动态内存管理的…

U-Mamba: Enhancing Long-range Dependency for Biomedical Image Segmentation

Abstract 卷积神经网络(Convolutional Neural Networks, cnn)和transformer是生物医学图像分割中最流行的架构&#xff0c;但由于固有的局部性或计算复杂性&#xff0c;它们处理远程依赖关系的能力有限。为了解决这一挑战&#xff0c;我们引入了U-Mamba&#xff0c;一个通用的…

二.Winform使用Webview2在Demo1中实现地址简单校验

Winform使用Webview2在Demo1中实现地址简单校验 往期目录回顾添加对于的简单url验证提示通过上节和本节涉及到的函数有 往期目录 往期相关文章目录 专栏目录 回顾 通过一.Winform使用Webview2(Edge浏览器核心) 创建demo(Demo1)实现回车导航到指定地址 我们已经知道了解决资源…

HCIA-HarmonyOS设备开发认证-HarmonyOS简介

目录 前言目标一、HarmonyOS简介1.1、初识HarmonyOS1.2、HarmonyOS典型应用场景 二、HarmonyOS架构与安全2.1、HarmonyOS架构 前言 本章主要介绍HarmonyOS分布式操作系统的概念、关键技术与能力以及HarmonyOS典型的应用场景。 目标 学习完成本课程后&#xff0c;您将能够&…

MySql必知必会

1.什么是BufferPool&#xff1f; Buffer Pool基本概念 Buffer Pool&#xff1a;缓冲池&#xff0c;简称BP。其作用是用来缓存表数据与索引数据&#xff0c;减少磁盘IO操作&#xff0c;提升效率。 Buffer Pool由缓存数据页(Page) 和 对缓存数据页进行描述的控制块 组成, 控制…

树莓派 Linux - 使用ngrok实现内网穿透

官网 &#xff1a;ngrok | Unified Application Delivery Platform for Developers 简单的注册一下即可 我这里的操作系统是kali Linux 选择linux 启动服务最好使用静态域名 把需要穿透的端口号配置为本地的端口号即可 参考视频 没有服务器&#xff0c;就不能上线网站了&am…

HYBBS 表白墙网站PHP程序源码 可封装成APP

源码介绍 PHP表白墙网站源码&#xff0c;可以做校园内的&#xff0c;也可以做校区间的&#xff0c;可封装成APP。告别QQ空间的表白墙吧。 安装PHP5.6以上随意 上传程序安装&#xff0c;然后设置账号密码&#xff0c;登陆后台切换模板手机PC都要换开启插件访问前台。 安装完…

Unity 工厂方法模式(实例详解)

文章目录 在Unity中&#xff0c;工厂方法模式是一种创建对象的常用设计模式&#xff0c;它提供了一个接口用于创建对象&#xff0c;而具体的产品类是由子类决定的。这样可以将对象的创建过程与使用过程解耦&#xff0c;使得代码更加灵活和可扩展。 工厂模式的主要优点如下&…

深度学习笔记(九)——tf模型导出保存、模型加载、常用模型导出tflite、权重量化、模型部署

文中程序以Tensorflow-2.6.0为例 部分概念包含笔者个人理解&#xff0c;如有遗漏或错误&#xff0c;欢迎评论或私信指正。 本篇博客主要是工具性介绍&#xff0c;可能由于软件版本问题导致的部分内容无法使用。 首先介绍tflite: TensorFlow Lite 是一组工具&#xff0c;可帮助开…

[足式机器人]Part2 Dr. CAN学习笔记- 最优控制Optimal Control Ch07-1最优控制问题与性能指标

本文仅供学习使用 本文参考&#xff1a; B站&#xff1a;DR_CAN Dr. CAN学习笔记 - 最优控制Optimal Control Ch07-1最优控制问题与性能指标

Spring+SprinMVC+MyBatis注解方式简易模板

SpringSprinMVCMyBatis注解方式简易模板代码Demo GitHub访问 ssm-tpl-anno 一、数据准备 创建数据库test&#xff0c;执行下方SQL创建表ssm-tpl-cfg /*Navicat Premium Data TransferSource Server : 127.0.0.1Source Server Type : MySQLSource Server Version :…

【优化技术专题】「性能优化系列」针对Java对象压缩及序列化技术的探索之路

针对Java对象压缩及序列化技术的探索之路 序列化和反序列化为何需要有序列化呢&#xff1f;Java实现序列化的方式二进制格式 指定语言层级二进制格式 跨语言层级JSON 格式化类JSON格式化&#xff1a;XML文件格式化 序列化的分类在速度的对比上一般有如下规律&#xff1a;Java…

选择排序(二)——堆排序(性能)与直接选择排序

目录 一.前言 二.选择排序 2.1 堆排序 2.2选择排序 2.2.1 基本思想 2.2.2直接选择排序 三.结语 一.前言 本文给大家带来的是选择排序&#xff0c;其中选择排序中的堆排序在之前我们已经有过详解所以本次主要是对比排序性能&#xff0c;感兴趣的友友可移步观看堆排&#…