当前位置: 首页 > news >正文

自然语言处理应用(三):微调BERT

微调BERT

微调(Fine-tuning)BERT是指在预训练的BERT模型基础上,使用特定领域或任务相关的数据对其进行进一步训练以适应具体任务的需求。BERT(Bidirectional Encoder Representations from Transformers)是一种基于Transformer架构的深度双向预训练语言模型,通过在大规模无监督数据上进行预训练,学习到了丰富的语言表示。

微调BERT的过程可以分为以下步骤:

  1. 准备数据集:根据任务或领域的需求,准备标注的训练数据集。数据集应包含输入文本以及相应的标签或目标。

  2. 加载预训练的BERT模型:从预训练的BERT模型中加载参数。这些参数包含了在大规模无监督数据上学习到的丰富语言表示。

  3. 构建模型结构:在加载预训练的BERT模型的基础上,构建任务特定的模型结构。通常,这涉及添加一个适当的分类器层,该层的输出与任务的类别数相匹配。

  4. 输入编码:将训练数据转换为BERT模型可以接受的输入格式。这包括将文本分割为标记、添加特殊标记如[CLS]和[SEP],并将其转换为对应的标记ID。

  5. 微调过程:使用准备好的训练数据对模型进行训练。通过将输入数据提供给模型,计算损失函数,并使用反向传播算法更新模型参数。常用的优化算法包括随机梯度下降(SGD)和Adam。

  6. 超参数调优:在微调过程中,可以根据需要调整学习率、批大小、训练轮数等超参数,以获得更好的性能。

  7. 模型评估:使用验证集或交叉验证方法评估微调后的模型性能。可以使用常见的评估指标,如准确率、精确度、召回率和F1分数。

  8. 推断和应用:在微调完成后,可以使用微调后的BERT模型进行推断和应用,输入新的未见过的文本数据,并生成相应的预测结果。

微调BERT的关键在于将预训练的语言模型参数与特定任务的数据进行结合,通过在任务数据上的有监督训练,使模型适应特定任务的需求,并提升在该任务上的性能表现。同时,由于BERT学习到了丰富的语言表示,在训练数据较少的情况下,微调BERT能够起到迁移学习的作用,从而提升模型的泛化能力。

文章内容来自李沐大神的《动手学深度学习》并加以我的理解,感兴趣可以去https://zh-v2.d2l.ai/查看完整书籍


文章目录

  • 微调BERT
  • 针对序列级和词元级应用微调BERT
    • 单文本分类
    • 文本对分类或回归
    • 文本标注
    • 问答
  • 自然语言推断:微调BERT
    • 加载BERT
    • 微调BERT的数据集
    • 微调BERT


针对序列级和词元级应用微调BERT

在本章的前几节中,我们为自然语言处理应用设计了不同的模型,例如基于循环神经网络、卷积神经网络、注意力和多层感知机。这些模型在有空间或时间限制的情况下是有帮助的,但是,为每个自然语言处理任务精心设计一个特定的模型实际上是不可行的。我们介绍了一个名为BERT的预训练模型,该模型可以对广泛的自然语言处理任务进行最少的架构更改。一方面,在提出时,BERT改进了各种自然语言处理任务的技术水平。另一方面,原始BERT模型的两个版本分别带有1.1亿和3.4亿个参数。因此,当有足够的计算资源时,我们可以考虑为下游自然语言处理应用微调BERT。

下面,我们将自然语言处理应用的子集概括为序列级和词元级。在序列层次上,介绍了在单文本分类任务和文本对分类(或回归)任务中,如何将文本输入的BERT表示转换为输出标签。在词元级别,我们将简要介绍新的应用,如文本标注和问答,并说明BERT如何表示它们的输入并转换为输出标签。在微调期间,不同应用之间的BERT所需的“最小架构更改”是额外的全连接层。在下游应用的监督学习期间,额外层的参数是从零开始学习的,而预训练BERT模型中的所有参数都是微调的。

单文本分类

单文本分类将单个文本序列作为输入,并输出其分类结果。 除了我们在这一章中探讨的情感分析之外,语言可接受性语料库(Corpus of Linguistic Acceptability,COLA)也是一个单文本分类的数据集,它的要求判断给定的句子在语法上是否可以接受。 (Warstadt et al., 2019)。例如,“I should study.”是可以接受的,但是“I should studying.”不是可以接受的。

