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

[oneAPI] 基于BERT预训练模型的命名体识别任务

[oneAPI] 基于BERT预训练模型的命名体识别任务

  • Intel® DevCloud for oneAPI 和 Intel® Optimization for PyTorch
  • 基于BERT预训练模型的命名体识别任务
    • 语料介绍
      • 数据集构建
      • 使用示例
    • 命名体识别模型
      • 前向传播
      • 模型训练
    • 结果
  • 参考资料

比赛:https://marketing.csdn.net/p/f3e44fbfe46c465f4d9d6c23e38e0517
Intel® DevCloud for oneAPI:https://devcloud.intel.com/oneapi/get_started/aiAnalyticsToolkitSamples/

Intel® DevCloud for oneAPI 和 Intel® Optimization for PyTorch

在本次实验中,我们在Intel® DevCloud for oneAPI上搭建实验,借助完全虚拟化的环境,专注于模型开发与优化,无需关心底层配置。使用Intel® Optimization for PyTorch,对PyTorch模型进行高效优化。

我们充分发挥了PyTorch和Intel® Optimization for PyTorch的强大功能,经过仔细的优化和拓展。这些优化措施极大地提升了PyTorch在各种任务中的性能,尤其是在英特尔硬件上的表现更为卓越。通过这些优化方法,我们的模型在训练和推断过程中变得更加敏捷高效,大幅缩短了计算时间,从而提升了整体效率。借助深度融合硬件与软件的巧妙设计,我们成功地释放了硬件潜力,使模型的训练和应用变得更加迅速高效。这些优化举措为人工智能应用开辟了崭新的前景,带来了全新的可能性。
在这里插入图片描述

基于BERT预训练模型的命名体识别任务

基于BERT预训练模型的第五个下游任务场景,即如何完成命名体识别(Named Entity Recognition, NER)任务。所谓命名体指的是给模型输入一句文本,最后需要模型将其中的实体(例如人名、地名、组织等等)标记出来。

1 句子:涂伊说,如果有机会他想去黄州赤壁看一看!
2 标签:['B-PER', 'I-PER', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'B-LOC', 'I-LOC', 'B-LOC', 'I-LOC', 'O', 'O', 'O', 'O']
3 实体:涂伊(人名)、黄州(地名)、赤壁(地名)

通常来讲,对于任意一个NLP任务来说模型最后所要完成的基本上都是一个分类任务,尽管表面上看起来可能不太像。根据给出的标签来看,对于原始句子中的每个字符来说其都有一个对应的类别标签,因此对于NER任务来说只需要对原始句子里的每个字符进行分类即可,然后再将预测后的结果进行后处理便能够得到句子从存在的相应实体。

原始数据输入为一个句子,我们只需要在句子的首尾分别加上[CLS]和[SEP],然后输入到模型当中进行特征提取并最终通过一个分类层对输出的每个Token进行分类即可,最后只需要对各个Token的预测结果进行后处理便能够实现整个NER任务。

语料介绍

一个中文命名体识别数据集https://github.com/zjy-ucas/ChineseNER,如下所示便是原始数据的存储形式:

 1 涂 B-PER2 伊 I-PER3 说 O4 , O5 如 O6 果 O7 有 O8 机 O9 会 O
10 他 O
11 想 O
12 去 O
13 黄 B-LOC
14 州 I-LOC
15 赤 B-LOC
16 壁 I-LOC
17 看 O
18 一 O
19 看 O
20 !O

其中每一行包含一个字符和其对应的所属类别,B-表示该类实体的开始标志,I-表示该类实体的延续标志。例如对于13-16行来说其对应了“黄州”和“赤壁”这两个实体。同时,对于这个数据集来说,其一共包含有3类实体(人名、地名和组织),因此其对应的分类总数便为7,如下所示:

1 {'O': 0, 'B-ORG': 1, 'B-LOC': 2, 'B-PER': 3, 'I-ORG': 4, 'I-LOC': 5, 'I-PER': 6}

对于数据预处理部分我们可以继续继承之前文本分类处理中的LoadSingleSentenceClassificationDataset类,然后再稍微修改其中的部分方法即可。

数据集构建

在说完数据集构造的整理思路后,下面我们就来正式编码实现整个数据集的构造过程。同样,对于数据预处理部分我们可以继续继承之前文本分类处理中的LoadSingleSentenceClassificationDataset类,然后再稍微修改其中的部分方法即可。

