基于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_t
        text_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_v
        video_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')  # 记录日志,表示开始将数据映射到主 GPU
    batch_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')  # 记录日志,表示完成数据映射到主 GPU

    with 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 here
            text_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 main
    test_dataloader, val_dataloader, train_dataloader, train_sampler = build_dataloader(args)
  File "/mnt/cloud_disk/fw/DRL/main.py", line 166, in build_dataloader
    train_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_train
    msrvtt_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_anns
    for 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 python
                     xxx       3551797 F...m python
                     xxx       3552245 F...m python
                     xxx       3554186 F...m python
/dev/nvidia1:        xxx       3551238 F...m python
                     xxx       3551797 F...m python
                     xxx       3552245 F...m python
                     xxx       3554186 F...m python
/dev/nvidia2:        xxx       3551238 F...m python
                     xxx       3551797 F...m python
                     xxx       3552245 F...m python
                     xxx       3554186 F...m python
/dev/nvidia3:        xxx       3551238 F...m python
                     xxx       3551797 F...m python
                     xxx       3552245 F...m python
                     xxx       3554186 F...m python
/dev/nvidia4:        xxx       3551238 F.... python
                     xxx       3551797 F.... python
                     xxx       3552245 F.... python
                     xxx       3554186 F.... python
/dev/nvidia5:        xxx       3551238 F.... python
                     xxx       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不兼容?
attention_mask的大小是torch.Size([16, 32])
sequence_output的大小是torch.Size([16, 1, 512]),经过了squeeze之后变成torch.Size([16, 512])
visual_output的大小是torch.Size([16, 12, 512]),经过了visual_output = self._mean_pooling_for_similarity_visual(visual_output, video_mask)之后就会变成torch.Size([16, 512])
其中一些变量的大小:
在这里插入图片描述
发现b是16,和batch_size_val一致;
而bs是12,和max_frames一致;

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

使用STM32的SPI接口实现与外部传感器的数据交互

一、引言 外部传感器是嵌入式系统中常用的外设&#xff0c;用于检测环境参数、采集数据等。通过STM32微控制器的SPI接口&#xff0c;可以与外部传感器进行数据交互&#xff0c;从而实现数据的采集和控制。本文将介绍如何使用STM32的SPI接口实现与外部传感器的数据交互&#xff…

云计算任务调度仿真05

今天再分享一个新的调度框架deeprm 本项目基于hongzimao/deeprm&#xff0c;原作者还著有论文Resource Management with Deep Reinforcement Learning 。 这个框架研究的也蛮多的&#xff0c;我在一篇博士论文中也看到了基于此的研究工作&#xff0c;但是论文题目忘记了。 运…

【C++】入门(一)

前言&#xff1a; 本篇博客将带大家认识C&#xff0c;熟悉基本语法 文章目录 认识CC的诞生与发展C 在行业中的运用 一、命名空间1.1 命名空间的定义1.2 命名空间的使用1.3 命名空间的访问 二、C输入&输出输出操作符 <<输入操作符 >>换行符和刷新输出缓冲区关键…

如何在CentOS8使用宝塔面板本地部署Typecho个人网站并实现公网访问【内网穿透】

文章目录 前言1. 安装环境2. 下载Typecho3. 创建站点4. 访问Typecho5. 安装cpolar6. 远程访问Typecho7. 固定远程访问地址8. 配置typecho 前言 Typecho是由type和echo两个词合成的&#xff0c;来自于开发团队的头脑风暴。Typecho基于PHP5开发&#xff0c;支持多种数据库&#…

vmware 安装Rocky-9.3系统

安装系统截图 安装完成&#xff0c;启动 查看版本和内核 开启远程登陆授权 1、编辑配置文件 #提升权限&#xff0c;输入su,并输入密码 su #编辑ssh文件开启root远程登陆 vi /etc/ssh/sshd_config找到以下内容&#xff1a;#PermitRootLogin prohibit-password 添加&#xff1a…

C#winform上位机开发学习笔记5-串口助手的定时发送功能添加

1.功能描述 选择自动发送功能后&#xff0c;按照设定的发送时间发送发送框中的信息数据&#xff0c;设定时间可以手动输入&#xff0c;当手动输入信息无效&#xff08;非数字&#xff09;时&#xff0c;系统弹出错误提示&#xff0c;并将其设置为默认定时时间。 2.代码部分 步…

【MySQL进阶】视图_存储过程_存储函数_触发器

文章目录 视图基本介绍视图操作视图创建视图查询视图修改视图删除 存储过程基本介绍基本操作存储语法变量IF语句参数传递CASEWHILEREPEATLOOP游标 存储函数触发器基本介绍基本操作 总结 视图 基本介绍 视图概念&#xff1a;视图是一种虚拟存在的数据表&#xff0c;这个虚拟的表…

【Linux对磁盘进行清理、重建、配置文件系统和挂载,进行系统存储管理调整存储结构】

Linux 调整存储结构 前言一、查看磁盘和分区列表二、创建 ext4 文件系统&#xff0c;即&#xff1a;格式化分区为ext4文件系统。1.使用命令 mkfs.ext4 (make file system)报错如下&#xff1a;解决办法1&#xff1a;&#xff08;经测试&#xff0c;不采用&#xff09;X解决办法…