在这里插入图片描述
BERT输入序列明确地表示单个文本和文本对,其中特殊分类标记“”用于序列分类,而特殊分类标记“”标记单个文本的结束或分隔成对文本。如图所示,在单文本分类应用中,特殊分类标记“”的BERT表示对整个输入文本序列的信息进行编码。作为输入单个文本的表示,它将被送入到由全连接(稠密)层组成的小多层感知机中,以输出所有离散标签值的分布。

文本对分类或回归

在本章中,我们还研究了自然语言推断。它属于文本对分类,这是一种对文本进行分类的应用类型。

以一对文本作为输入但输出连续值,语义文本相似度是一个流行的“文本对回归”任务。 这项任务评估句子的语义相似度。例如,在语义文本相似度基准数据集(Semantic Textual Similarity Benchmark)中,句子对的相似度得分是从0(无语义重叠)到5(语义等价)的分数区间 (Cer et al., 2017)。我们的目标是预测这些分数。来自语义文本相似性基准数据集的样本包括(句子1,句子2,相似性得分):

“A plane is taking off.”(“一架飞机正在起飞。”),“An air plane is taking off.”(“一架飞机正在起飞。”),5.000分;

“A woman is eating something.”(“一个女人在吃东西。”),“A woman is eating meat.”(“一个女人在吃肉。”),3.000分;

“A woman is dancing.”(一个女人在跳舞。),“A man is talking.”(“一个人在说话。”),0.000分。

在这里插入图片描述
图中的文本对分类的BERT微调在输入表示上有所不同。对于文本对回归任务(如语义文本相似性),可以应用细微的更改,例如输出连续的标签值和使用均方损失:它们在回归中很常见。

文本标注

现在让我们考虑词元级任务,比如文本标注(text tagging),其中每个词元都被分配了一个标签。在文本标注任务中,词性标注为每个单词分配词性标记(例如,形容词和限定词)。 根据单词在句子中的作用。如,在Penn树库II标注集中,句子“John Smith‘s car is new”应该被标记为“NNP(名词,专有单数)NNP POS(所有格结尾)NN(名词,单数或质量)VB(动词,基本形式)JJ(形容词)”。

在这里插入图片描述
图中说明了文本标记应用的BERT微调。唯一的区别在于,在文本标注中,输入文本的每个词元的BERT表示被送到相同的额外全连接层中,以输出词元的标签,例如词性标签。

问答

作为另一个词元级应用,问答反映阅读理解能力。 例如,斯坦福问答数据集(Stanford Question Answering Dataset,SQuAD v1.1)由阅读段落和问题组成,其中每个问题的答案只是段落中的一段文本(文本片段) (Rajpurkar et al., 2016)。举个例子,考虑一段话:“Some experts report that a mask’s efficacy is inconclusive.However,mask makers insist that their products,such as N95 respirator masks,can guard against the virus.”(“一些专家报告说面罩的功效是不确定的。然而,口罩制造商坚持他们的产品,如N95口罩,可以预防病毒。”)还有一个问题“Who say that N95 respirator masks can guard against the virus?”(“谁说N95口罩可以预防病毒?”)。答案应该是文章中的文本片段“mask makers”(“口罩制造商”)。因此,SQuAD v1.1的目标是在给定问题和段落的情况下预测段落中文本片段的开始和结束。
在这里插入图片描述
为了微调BERT进行问答,在BERT的输入中,将问题和段落分别作为第一个和第二个文本序列。为了预测文本片段开始的位置,相同的额外的全连接层将把来自位置 i i i的任何词元的BERT表示转换成标量分数 s i s_i si。文章中所有词元的分数还通过softmax转换成概率分布,从而为文章中的每个词元位置 i i i分配作为文本片段开始的概率 p i p_i pi。预测文本片段的结束与上面相同,只是其额外的全连接层中的参数与用于预测开始位置的参数无关。当预测结束时,位置 i i i的词元由相同的全连接层变换成标量分数 e i e_i ei。 上图描述了用于问答的微调BERT。

对于问答,监督学习的训练目标就像最大化真实值的开始和结束位置的对数似然一样简单。当预测片段时,我们可以计算从位置 i i i到位置 j j j的有效片段的分数 s i + e j s_i+e_j si+ej i < = j i<=j i<=j),并输出分数最高的跨度。

下面我们举一个例子微调BERT

自然语言推断:微调BERT