class LoadChineseNERDataset(LoadSingleSentenceClassificationDataset):def __init__(self, entities=None, num_labels=None, ignore_idx=-100, **kwargs):super(LoadChineseNERDataset, self).__init__(**kwargs)self.entities = entitiesself.num_labels = num_labelsself.IGNORE_IDX = ignore_idxif self.entities is None or self.num_labels is None:raise ValueError(f"类 {self.__class__.__name__} 中参数 entities 或 num_labels 不能为空!")@cachedef data_process(self, filepath, postfix='cache'):raw_iter = open(filepath, encoding="utf8").readlines()data = []max_len = 0tmp_token_ids = []tmp_sentence = ""tmp_label = []tmp_entity = []for raw in tqdm(raw_iter, ncols=80):line = raw.rstrip("\n").split(self.split_sep)if len(line) != 1 and len(line) != 2:raise ValueError(f"数据标注有误{line}")if len(line) == 1:  # 表示得到一个完整的token id样本if len(tmp_token_ids) > self.max_position_embeddings - 2:tmp_token_ids = tmp_token_ids[:self.max_position_embeddings - 2]tmp_label = tmp_label[:self.max_position_embeddings - 2]max_len = max(max_len, len(tmp_label) + 2)token_ids = torch.tensor([self.CLS_IDX] + tmp_token_ids +[self.SEP_IDX], dtype=torch.long)labels = torch.tensor([self.IGNORE_IDX] + tmp_label +[self.IGNORE_IDX], dtype=torch.long)data.append([tmp_sentence, token_ids, labels])logging.debug(" ### 样本构造结果为:")logging.debug(f"   ## 句子: {tmp_sentence}")logging.debug(f"   ## 实体: {tmp_entity}")logging.debug(f"   ## input_ids: {token_ids.tolist()}")logging.debug(f"   ## label: {labels.tolist()}")logging.debug(f" ================================\n")assert len(tmp_token_ids) == len(tmp_label)tmp_token_ids = []tmp_sentence = ""tmp_label = []tmp_entity = []continuetmp_sentence += line[0]tmp_token_ids.append(self.vocab[line[0]])tmp_label.append(self.entities[line[-1]])tmp_entity.append(line[-1])return data, max_lendef generate_batch(self, data_batch):batch_sentence, batch_token_ids, batch_label = [], [], []for (sen, token_ids, label) in data_batch:  # 开始对一个batch中的每一个样本进行处理。batch_sentence.append(sen)batch_token_ids.append(token_ids)batch_label.append(label)batch_token_ids = pad_sequence(batch_token_ids,  # [batch_size,max_len]padding_value=self.PAD_IDX,batch_first=False,max_len=self.max_sen_len)batch_label = pad_sequence(batch_label,  # [batch_size,max_len]padding_value=self.IGNORE_IDX,batch_first=False,max_len=self.max_sen_len)# ① 因为label的长度各不相同,所以同一个batch中的label需要padding到相同的长度;# ② 因为进行了padding操作,所以在计算损失的时候需要把padding部分的损失忽略掉;# ③ 又因为label中有0这个类别的存在,所以不能用词表中的PAD_IDX进行padding(PAD_IDX为0),所以要另外取一个IGNORE_IDXreturn batch_sentence, batch_token_ids, batch_labeldef make_inference_samples(self, sentences):if not isinstance(sentences, list):sentences = [sentences]data = []for sen in sentences:tokens = [self.vocab[word] for word in sen]label = [-1] * len(tokens)token_ids = torch.tensor([self.CLS_IDX] + tokens + [self.SEP_IDX], dtype=torch.long)labels = torch.tensor([self.IGNORE_IDX] + label + [self.IGNORE_IDX], dtype=torch.long)data.append([sen, token_ids, labels])return self.generate_batch(data)

使用示例

在完成数据集构造部分的相关代码实现之后,便可以通过如下所示的方式进行使用,代码如下:

class ModelConfig:def __init__(self):self.project_dir = os.path.dirname(os.path.abspath(__file__))self.dataset_dir = os.path.join(self.project_dir, 'ChineseNERdata')self.pretrained_model_dir = os.path.join(self.project_dir, "pretraining")self.vocab_path = os.path.join(self.pretrained_model_dir, 'vocab.txt')self.device = torch.device('xpu' if torch.cuda.is_available() else 'cpu')self.train_file_path = os.path.join(self.dataset_dir, 'example_train.txt')self.val_file_path = os.path.join(self.dataset_dir, 'example_dev.txt')self.test_file_path = os.path.join(self.dataset_dir, 'example_test.txt')self.model_save_dir = os.path.join(self.project_dir, 'cache')self.model_save_name = "ner_model.pt"self.logs_save_dir = os.path.join(self.project_dir, 'logs')self.split_sep = ' 'self.is_sample_shuffle = Trueself.batch_size = 6self.max_sen_len = Noneself.epochs = 10self.learning_rate = 1e-5self.model_val_per_epoch = 2self.entities = {'O': 0, 'B-ORG': 1, 'B-LOC': 2, 'B-PER': 3, 'I-ORG': 4, 'I-LOC': 5, 'I-PER': 6}self.num_labels = len(self.entities)self.ignore_idx = -100logger_init(log_file_name='ner', log_level=logging.DEBUG,log_dir=self.logs_save_dir)if not os.path.exists(self.model_save_dir):os.makedirs(self.model_save_dir)# 把原始bert中的配置参数也导入进来bert_config_path = os.path.join(self.pretrained_model_dir, "config.json")bert_config = BertConfig.from_json_file(bert_config_path)for key, value in bert_config.__dict__.items():self.__dict__[key] = value# 将当前配置打印到日志文件中logging.info(" ### 将当前配置打印到日志文件中 ")for key, value in self.__dict__.items():logging.info(f"###  {key} = {value}")

命名体识别模型

前向传播

我们只需要在原始BERT模型的基础上再加一个对所有Token进行分类的分类层即可,因此这部分代码相对来说也比较容易理解。首先需要在DownstreamTasks目录下新建一个BertForTokenClassification模块,并完成整个模型的初始化和前向传播过程,代码如下:

from ..BasicBert.Bert import BertModel
import torch.nn as nnclass BertForTokenClassification(nn.Module):def __init__(self, config, bert_pretrained_model_dir=None):super(BertForTokenClassification, self).__init__()self.num_labels = config.num_labelsif bert_pretrained_model_dir is not None:self.bert = BertModel.from_pretrained(config, bert_pretrained_model_dir)else:self.bert = BertModel(config)self.dropout = nn.Dropout(config.hidden_dropout_prob)self.classifier = nn.Linear(config.hidden_size, self.num_labels)self.config = configdef forward(self,input_ids=None,attention_mask=None,token_type_ids=None,position_ids=None,labels=None):""":param input_ids: [src_len,batch_size]:param attention_mask: [batch_size, src_len]:param token_type_ids::param position_ids::param labels: [src_len,batch_size]:return:"""_, all_encoder_outputs = self.bert(input_ids=input_ids,attention_mask=attention_mask,token_type_ids=token_type_ids,position_ids=position_ids)  # [batch_size,hidden_size]sequence_output = all_encoder_outputs[-1]  # 取最后一层# sequence_output: [src_len, batch_size, hidden_size]sequence_output = self.dropout(sequence_output)logits = self.classifier(sequence_output)# logit: [src_len, batch_size, num_labels]if labels is not None:  # [src_len,batch_size]loss_fct = nn.CrossEntropyLoss(ignore_index=self.config.ignore_idx)loss = loss_fct(logits.view(-1, self.num_labels), labels.view(-1))return loss, logitselse:return logits

模型训练

对于模型训练这部分内容来说,首先我们需要在Tasks目录下新建一个TaskForChineseNER.py模块,并新建一个配置类ModelConfig来管理整个模型需要用到的参数,代码实现如下:

class ModelConfig:def __init__(self):self.project_dir = os.path.dirname(os.path.abspath(__file__))self.dataset_dir = os.path.join(self.project_dir, 'ChineseNERdata')self.pretrained_model_dir = os.path.join(self.project_dir, "pretraining")self.vocab_path = os.path.join(self.pretrained_model_dir, 'vocab.txt')self.device = torch.device('xpu' if torch.cuda.is_available() else 'cpu')self.train_file_path = os.path.join(self.dataset_dir, 'example_train.txt')self.val_file_path = os.path.join(self.dataset_dir, 'example_dev.txt')self.test_file_path = os.path.join(self.dataset_dir, 'example_test.txt')self.model_save_dir = os.path.join(self.project_dir, 'cache')self.model_save_name = "ner_model.pt"self.logs_save_dir = os.path.join(self.project_dir, 'logs')self.split_sep = ' 'self.is_sample_shuffle = Trueself.batch_size = 6self.max_sen_len = Noneself.epochs = 10self.learning_rate = 1e-5self.model_val_per_epoch = 2self.entities = {'O': 0, 'B-ORG': 1, 'B-LOC': 2, 'B-PER': 3, 'I-ORG': 4, 'I-LOC': 5, 'I-PER': 6}self.num_labels = len(self.entities)self.ignore_idx = -100logger_init(log_file_name='ner', log_level=logging.DEBUG,log_dir=self.logs_save_dir)if not os.path.exists(self.model_save_dir):os.makedirs(self.model_save_dir)# 把原始bert中的配置参数也导入进来bert_config_path = os.path.join(self.pretrained_model_dir, "config.json")bert_config = BertConfig.from_json_file(bert_config_path)for key, value in bert_config.__dict__.items():self.__dict__[key] = value# 将当前配置打印到日志文件中logging.info(" ### 将当前配置打印到日志文件中 ")for key, value in self.__dict__.items():logging.info(f"###  {key} = {value}")

因为在模型训练过程中需要计算相关的评价指标,如准确率、精确率和召回率等,因此需要对这部分进行实现,代码如下

def accuracy(logits, y_true, ignore_idx=-100):""":param logits:  [src_len,batch_size,num_labels]:param y_true:  [src_len,batch_size]:param ignore_idx: 默认情况为-100:return:e.g.y_true = torch.tensor([[-100, 0, 0, 1, -100],[-100, 2, 0, -100, -100]]).transpose(0, 1)logits = torch.tensor([[[0.5, 0.1, 0.2], [0.5, 0.4, 0.1], [0.7, 0.2, 0.3], [0.5, 0.7, 0.2], [0.1, 0.2, 0.5]],[[0.3, 0.2, 0.5], [0.7, 0.2, 0.4], [0.8, 0.1, 0.3], [0.9, 0.2, 0.1], [0.1, 0.5, 0.2]]])logits = logits.transpose(0, 1)print(accuracy(logits, y_true, -100)) # (0.8, 4, 5)"""y_pred = logits.transpose(0, 1).argmax(axis=2).reshape(-1).tolist()# 将 [src_len,batch_size,num_labels] 转成 [batch_size, src_len,num_labels]y_true = y_true.transpose(0, 1).reshape(-1).tolist()real_pred, real_true = [], []for item in zip(y_pred, y_true):if item[1] != ignore_idx:real_pred.append(item[0])real_true.append(item[1])return accuracy_score(real_true, real_pred), real_true, real_pred

为了能够在模型训练或推理过程中输入模型的预测结果,因此我们需要实现3个辅助函数来完成。首先需要实现根据logits和input_token_ids来得到每个预测值对应的实体标签,代码如下:

def get_ner_tags(logits, token_ids, entities, SEP_IDX=102):""":param logits:  [src_len,batch_size,num_samples]:param token_ids: # [src_len,batch_size]:return:e.g.logits = torch.tensor([[[0.4, 0.7, 0.2],[0.5, 0.4, 0.1],[0.1, 0.2, 0.3],[0.5, 0.7, 0.2],[0.1, 0.2, 0.5]],[[0.3, 0.2, 0.5],[0.7, 0.8, 0.4],[0.1, 0.1, 0.3],[0.9, 0.2, 0.1],[0.1, 0.5,0.2]]])logits = logits.transpose(0, 1)  # [src_len,batch_size,num_samples]token_ids = torch.tensor([[101, 2769, 511, 102, 0],[101, 56, 33, 22, 102]]).transpose(0, 1)  # [src_len,batch_size]labels, probs = get_ner_tags(logits, token_ids, entities)[['O', 'B-LOC'], ['B-ORG', 'B-LOC', 'O']][[0.5, 0.30000001192092896], [0.800000011920929, 0.30000001192092896, 0.8999999761581421]]"""# entities = {'O': 0, 'B-ORG': 1, 'B-LOC': 2, 'B-PER': 3, 'I-ORG': 4, 'I-LOC': 5, 'I-PER': 6}label_list = list(entities.keys())logits = logits[1:].transpose(0, 1)  # [batch_size,src_len-1,num_samples]prob, y_pred = torch.max(logits, dim=-1)  # prob, y_pred: [batch_size,src_len-1]token_ids = token_ids[1:].transpose(0, 1)  # [ batch_size,src_len-1], 去掉[cls]assert y_pred.shape == token_ids.shapelabels = []probs = []for sample in zip(y_pred, token_ids, prob):tmp_label, tmp_prob = [], []for item in zip(*sample):if item[1] == SEP_IDX:  # 忽略最后一个[SEP]字符breaktmp_label.append(label_list[item[0]])tmp_prob.append(item[2].item())labels.append(tmp_label)probs.append(tmp_prob)return labels, probs

进一步,在得到每个输入句子的预测结果后,还需要将其进行格式化处理得到最终的预测结果,实现代码如下:

def pretty_print(sentences, labels, entities):""":param sentences::param labels::param entities::return:e.g.labels = [['B-PER','I-PER', 'O','O','O','O','O','O','O','O','O','O','B-LOC','I-LOC','B-LOC','I-LOC','O','O','O','O'],['B-LOC','I-LOC','O','B-LOC','I-LOC','O','B-LOC','I-LOC','I-LOC','O','B-LOC','I-LOC','O','O','O','B-PER','I-PER','O','O','O','O','O','O']]sentences=["涂伊说,如果有机会他想去赤壁看一看!","丽江、大理、九寨沟、黄龙等都是涂伊想去的地方!"]entities = {'O': 0, 'B-ORG': 1, 'B-LOC': 2, 'B-PER': 3, 'I-ORG': 4, 'I-LOC': 5, 'I-PER': 6}句子:涂伊说,如果有机会他想去黄州赤壁看一看!涂伊:  PER黄州:  LOC赤壁:  LOC句子:丽江、大理、九寨沟、黄龙等都是涂伊想去的地方!丽江:  LOC大理:  LOC九寨沟:  LOC黄龙:  LOC涂伊:  PER"""sep_tag = [tag for tag in list(entities.keys()) if 'I' not in tag]result = []for sen, label in zip(sentences, labels):logging.info(f"句子:{sen}")last_tag = Nonefor item in zip(sen + "O", label + ['O']):if item[1] in sep_tag:  #if len(result) > 0:entity = "".join(result)logging.info(f"\t{entity}:  {last_tag.split('-')[-1]}")result = []if item[1] != 'O':result.append(item[0])last_tag = item[1]else:result.append(item[0])last_tag = item[1]

输出结果如下:

1 句子:涂伊说,如果有机会他想去黄州赤壁看一看!2 涂伊:  PER3 黄州:  LOC4 赤壁:  LOC5 句子:丽江、大理、九寨沟、黄龙等都是涂伊想去的地方!6 丽江:  LOC7 大理:  LOC8 九寨沟:  LOC9 黄龙:  LOC
10 涂伊:  PER

在完成上述所有铺垫之后,便可以来实现模型的训练部分,代码如下(下面只摘录核心部分进行介绍):