Docker-Jenkins编译android-app的两种方案

Docker-Jenkins编译android-app的两种方案 android开发使用jenkins编译&#xff0c;自动集成修改点/自动命名/自动备份&#xff0c;将修改的apk发布到测试服务器发布网盘&#xff0c;而不需要用通讯工具传来传去。 jenkins用在互联网开发编译比较常见&#xff0c;如果android开…

电力电子技术

文章目录 5 直流直流变流电路5.0 简介5.1 基本斩波电路5.1.1 降压斩波电路 Buck Chopper5.1.1.1 小纹波近似 5.1.2升压斩波电路 11 DC-DC 变换器数字控制11.1 基于单片机控制11.2 基于 DSP 控制11.3 基于 FPGA 控制 12 多相交错并联拓扑结构12.1 多相交错并联12.1 多相交错并联…

CS8370错误,这是由于使用了C# 7.3中不支持的功能

目录 背景: 第一种方法: 第二种办法: 背景: 在敲代码的时候&#xff0c;程序提示报错消息提示:CS8370错误&#xff0c;那么这是什么原因导致的&#xff0c;这是由于使用了C# 7.3中不支持的功能&#xff0c;不支持该功能&#xff0c;那就是版本太低我们就需要升级更高的版本&…

韩国访问学者如何申请?

作为访问学者&#xff0c;前往韩国学术机构进行研究是一项令人期待的经历。首先&#xff0c;申请者需要查找目标学术机构的官方网站&#xff0c;下面知识人网小编带大家了解其访问学者计划的具体要求和申请流程。 通常&#xff0c;申请程序包括填写在线申请表格&#xff0c;提交…

《WebKit 技术内幕》学习之八(3):硬件加速机制

3 其他硬件加速模块 3.1 2D图形的硬件加速机制 其实网页中有很多绘图操作是针对2D图形的&#xff0c;这些操作包括通常的网页绘制&#xff0c;例如绘制边框、文字、图片、填充等&#xff0c;它们都是典型的2D绘图操作。在HTML5中&#xff0c;规范又引入了2D绘图的画布功能&a…

枚举问题刷题

考研机试题目中的很多问题往往能通过暴力方法来求解&#xff0c;这些题目并不需要进行过多的思考&#xff0c;而只需枚举所有可能的情况&#xff0c;或者模拟题目中提出的规则&#xff0c;便可以得到解答。虽然说这种方法看上并不高明&#xff0c;但对于一些简单的题目来说却是…

力扣日记1.21-【回溯算法篇】77. 组合

力扣日记&#xff1a;【回溯算法篇】77. 组合 日期&#xff1a;2023.1.21 参考&#xff1a;代码随想录、力扣 终于结束二叉树了&#xff01;听说回溯篇也是个大头&#xff0c;不知道这一篇得持续多久了…… 77. 组合 题目描述 难度&#xff1a;中等 给定两个整数 n 和 k&#…

最优传输学习及问题总结

文章目录 参考内容lam0.1lam3lam10lam50lam100lam300画图线性规划matlabpython代码 欢迎关注我们组的微信公众号&#xff0c;更多好文章在等你呦&#xff01; 微信公众号名&#xff1a;碳硅数据 公众号二维码&#xff1a; 参考内容 https://blog.csdn.net/qq_41129489/artic…

Ubuntu下安装Gazebo仿真器

Ubuntu下安装Gazebo仿真器 Gazebo仿真平台通常需要配合ROS使用&#xff0c;因此需要先安装ROS。可以参考ROS安装教程 首先安装一些必要的工具 sudo apt-get update sudo apt-get install lsb-release wget gnupg修改源 sudo wget https://packages.osrfoundation.org/gazebo…

【教程】npm的时候ssh报错ssh://git@github.com/frozeman/bignumber.js-nolookahead.git

问题&#xff1a; fiscoubuntu:~/fisco/benchmarks$ npm install install web30.20.7 npm ERR! code 128 npm ERR! An unknown git error occurred npm ERR! command git --no-replace-objects ls-remote ssh://gitgithub.com/frozeman/bignumber.js-nolookahead.git npm ERR! …

UE5 Windows打包时报错“SDK Not Found”解决方案

在Unreal Engine 5.0.3 Windows平台下打包时报错&#xff1a;“Windows的SDK未正常安装&#xff0c;而其是生成数据的必需项。请检查主工具栏中“启动“菜单SDK部分来更新SDK。” 解决方案&#xff1a; 1、打开 Visual Studio Installer&#xff0c;点击“修改”按钮&#xf…

【技术分享】远程透传网关-单网口快速实现西门子S7-1200/1500 PLC程序远程上下载

准备工作 一台可联网操作的电脑一台单网口的远程透传网关及博达远程透传配置工具网线一条&#xff0c;用于实现网络连接和连接PLC一台西门子S7-1200/1500 PLC及其编程软件一张4G卡或WIFI天线实现通讯(使用4G联网则插入4G SIM卡&#xff0c;WIFI联网则将WIFI天线插入USB口&…