在本章的前面几节中,我们已经为SNLI数据集上的自然语言推断任务设计了一个基于注意力的结构。现在,我们通过微调BERT来重新审视这项任务。自然语言推断是一个序列级别的文本对分类问题,而微调BERT只需要一个额外的基于多层感知机的架构,如图中所示。在这里插入图片描述
本节将下载一个预训练好的小版本的BERT,然后对其进行微调,以便在SNLI数据集上进行自然语言推断。

加载BERT

原始的BERT模型有数以亿计的参数。在下面,我们提供了两个版本的预训练的BERT:“bert.base”与原始的BERT基础模型一样大,需要大量的计算资源才能进行微调,而“bert.small”是一个小版本,以便于演示。

import json
import multiprocessing
import os
import torch
from torch import nn
from d2l import torch as d2l
d2l.DATA_HUB['bert.base'] = (d2l.DATA_URL + 'bert.base.torch.zip','225d66f04cae318b841a13d32af3acc165f253ac')
d2l.DATA_HUB['bert.small'] = (d2l.DATA_URL + 'bert.small.torch.zip','c72329e68a732bef0452e4b96a1c341c8910f81f')

两个预训练好的BERT模型都包含一个定义词表的“vocab.json”文件和一个预训练参数的“pretrained.params”文件。我们实现了以下load_pretrained_model函数来加载预先训练好的BERT参数。

def load_pretrained_model(pretrained_model, num_hiddens, ffn_num_hiddens,num_heads, num_layers, dropout, max_len, devices):data_dir = d2l.download_extract(pretrained_model)# 定义空词表以加载预定义词表vocab = d2l.Vocab()vocab.idx_to_token = json.load(open(os.path.join(data_dir,'vocab.json')))vocab.token_to_idx = {token: idx for idx, token in enumerate(vocab.idx_to_token)}bert = d2l.BERTModel(len(vocab), num_hiddens, norm_shape=[256],ffn_num_input=256, ffn_num_hiddens=ffn_num_hiddens,num_heads=4, num_layers=2, dropout=0.2,max_len=max_len, key_size=256, query_size=256,value_size=256, hid_in_features=256,mlm_in_features=256, nsp_in_features=256)# 加载预训练BERT参数bert.load_state_dict(torch.load(os.path.join(data_dir,'pretrained.params')))return bert, vocab

为了便于在大多数机器上演示,我们将在本节中加载和微调经过预训练BERT的小版本(“bert.small”)。在练习中,我们将展示如何微调大得多的“bert.base”以显著提高测试精度。

微调BERT的数据集

对于SNLI数据集的下游任务自然语言推断,我们定义了一个定制的数据集类SNLIBERTDataset。在每个样本中,前提和假设形成一对文本序列,并被打包成一个BERT输入序列,片段索引用于区分BERT输入序列中的前提和假设。利用预定义的BERT输入序列的最大长度(max_len),持续移除输入文本对中较长文本的最后一个标记,直到满足max_len。为了加速生成用于微调BERT的SNLI数据集,我们使用4个工作进程并行生成训练或测试样本。

class SNLIBERTDataset(torch.utils.data.Dataset):def __init__(self, dataset, max_len, vocab=None):all_premise_hypothesis_tokens = [[p_tokens, h_tokens] for p_tokens, h_tokens in zip(*[d2l.tokenize([s.lower() for s in sentences])for sentences in dataset[:2]])]self.labels = torch.tensor(dataset[2])self.vocab = vocabself.max_len = max_len(self.all_token_ids, self.all_segments,self.valid_lens) = self._preprocess(all_premise_hypothesis_tokens)print('read ' + str(len(self.all_token_ids)) + ' examples')def _preprocess(self, all_premise_hypothesis_tokens):pool = multiprocessing.Pool(4)  # 使用4个进程out = pool.map(self._mp_worker, all_premise_hypothesis_tokens)all_token_ids = [token_ids for token_ids, segments, valid_len in out]all_segments = [segments for token_ids, segments, valid_len in out]valid_lens = [valid_len for token_ids, segments, valid_len in out]return (torch.tensor(all_token_ids, dtype=torch.long),torch.tensor(all_segments, dtype=torch.long),torch.tensor(valid_lens))def _mp_worker(self, premise_hypothesis_tokens):p_tokens, h_tokens = premise_hypothesis_tokensself._truncate_pair_of_tokens(p_tokens, h_tokens)tokens, segments = d2l.get_tokens_and_segments(p_tokens, h_tokens)token_ids = self.vocab[tokens] + [self.vocab['<pad>']] \* (self.max_len - len(tokens))segments = segments + [0] * (self.max_len - len(segments))valid_len = len(tokens)return token_ids, segments, valid_lendef _truncate_pair_of_tokens(self, p_tokens, h_tokens):# 为BERT输入中的'<CLS>'、'<SEP>'和'<SEP>'词元保留位置while len(p_tokens) + len(h_tokens) > self.max_len - 3:if len(p_tokens) > len(h_tokens):p_tokens.pop()else:h_tokens.pop()def __getitem__(self, idx):return (self.all_token_ids[idx], self.all_segments[idx],self.valid_lens[idx]), self.labels[idx]def __len__(self):return len(self.all_token_ids)