def train(config):model = BertForTokenClassification(config,config.pretrained_model_dir)model_save_path = os.path.join(config.model_save_dir,config.model_save_name)global_steps = 0if os.path.exists(model_save_path):checkpoint = torch.load(model_save_path)global_steps = checkpoint['last_epoch']loaded_paras = checkpoint['model_state_dict']model.load_state_dict(loaded_paras)logging.info("## 成功载入已有模型,进行追加训练......")model = model.to(config.device)optimizer = torch.optim.Adam(model.parameters(), lr=config.learning_rate)'''Apply Intel Extension for PyTorch optimization against the model object and optimizer object.'''model, optimizer = ipex.optimize(model, optimizer=optimizer)model.train()data_loader = LoadChineseNERDataset(entities=config.entities,num_labels=config.num_labels,ignore_idx=config.ignore_idx,vocab_path=config.vocab_path,tokenizer=BertTokenizer.from_pretrained(config.pretrained_model_dir).tokenize,batch_size=config.batch_size,max_sen_len=config.max_sen_len,split_sep=config.split_sep,max_position_embeddings=config.max_position_embeddings,pad_index=config.pad_token_id,is_sample_shuffle=config.is_sample_shuffle)train_iter, test_iter, val_iter = \data_loader.load_train_val_test_data(train_file_path=config.train_file_path,val_file_path=config.val_file_path,test_file_path=config.test_file_path,only_test=False)max_acc = 0for epoch in range(config.epochs):losses = 0start_time = time.time()for idx, (sen, token_ids, labels) in enumerate(train_iter):token_ids = token_ids.to(config.device)labels = labels.to(config.device)padding_mask = (token_ids == data_loader.PAD_IDX).transpose(0, 1)loss, logits = model(input_ids=token_ids,  # [src_len, batch_size]attention_mask=padding_mask,  # [batch_size,src_len]token_type_ids=None,position_ids=None,labels=labels)  # [src_len, batch_size]# logit: [src_len, batch_size, num_labels]optimizer.zero_grad()loss.backward()optimizer.step()losses += loss.item()global_steps += 1acc, _, _ = accuracy(logits, labels, config.ignore_idx)if idx % 20 == 0:logging.info(f"Epoch: {epoch}, Batch[{idx}/{len(train_iter)}], "f"Train loss :{loss.item():.3f}, Train acc: {round(acc, 5)}")if idx % 100 == 0:show_result(sen[:10], logits[:, :10], token_ids[:, :10], config.entities)end_time = time.time()train_loss = losses / len(train_iter)logging.info(f"Epoch: [{epoch + 1}/{config.epochs}],"f" Train loss: {train_loss:.3f}, Epoch time = {(end_time - start_time):.3f}s")if (epoch + 1) % config.model_val_per_epoch == 0:acc = evaluate(config, val_iter, model, data_loader)logging.info(f"Accuracy on val {acc:.3f}")if acc > max_acc:max_acc = accstate_dict = deepcopy(model.state_dict())torch.save({'last_epoch': global_steps,'model_state_dict': state_dict},model_save_path)

结果

在这里插入图片描述
在这里插入图片描述

参考资料

基于BERT预训练模型的中文文本分类任务: https://mp.weixin.qq.com/s/bbeN95mlLaE05dFndUAxgA

相关文章:

[oneAPI] 基于BERT预训练模型的命名体识别任务

[oneAPI] 基于BERT预训练模型的命名体识别任务 Intel DevCloud for oneAPI 和 Intel Optimization for PyTorch基于BERT预训练模型的命名体识别任务语料介绍数据集构建使用示例 命名体识别模型前向传播模型训练 结果 参考资料 比赛:https://marketing.csdn.net/p/f3…...

SSL证书如何使用?SSL保障通信安全

由于SSL技术已建立到所有主要的浏览器和WEB服务器程序中,因此,仅需安装数字证书或服务器证书就可以激活功能了。SSL证书主要是服务于HTTPS,部署证书后,网站链接就由HTTP开头变为HTTPS。 SSL安全证书主要用于发送安全电子邮件、访…...

postgresql 的递归查询

postgresql 的递归查询功能很强大,可以实现传统 sql 无法实现的事情。那递归查询的执行逻辑是什么呢?在递归查询中,我们一般会用到 union 或者 union all,他们两者之间的区别是什么呢? 递归查询的执行逻辑 递归查询的…...

Go语言进阶:函数、指针、错误处理

一、函数 函数是基本的代码块,用于执行一个任务。 Go 语言最少有个 main() 函数。 你可以通过函数来划分不同功能,逻辑上每个函数执行的是指定的任务。 函数声明包括函数名﹑形式参数列表﹑返回值列表(可省略)以及函数体。 fun…...

最强自动化测试框架Playwright(30)-JS句柄

在 Playwright 中,JSHandle 是一个表示浏览器中 JavaScript 对象的类。它提供了与网页中的 JavaScript 对象进行交互和操作的方法。 可以通过调用 Playwright中的 evaluateHandle 或 evaluate 方法来获取 JSHandle from playwright.sync_api import sync_playwrig…...

Ctfshow web入门 命令执行RCE篇 web29-web77 与 web118-web124 详细题解 全

Ctfshow 命令执行 web29 pregmatch是正则匹配函数,匹配是否包含flag,if(!preg_match("/flag/i", $c)),/i忽略大小写 可以利用system来间接执行系统命令 flag采用f*绕过,或者mv fl?g.php 1.txt修改文件名&#xff0c…...

【C++ STL之map,set,pair详解】

目录 一.map映射1.简介2.包含头文件及其初始化3.基本操作4.用迭代器正反遍历5.添加元素的四种方式6.元素的访问7.对比unordered_map,multimap 二.set集合1.简介2.包含头文件及其初始化3.基本操作4.元素的访问5.set,multiset,unordered_set&am…...

Python LEGB规则解析与应用

引言 推荐阅读 AI文本 OCR识别最佳实践 AI Gamma一键生成PPT工具直达链接 玩转cloud Studio 在线编码神器 玩转 GPU AI绘画、AI讲话、翻译,GPU点亮AI想象空间 资源分享 「java、python面试题」来自UC网盘app分享,打开手机app,额外获得1T空间 http…...

气象监测站:用科技感知气象变化

气象监测站是利用科学技术感知当地小气候变化情况的气象观测仪器,可用于农业、林业、养殖业、畜牧业、环境保护、工业等多个领域,提高对环境数据的利用率,促进产业效能不断提升。 气象监测站主要由气象传感器、数据传输系统、电源系统、支架…...

Linux debian12解压和压缩.rar文件教程

一、Debian12安装rar命令 sudo apt install rar二、使用rar软件 1.解压文件 命令格式: rar x 文件名.rar实例测试: [rootdoudou tmp]# rar x test.rar2.压缩文件 test是一个文件夹 命令格式: rar a 文件名.rar 文件夹名实例测试&#x…...

探析国际大文件传输的花费与降低开销的小妙招

随着全球化的不断发展,跨国企业日益增多,因此国外大文件传输也日益普遍。在这种背景下,国外大文件传输方式的需求也相应增加。本文旨在深入分析国外大文件传输的成本,并提出有效降低这些成本的方法。 一、国外大文件传输成本分析 …...

Linux中shell脚本——for、while循环及脚本练习

目录 一.for循环 1.1.基本格式 1.2.类C语言格式 二.while循环 2.1.基本格式 2.2.死循环语句 三.跳出循环 3.1.continue跳出循环 3.2.break跳出循环 四.常用循环 4.1.循环打印九九乘法表 4.2.循环ping测试某个网段网络连通性 4.3.while死循环实现猜数字游戏 4.4.数…...

【数字实验室】时钟切换

大部分开发者使用 BUFGCTRL 或 BUFGMUX进行时钟切换,它们在时钟切换上可以提供无毛刺输出。然而,了解所涉及的原理是有好处的。 当然,无论我们在同步逻辑中使用哪种技术,重要的是要确保在进行时钟切换时输出上没有毛刺。任何故障都…...

线性代数的学习和整理7:各种特殊效果矩阵特例(草稿-----未完成)

目录 1 矩阵 1.1 1维的矩阵 1.2 2维的矩阵 1.3 没有3维的矩阵---3维的是3阶张量 2 方阵 3 单位矩阵 3.1 单位矩阵的定义 3.2 单位矩阵的特性 3.3 为什么单位矩阵I是 [1,0;0,1] 而不是[0,1;1,0] 或[1,1;1,1] 3.4 零矩阵 3.4 看下这个矩阵 [0,1;1,0] 3.5 看下这个矩阵…...

springBoot 配置文件 spring.mvc.throw-exception-if-no-handler-found 参数的作用

在Spring Boot应用中,可以通过配置文件来控制当找不到请求处理器(handler)时是否抛出异常。具体的配置参数是spring.mvc.throw-exception-if-no-handler-found。 默认情况下,该参数的值为false,即当找不到请求处理器时…...

linux部署kafka3.5.1(单机)

一、下载jdk17 kafka3.x版本需要jdk11以上版本才能更好的兼容,jdk11、jdk17都是LTS长期维护版本,而且jdk17支持springboot3.x,所以我选择了openjdk17。 下载地址: Archived OpenJDK GA Releaseshttps://jdk.java.net/archive/ 二、上传jdk安装包解压 …...

css 实现svg动态图标效果

效果演示&#xff1a; 实现思路&#xff1a;主要是通过css的stroke相关属性来设置实现的。 html代码: <svgt"1692441666814"class"icon"viewBox"0 0 1024 1024"version"1.1"xmlns"http://www.w3.org/2000/svg"p-id"…...

软件测试项目实战,电商业务功能测试点汇总(全覆盖)

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 支付功能怎么测试…...

LeetCode[274]H指数

难度&#xff1a;Medium 题目&#xff1a; 给你一个整数数组 citations &#xff0c;其中 citations[i] 表示研究者的第 i 篇论文被引用的次数。计算并返回该研究者的 h 指数。 根据维基百科上 h 指数的定义&#xff1a;h 代表“高引用次数” &#xff0c;一名科研人员的 h 指…...

MyBatis-Plus快速开始[MyBatis-Plus系列] - 第482篇

悟纤&#xff1a;师傅&#xff0c;MyBatis-Plus被你介绍的这么神乎其乎&#xff0c;咱们还是来的点实际的吧。 师傅&#xff1a;那真是必须的&#xff0c;学习技术常用的一种方法&#xff0c;就是实践。 悟纤&#xff1a;贱贱更健康。 师傅&#xff1a;这… 师傅&#xff1a;…...

CF1003A Polycarp‘s Pockets 题解

题目传送门 题目意思&#xff1a; 给你 n n n 个数&#xff0c;求出最多相同的数的个数。 这道题目有两种解法。 方法一&#xff1a;桶排 一边输入&#xff0c;一边将第 i i i 个数 a i a_i ai​ 出现的次数存在一个数组 b b b 的第 a i a_i ai​ 个位置。输入完后遍历…...

数据库厂商智臾科技加入龙蜥社区,打造多样化的数据底座

近日&#xff0c;浙江智臾科技有限公司&#xff08;以下简称“智臾科技”&#xff09;正式签署 CLA 贡献者许可协议&#xff0c;加入龙蜥社区&#xff08;OpenAnolis&#xff09;。 智臾科技主创团队从 2012 年开始投入研发 DolphinDB。DolphinDB 作为一款基于高性能时序数据库…...

一天赚四五十的副业,可以试试这几种

大家都希望能够有额外的零花钱&#xff0c;尤其是对于学生和不收入稳定的人来说。今天&#xff0c;我将分享一些简单实用的赚钱技巧&#xff0c;帮助你每天赚取四五十的零花钱&#xff0c;让你的钱包更丰盈。 第一种&#xff1a;蚂蚁路客和友活来了 支付宝旗下两款接任务拍门…...

OpenCV 中的色彩空间 (C++ / Python)

在本教程中,我们将了解计算机视觉中使用的流行色彩空间,并将其用于基于颜色的分割。我们还将分享 C++ 和 Python 的演示代码。...

邀请函 | 高质量区块链·元宇宙—标准行系列沙龙(北京站)即将开启

区块链、元宇宙是近年来备受关注的新兴技术&#xff0c;也是推动数字经济发展的重要力量。高质量标准引领高质量发展&#xff0c;加快形成标准引领&#xff0c;充分释放区块链、元宇宙对实体经济牵引赋能效应&#xff0c;推进形成相关产业体系高质量发展新格局刻不容缓。 为进…...

php hmacsha256加密的算法

HMAC-SHA256是一种基于哈希算法的消息认证码算法&#xff0c;用于验证数据的完整性和真实性。它将密钥和数据一起进行哈希运算&#xff0c;生成一个固定长度的摘要值。只有知道密钥的人才能够验证该摘要值的真实性。 在PHP中&#xff0c;可以使用hash_hmac函数来计算HMAC-SHA2…...

Spring源码编译教程

1. Spring版本是5.3.10 2. 下载gradle依赖 Spring是通过gradle来编译源码下载依赖的&#xff0c;.gradle文件夹可以理解为gradle的仓库&#xff08;和mave类似&#xff0c;不懂gradle的先这么理解&#xff09;&#xff0c;而我给大家的这个仓库&#xff0c;只包含了Spring源码…...

Python入门教程 | Python简介和环境搭建

Python 简介 Python是一种高级编程语言&#xff0c;由荷兰人Guido van Rossum于1991年创建。它以其简单易学、可读性强和丰富的生态系统而受到广泛喜爱。它被广泛应用于各个领域&#xff0c;包括Web开发、科学计算、数据分析、人工智能等。 Python的特点 简洁易读&#xff1a…...

阿里云ECS服务器企业级和共享型介绍_企业级常见问题解答FAQ

阿里云企业级服务器是什么&#xff1f;企业级和共享型有什么区别&#xff1f;企业级服务器具有独享且稳定的计算、存储、网络资源&#xff0c;如ECS计算型c6、通用型g8等都是企业级实例&#xff0c;阿里云百科分享什么是企业级云服务器、企业级实例的优势、企业级和共享型云服务…...

leetcode做题笔记92. 反转链表 II

给你单链表的头指针 head 和两个整数 left 和 right &#xff0c;其中 left < right 。请你反转从位置 left 到位置 right 的链表节点&#xff0c;返回 反转后的链表 。 示例 1&#xff1a; 思路一&#xff1a;头插法 struct ListNode *reverseBetween(struct ListNode *h…...

springboot引入druid解析sql

一、前言 在开发中&#xff0c;有时我们可能会需要获取SQL中的表名&#xff0c;那么因为不同的数据源类型SQL会存在部分差异&#xff0c;那么我们就可以使用alibaba 的druid包实现不同的数据源类型的sql解析。 二、引入相关maven依赖 <dependency><groupId>com.a…...

学习笔记十九:Pod常见的状态和重启策略

Pod常见的状态和重启策略 常见的pod状态第一阶段&#xff1a;第二阶段&#xff1a;扩展&#xff1a; pod重启策略测试Always重启策略正常停止容器内的tomcat服务非正常停止容器里的tomcat服务 测试never重启策略正常停止容器里的tomcat服务非正常停止容器里的tomcat服务 测试On…...

Spring的ApplicationEvent简单使用

ApplicationEvent以及Listener是Spring为我们提供的一个事件监听、订阅的实现&#xff0c;内部实现原理是观察者设计模式&#xff0c;设计初衷也是为了系统业务逻辑之间的解耦&#xff0c;提高可扩展性以及可维护性。事件发布者并不需要考虑谁去监听&#xff0c;监听具体的实现…...

python程序员面试题之:set vs tuple vs list vs dict

首先&#xff0c;set/tuple/list/dict都是存储变量的python类型&#xff0c;四者之间有异有同。 首先&#xff0c;set存储无序不重复序列。 set_b {1,2,4} print(set_b[0]) TypeError: ‘set’ object is not subscriptable set 会自动去重&#xff0c;所以根据这个特性可以对…...

STM32 F103C8T6学习笔记11:RTC实时时钟—OLED手表日历

之前在 学习笔记10文章 做了一个简易的&#xff0c;使用定时器计时的简单时钟&#xff0c;现在使用RTC实时时钟同步代替定时器来实现一下OLED手表日历&#xff0c;接着上个实验文章进行完善~~ 文章提供源码、测试工程下载、测试效果图。 目录 RTC实时时钟&#xff1a; 简介&…...

无法将“环境变量”项识别为 cmdlet、函数、脚本文件或可运行程序的名称(pycharm)

无法将“配置的任何一个环境变量”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。 记录解决“无法将“C:......conda.exe”项识别为 cmdlet、函数、脚本文件或可运行程序的名称”以及“表达式或语句中包含意外的标记”的系列问题(VSCode开发环境)一、Conda.exe无法正常识…...

基于图像链接的批量下载

1. 获取图像路径 1.1 给定图像链接&#xff0c;这是一张图像 image_url “https://univs-news-1256833609.cos.ap-beijing.myqcloud.com/123/upload/resources/image/7467914.jpg”1.1通过网站规则得到其想要的图像链接 image_urls [ f"https://univs-news-125683360…...

mongodb使用心得

入门 术语 collection&#xff1a;相当于db的表 document&#xff1a;相当于表的记录 启动 单机模式启动mongo server mongod --dbpath D:\programs\mongodb-4.2.8\data\dbreplica set模式启动 replica set模式其实就是主从模式。 做mongo的启动配置文件&#xff1a; …...

学习Vue:响应式原理与性能优化策略

性能优化是Vue.js应用开发中的一个关键方面&#xff0c;而深入了解响应式原理并采用有效的性能优化策略可以显著提升应用的性能。本文将解释响应式原理并介绍一些性能优化策略&#xff0c;旨在帮助您构建高性能的Vue.js应用。 响应式原理 Vue.js的响应式原理是通过利用Object.…...

神经网络基础-神经网络补充概念-43-梯度下降法

概念 梯度下降法&#xff08;Gradient Descent&#xff09;是一种优化算法&#xff0c;用于在机器学习和深度学习中最小化&#xff08;或最大化&#xff09;目标函数。它通过迭代地调整模型参数&#xff0c;沿着梯度方向更新参数&#xff0c;以逐步接近目标函数的最优解。梯度…...

Reids之Set类型解读

目录 基本介绍 命令概述 SADD key member1 [member2] SCARD key SINTER key1 [key2] SMEMBERS key SPOP key SUNION key1 [key2] 基本介绍 新的存储需求&#xff1a;存储大量的数据 在查询方面提供更高的效率需要的存储结构&#xff1a;能够保存大量的数据&#x…...

【网络基础】数据链路层

【网络基础】数据链路层 文章目录 【网络基础】数据链路层1、对比网络层2、以太网2.1 基本概念2.2 类似技术2.3 以太网帧 3、MAC地址对比IP地址 4、MTU4.1 对IP协议影响4.2 对UDP协议影响4.3 对TCP协议影响4.4 地址、MTU查看 5、ARP协议5.1 协议作用5.2 协议工作流程5.3 数据报…...

云计算|OpenStack|使用VMware安装华为云的R006版CNA和VRM---初步使用(二)

前言&#xff1a; 在前面一篇文章云计算|OpenStack|使用VMware安装华为云的R006版CNA和VRM---初始安装&#xff08;一&#xff09;_华为cna_晚风_END的博客-CSDN博客 介绍了基于VMware虚拟机里嵌套部署华为云的云计算&#xff0c;不过仅仅是做到了在VRM的web界面添加计算节点…...

Python typing函式庫和torch.types

Python typing函式庫和torch.types 前言typingSequence vs IterableCallableUnionOptionalFunctionsCallableIterator/generator位置參數 &#xff06; 關鍵字參數 Classesself自定義類別ClassVar\_\_setattr\_\_ 與 \__getattr\_\_ torch.typesbuiltins 參數前的&#xff0a; …...

UE5 编程规范

官方文档 使用现代C编程标准, 使用前沿C标准库版本. 1. 类中按照先 Public 后 Private 去写 2. 继承自 UObject 的类都以 U 前缀 3. 继承自 AActor 的类都以 A 前缀 4. 继承自 SWidget 的类都以 S 前缀 5. 模板以 T 前缀 6. 接口以 I 前缀 7. 枚举以 E 前缀 8. 布尔值…...

交互消息式IMessage扩展开发记录

IMessage扩展简介 iOS10新加入的基于iMessage的应用扩展&#xff0c;可以丰富发送消息的内容。&#xff08;分享表情、图片、文字、视频、动态消息&#xff1b;一起完成任务或游戏。&#xff09; 简单的将发送的数据内型分为三种&#xff1a; 1.贴纸Stickers&#xff1b; 2.交…...

软件团队降本增效-建立需求评估体系

需求对于软件开发来说是非常重要的输入&#xff0c;它们直接决定了软件的产品形态、代码数量和质量。如果需求不清晰、不完善&#xff0c;或者存在逻辑冲突&#xff0c;将会导致软件质量迅速下降&#xff0c;增加代码耦合性和开发成本。 在开发过程中&#xff0c;对需求的产品…...

npm yarn pnpm 命令集

npm 安装依赖 npm install 安装某个依赖 npm install xxx7.6.3 安装到全局&#xff08;dependencies&#xff09; npm install xxx7.6.3 -S 安装到线下&#xff08;devDependencies&#xff09; npm install xxx7.6.3 -D 卸载某个依赖 npm uninstall xxx 卸载全局依…...

python 开发环境(PyCharm)搭建指南

Python 的下载并安装 参考&#xff1a;Python基础教程——搭建Python编程环境 下载 Python Python 下载地址&#xff1a;官网 &#xff08;1&#xff09;点击【Downloads】>>>点击【Windows】>>>点击【Python 3.x.x】下载最新版 Python&#xff1b; Pyt…...

springboot里 运用 easyexcel 导出

引入pom <dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>2.2.6</version> </dependency>运用 import com.alibaba.excel.EasyExcel; import org.springframework.stereotype.Contr…...