这是一个用于加载和预处理SNLI数据集的SNLIBERTDataset类,用于将数据集转换为适合BERT模型微调的格式。以下是该类的主要功能和方法:

  • __init__(self, dataset, max_len, vocab=None): 类的初始化方法,接受数据集、最大长度和词汇表作为参数,并进行预处理操作,包括分词、截断、转换为ID等。初始化时会打印读取的示例数量。

  • _preprocess(self, all_premise_hypothesis_tokens): 内部方法,用于多进程处理数据集中的所有前提和假设对。它调用_mp_worker方法处理每个前提和假设对,并返回转换后的token ID、segments和有效长度。

  • _mp_worker(self, premise_hypothesis_tokens): 内部方法,用于处理单个前提和假设对的token化、截断和转换为ID等操作。返回处理后的token ID、segments和有效长度。

  • _truncate_pair_of_tokens(self, p_tokens, h_tokens): 内部方法,用于根据最大长度对前提和假设对进行截断,以便适应BERT模型的输入格式。

  • __getitem__(self, idx): 用于获取数据集中特定索引处的样本和标签。返回的是模型所需的输入张量和相应的标签。

  • __len__(self): 返回数据集的样本数量。

all_premise_hypothesis_tokens是一个列表,其中包含了前提和假设对的tokenized表示。

具体地,all_premise_hypothesis_tokens列表是通过列表推导式生成的。每个列表元素都是一个包含两个子列表的元组,分别表示一个前提句子和一个假设句子的tokenized表示。这些tokenized表示是通过对输入的前提和假设对进行小写转换和分词操作生成的。

例如,假设输入的前提和假设对是:

dataset = [["The cat is on the mat.", "The cat is lying on the mat."],["She is reading a book.", "The girl is studying."],
]

经过处理后,all_premise_hypothesis_tokens的值将是:

[(["the", "cat", "is", "on", "the", "mat", "."], ["the", "cat", "is", "lying", "on", "the", "mat", "."]),(["she", "is", "reading", "a", "book", "."], ["the", "girl", "is", "studying", "."])
]

将所有句子词元化后,使用多线程的方法,调用_mp_worker方法对每个假设和前提进行处理和转换

具体而言,_mp_worker方法执行以下操作:

  1. 解包传入的premise_hypothesis_tokens元组,将前提和假设的tokenized表示分配给p_tokens和h_tokens变量。

  2. 调用_truncate_pair_of_tokens方法,根据设定的最大长度截断前提和假设的tokenized表示,以确保其长度不超过最大长度限制。

  3. 调用d2l.get_tokens_and_segments函数,将截断后的前提和假设的tokenized表示作为参数,获取它们的tokens和segments。tokens表示整个句子的token序列,segments表示句子的分段标识。

  4. 将tokens转换为对应的token ID,并使用词汇表进行查找。如果tokens的长度小于最大长度(self.max_len),则在末尾添加的ID,以使token_ids的长度与最大长度相同。

  5. 将segments的长度扩展到与最大长度相同,如果segments的长度小于最大长度,则在末尾添加0。

  6. 计算tokens的有效长度,即没有被截断的长度。

  7. 返回处理后的结果,即包含了token ID表示、segments表示和有效长度的元组(token_ids, segments, valid_len)。

下载完SNLI数据集后,我们通过实例化SNLIBERTDataset类来生成训练和测试样本。这些样本将在自然语言推断的训练和测试期间进行小批量读取。

# 如果出现显存不足错误,请减少“batch_size”。在原始的BERT模型中,max_len=512
batch_size, max_len, num_workers = 512, 128, d2l.get_dataloader_workers()
data_dir = d2l.download_extract('SNLI')
train_set = SNLIBERTDataset(d2l.read_snli(data_dir, True), max_len, vocab)
test_set = SNLIBERTDataset(d2l.read_snli(data_dir, False), max_len, vocab)
train_iter = torch.utils.data.DataLoader(train_set, batch_size, shuffle=True,num_workers=num_workers)
test_iter = torch.utils.data.DataLoader(test_set, batch_size,num_workers=num_workers)

这个地方可能会卡在train_set = SNLIBERTDataset(d2l.read_snli(data_dir, True), max_len, vocab)这一行,具体原因不知,可以尝试减少batch_size

微调BERT

用于自然语言推断的微调BERT只需要一个额外的多层感知机,该多层感知机由两个全连接层组成(请参见下面BERTClassifier类中的self.hidden和self.output)。这个多层感知机将特殊的“”词元的BERT表示进行了转换,该词元同时编码前提和假设的信息为自然语言推断的三个输出:蕴涵、矛盾和中性。

class BERTClassifier(nn.Module):def __init__(self, bert):super(BERTClassifier, self).__init__()self.encoder = bert.encoderself.hidden = bert.hiddenself.output = nn.Linear(256, 3)def forward(self, inputs):tokens_X, segments_X, valid_lens_x = inputsencoded_X = self.encoder(tokens_X, segments_X, valid_lens_x)return self.output(self.hidden(encoded_X[:, 0, :]))

在下文中,预训练的BERT模型bert被送到用于下游应用的BERTClassifier实例net中。在BERT微调的常见实现中,只有额外的多层感知机(net.output)的输出层的参数将从零开始学习。预训练BERT编码器(net.encoder)和额外的多层感知机的隐藏层(net.hidden)的所有参数都将进行微调。

net = BERTClassifier(bert)

MaskLM类和NextSentencePred类在其使用的多层感知机中都有一些参数。这些参数是预训练BERT模型bert中参数的一部分,因此是net中的参数的一部分。然而,这些参数仅用于计算预训练过程中的遮蔽语言模型损失和下一句预测损失。这两个损失函数与微调下游应用无关,因此当BERT微调时,MaskLM和NextSentencePred中采用的多层感知机的参数不会更新(陈旧的,staled)。

为了允许具有陈旧梯度的参数,标志ignore_stale_grad=True在step函数d2l.train_batch_ch13中被设置。我们通过该函数使用SNLI的训练集(train_iter)和测试集(test_iter)对net模型进行训练和评估。由于计算资源有限,训练和测试精度可以进一步提高:我们把对它的讨论留在练习中。

虽然书中这么写,但是我并没有找到哪里设置了ignore_stale_grad,这里应该仍然微调了所有的参数

lr, num_epochs = 1e-4, 5
trainer = torch.optim.Adam(net.parameters(), lr=lr)
loss = nn.CrossEntropyLoss(reduction='none')
d2l.train_ch13(net, train_iter, test_iter, loss, trainer, num_epochs,devices)

在这里插入图片描述

相关文章:

自然语言处理应用(三):微调BERT

微调BERT 微调&#xff08;Fine-tuning&#xff09;BERT是指在预训练的BERT模型基础上&#xff0c;使用特定领域或任务相关的数据对其进行进一步训练以适应具体任务的需求。BERT&#xff08;Bidirectional Encoder Representations from Transformers&#xff09;是一种基于Tr…...

MySQL基础【学习至基本语句】

一、安装与配置 1、安装 yum install -y mysql-server.x86_642、MySQL安装完成后&#xff0c;启动报错&#xff0c;查看MySQL的状态&#xff0c;发现是3306端口被占用 [rootiZ56kkvaq4nlfhZ etc]# systemctl status mysqld.service ● mysqld.service - MySQL 8.0 database …...

Leetcode152. 连续子数组的最大乘积

力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 给你一个整数数组 nums &#xff0c;请你找出数组中乘积最大的非空连续子数组&#xff08;该子数组中至少包含一个数字&#xff09;&#xff0c;并返回该子数组所对应的乘积。 测试用例的答案是一个 32…...

01_kafka_环境搭建安装_topic管理

文章目录 安装jdk配置主机名Zookeeper 下载与安装Kafka 下载与安装测试集群版安装测试输出 安装jdk 略 配置主机名 hostnamectl set-hostname kafka_1 /etc/sysconfig/network HOSTNAMEkafka_1/etc/hosts ip kafka_1ping kafka_1 测试 Zookeeper 下载与安装 由于 集群…...

Python+Requests+Excel接口测试实战

1、EXCEL文件接口保存方式&#xff0c;如图。 2、然后就是读取EXCEL文件中的数据方法&#xff0c;如下&#xff1a; 1 import xlrd2 3 4 class readExcel(object):5 def __init__(self, path):6 self.path path7 8 property9 def getSheet(self): 10 …...

10:STM32------I2C通信

目录​​​​​​​ 一:I2C通信协议 1:I2C简历 2:硬件电路 3:I2C时序基本单元 A : 开/ 终条件 2:发送一个字节 3:接收一个字节 4:应答机制 4:I2C时序 1:指定地址写 2:当前地址读 3: 指定地址读 二:MPU6050 1:简历 2:参数 3:硬件电路 4:框图 5:寄存器地址 …...

Git多人开发解决冲突案例

准备工作&#xff1a; 1.创建一个gitee远程仓库https://gitee.com/xxxxxxx.git 2.初始化两个本地git仓库用户&#xff0c;目的是模拟多人协作开发时提交代码发生冲突的场景 3.解决冲突并提交。 进入正题&#xff1a; lisi 通过vim指令修改readme.md文件内容&#xff0c;推送到…...

医疗机构如何维护电力系统?来看看这个小技巧

在现代医疗领域&#xff0c;电力是不可或缺的。从手术室里的手术灯到病房中的呼吸机&#xff0c;医院的各种医疗设备和系统都依赖于稳定的电源供应。 然而&#xff0c;电力中断和紧急情况不可避免&#xff0c;而这些情况下的电力可靠性可能会直接影响病人的生命和健康。为了确保…...

时序预测 | MATLAB实现ELM极限学习机时间序列预测未来

时序预测 | MATLAB实现ELM极限学习机时间序列预测未来 目录 时序预测 | MATLAB实现ELM极限学习机时间序列预测未来预测效果基本介绍程序设计参考资料 预测效果 基本介绍 1.MATLAB实现ELM极限学习机时间序列预测未来&#xff1b; 2.运行环境Matlab2018及以上&#xff0c;data为数…...

【数据分享】1901-2022年我国省市县镇四级的逐年平均气温数据(免费获取/Shp/Excel格式)

气象数据在日常研究中非常常用&#xff0c;之前我们分享过来自国家青藏高原科学数据中心提供的1901-2022年1km分辨率逐月平均气温栅格数据&#xff0c;2001-2022年我国省市县镇四级的逐月平均气温数据&#xff0c;以及基于该栅格数据处理得到的1901-2022年1km分辨率的逐年平均气…...

【Axure高保真原型】日历日期原型模板

今天和大家分享日历日期的原型模板&#xff0c;包括月计划、周计划、日计划的原型案例&#xff0c;以及日期、时间、月份、区间选择器……具体效果可以点击下方视频观看 【原型预览及下载地址】 Axure 原型 备用地址&#xff1a;Untitled Document 【原型效果】 【原型效果…...

深入了解接口测试:Postman 接口测试指南

在现代软件开发生命周期中&#xff0c;接口测试是一个至关重要的部分。使用 Postman 这一工具&#xff0c;可以轻松地进行 接口测试。以下是一份简单的使用教程&#xff0c;帮助你快速上手。 安装 Postman 首先&#xff0c;你需要在电脑上安装 Postman。你可以从官网上下载并…...

【ROS】Ubuntu20.04+ROS Noetic 配置PX4-v1.12.2和Gazebo11联合仿真环境【教程】

【ROS】Ubuntu20.04ROS Noetic 配置PX4-v-v1.12.2和Gazebo11联合仿真环境【教程】 文章目录 【ROS】Ubuntu20.04ROS Noetic 配置PX4-v-v1.12.2和Gazebo11联合仿真环境【教程】0. 安装UbuntuROS1. 安装依赖2. 安装QGC地面站3. 配置PX4-v1.12.23.1 安装PX43.2 测试PX4是否成功安装…...

Java 代理模式之静态代理与动态代理

1&#xff0c;代理模式 代理模式给某一个对象提供一个代理对象&#xff0c;并由代理对象控制对原对象的引用。通俗的来讲代理模式就是我们生活中常见的中介。 代理模式的目的&#xff1a; &#xff08;1&#xff09;通过引入代理对象的方式来间接访问目标对象&#xff0c;防…...

打造基于终端命令行的IDE,Termux配置Vim C++开发环境

Termux配置Vim C开发环境&#xff0c;打造基于终端命令行的IDE 主要利用VimCoc插件&#xff0c;配置C的代码提示等功能。 Termux换源 打开termux&#xff0c;输入termux-change-repo 找到mirrors.tuna.tsinghua.edu.cn&#xff0c;清华源&#xff0c;空格选中&#xff0c;回…...

【初阶C语言】操作符2---表达式求值

前言&#xff1a;本节重点介绍操作符的使用&#xff0c;如&#xff0c;优先级高低、类型转换等 一、逻辑操作符 前言&#xff1a;逻辑操作符包括逻辑与&#xff08;&&&#xff09;和逻辑或&#xff08;||&#xff09;&#xff0c;操作对象&#xff1a;两个 1.逻辑与&…...

代码随想录day50|123. 买卖股票的最佳时机 III188. 买卖股票的最佳时机 IV

123. 买卖股票的最佳时机 III class Solution:def maxProfit(self, prices: List[int]) -> int:dp[[0]*5 for _ in range(len(prices))]dp[0][0]0dp[0][1]-prices[0]dp[0][2]0dp[0][3]-prices[0]dp[0][4]0for i in range(1,len(prices)):dp[i][0] dp[i-1][0]dp[i][1] max…...

Word 表格单元格无法垂直居中

Word使用 由于平时也需要用到word编写一些文档&#xff0c;但是咱们就是用的少&#xff0c;很多操作或者技巧不太清楚&#xff0c;很多小问题处理起来反而需要消耗很多时间&#xff0c;所以在这里记录平时遇到的一些问题。 表格无法垂直居中 类似于上图的情况&#xff0c;总之…...

python实现Flask POST Demo

数据处理逻辑 from flask import Flask, requestapp Flask(__name__)app.route(/, methods[POST]) def index():username request.form[username]password request.form[password]if username "Jhon" and password "1":return f"<html>&l…...

3-Pytorch张量的运算、形状改变、自动微分

3-Pytorch张量的运算、形状改变、自动微分 1 导入必备库2 张量的运算3 张量的算数运算4 一个元素的张量可以使用tensor.item()方法转成标量5 torch.from_numpy()和tensor.numpy()6 张量的变形7 张量的自动微分8 使用with torch.no_grad():包含上下文中使其不再跟踪计算9 使用te…...

用户权限数据转换为用户组列表(3/3) - Excel PY公式

最近Excel圈里的大事情就是微软把PY塞进了Excel单元格&#xff0c;可以作为公式使用&#xff0c;轻松用PY做数据分析。系好安全带&#xff0c;老司机带你玩一把。 实例需求&#xff1a;如下是AD用户的列表,每个用户拥有该应用程序的只读或读写权限&#xff0c;现在需要创建新的…...

VS2022+CMAKE+OPENCV+QT+PCL安装及环境搭建

VS2022安装&#xff1a; Visual Studio 2022安装教程&#xff08;千字图文详解&#xff09;&#xff0c;手把手带你安装运行VS2022以及背景图设置_vs安装教程_我不是大叔丶的博客-CSDN博客 CMAKE配置&#xff1a; win11下配置vscodecmake_心儿痒痒的博客-CSDN博客 OPENCV配…...

JavaScript的内置类

一、认识包装类型 1.原始类型的包装类 JavaScript的原始类型并非对象类型&#xff0c;所以从理论上来说&#xff0c;它们是没有办法获取属性或者调用方法的。 但是&#xff0c;在开发中会看到&#xff0c;我们会经常这样操作&#xff1a; var message "hello world&q…...

6.英语的十六种时态(三面旗):主动、被动、肯定、否定、一般疑问句、特殊疑问句。

目录 一、do句型&#xff08;以动词allow举例&#xff09;。 &#xff08;1&#xff09;主动语态表格。 &#xff08;2&#xff09;被动语态表格。 &#xff08;3&#xff09;否定。 二、be句型&#xff08;表格里的时态可以参考&#xff0c;查不到对应的资料&#xff09;…...

SpringBoot连接Redis与Redisson【代码】

系列文章目录 一、SpringBoot连接MySQL数据库实例【tk.mybatis连接mysql数据库】 二、SpringBoot连接Redis与Redisson【代码】 三、SpringBoot整合WebSocket【代码】 四、SpringBoot整合ElasticEearch【代码示例】 文章目录 系列文章目录代码下载地地址一、引入依赖二、修改配…...

ardupilot开发 --- MAVSDK 篇

概述 MAVSDK是各种编程语言的库集合&#xff0c;用于与MAVLink系统&#xff08;如无人机、相机或地面系统&#xff09;接口。这些库提供了一个简单的API&#xff0c;用于管理一个或多个车辆&#xff0c;提供对车辆信息和遥测的程序访问&#xff0c;以及对任务、移动和其他操作…...

腾讯云AI超级底座新升级:训练效率提升幅度达到3倍

大模型推动AI进入新纪元&#xff0c;对计算、存储、网络、数据检索及调度容错等方面提出了更高要求。在9月7日举行的2023腾讯全球数字生态大会“AI超级底座专场”上&#xff0c;腾讯云介绍异构计算全新产品矩阵“AI超级底座”及其新能力。 腾讯云副总裁王亚晨在开场致辞中表示&…...

AB测试结果分析

一、假设检验 根据样本&#xff08;小流量&#xff09;的观测结果&#xff0c;拒绝或接受关于总体&#xff08;全部流量&#xff09;的某个假设&#xff0c;称为假设检验。 假设检验的基本依据是小概率事件原理&#xff08;小概率事件几乎不发生&#xff09;&#xff0c;如果…...

Python模块和包:sys模块、os模块和变量函数的使用

文章目录 模块&#xff08;module&#xff09;引入外部模块引入部分内容包 (package)示例代码开箱即用sys模块sys.argvsys.modulessys.pathsys.platformsys.exit() os模块os.environos.system()os模块中的变量、函数和类 测试代码模块中的变量和函数的使用 总结&#xff1a;pyt…...

计算机软件工程毕业设计题目推荐

文章目录 0 简介1 如何选题2 最新软件工程毕设选题3 最后 0 简介 学长搜集分享最新的软件工程业专业毕设选题&#xff0c;难度适中&#xff0c;适合作为毕业设计&#xff0c;大家参考。 学长整理的题目标准&#xff1a; 相对容易工作量达标题目新颖 1 如何选题 最近非常多的…...

用jsp做网站一般会用到什么/磁力狗在线搜索

欢迎大家分享自己的文档&#xff0c;请点击查阅&#xff1a;分享方法,如果你喜欢这文章&#xff0c;可以点击文章结尾处百度分享&#xff0c;分享到你的各种社区收藏&#xff0c;或推荐给朋友……linux工作手册释放内存&#xff1a;syncecho 3 > /proc/sys/vm/drop_cachesLi…...

哪些网站可以做视频收费/百度投诉中心电话24个小时

CodeIgniter源码分析之CodeIgniter.php <?php if ( ! defined(BASEPATH)) exit(No direct script access allowed); /** * 上面&#xff1a; * 这个BASEPATH&#xff0c;就是在入口文件(index.php)里面定义的那个BASEPATH&#xff5e; * 如果没有定义BASEPATH&…...

做聊天网站的视频教程/seo搜索优化是什么呢

8月27日消息&#xff0c;二手时尚电商平台Plum近日完成数千万美元B 轮融资&#xff0c;本轮融资由经纬中国领投&#xff0c;启明创投以及IDG资本、九合创投、险峰长青等原老股东跟投。去年9 月团队就获得了IDG 资本、经纬中国和险峰长青的A 轮融资。 Plum于2017 年2 月上线&am…...

国外经典平面设计网站/自己的网站怎么建立

终于&#xff0c;进入了JavaScript的学习环节 首先列举一些常用的关键词&#xff0c;并说明含义 var 声明变量function 声明函数switch 选择不同执行情况break 终止 switch 或循环return 退出函数try … catch 对语句块实现错误处理do … while 执行语句&#xff0c;条件为真执…...

石家庄网站建设外贸/百度推广网页版

namespace Coldairarrow.Util {public class ErrorResult : AjaxResult{public ErrorResult(string msg "操作失败!", int errorCode 0){Msg msg;Success false;ErrorCode errorCode;}} }...

四川省城乡建设厅门户网站/大地资源网在线观看免费

上一篇唯一插件化Replugin源码及原理深度剖析–初始化之框架核心&#xff0c;我们说了Replugin的整体框架的初始化&#xff0c;但是因为篇幅的缘故还有Hook系统的ClassLoader和插件的加载没有说&#xff0c;那么我们这一篇就来详解的来分析一下Hook这块&#xff0c;本章我们讲从…...