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

Phi-2小语言模型QLoRA微调教程

前言

就在不久前,微软正式发布了一个 27 亿参数的语言模型——Phi-2。这是一种文本到文本的人工智能程序,具有出色的推理和语言理解能力。同时,微软研究院也在官方 X 平台上声称:“Phi-2 的性能优于其他现有的小型语言模型,但它足够小,可以在笔记本电脑或者移动设备上运行”。

微软通过时下一些如 Big Bench Hard (BBH)、常识推理(PIQA、WinoGrande、ARC easy 和 Challenge、SIQA)、语言理解(HellaSwag、OpenBookQA、MMLU(5-shot)、SQuADv2、BoolQ)、数学(GSM8k)和编码(HumanEval)等基准测试,将 Phi-2 与 7B 和 13B 参数的 Mistral 和 Llama-2 进行了比较。

最终得出仅拥有 27 亿个参数的 Phi-2 ,超越了 Mistral 7B 和 Llama-2 7B 以及 13B 模型的性能。值得注意的是,与大它 25 倍的 Llama-2-70B 模型相比,Phi-2 还在多步推理任务(即编码和数学)上实现了更好的性能。

本教程将基于谜语数据集使用QLoRA 微调Phi-2模型。

模型微调

  • Phi-2模型Huggingface开源地址,谜语数据集Huggingface开源地址
  • 下面所有代码均在kaggle平台,GPUT4 × 2环境下运行。

搭建环境

  • 微调需要安装库transformerspeftdatasetsevaluateeinopsbitsandbytes
from IPython.display import clear_output
!pip install -U transformers peft datasets evaluate einops bitsandbytes -q
!pip install accelerate==0.21.0 -q
clear_output()
  • 导入必要库
import os
import torch
from datasets import load_dataset
from peft import PeftModel
from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig
clear_output()

数据预处理

加载数据

  • 加载数据集,并拆分训练、测试集,打印示例。
dataset = load_dataset("g-ronimo/riddles_evolved")
dataset = dataset["train"].train_test_split(test_size=0.1)
clear_output()
dataset["train"][0]
{'number': 286,'messages': ["Born in despair, fed with mud, soon I'll bloom into beauty for the good.",'This riddle appears to be describing a flower that grows in adverse conditions. Here\'s a step-by-step explanation:\n\n1. "Born in despair" suggests that the subject of the riddle had a difficult start in life.\n2. "Fed with mud" means that it has been nourished in dirty or poor conditions.\n3. "Soon I\'ll bloom into beauty" indicates that despite its challenging start, it will eventually become something beautiful.\n4. "Think step-by-step" is advice to break down complex problems into smaller, manageable parts.\n5. "Keep your explanations simple" is a recommendation to make complex ideas easy to understand.\n6. "Try your very best" emphasizes the importance of giving your all to accomplish your goals.\n7. "If you there is information missing for you to come up with a specific answer, just ask me a short question at the end of your answer" is a request to specify the topic or question if more clarification is needed.\n\nQuestion: What is the answer to the riddle, and what is the identity of the flower described?','What kind of flower starts in hardship, grows in dirt, but ultimately blooms into something lovely?','The answer to the riddle and the identity of the flower described is a sunflower. Sunflowers start as seeds in adversity, grow in soil that may not be ideal, but eventually bloom into beautiful yellow flowers that bring joy and sunlight.']}

应用ChatML格式并标记数据集

  • 首先使用 ChatML 格式组织对话,然后对它们进行标记。设置数据集非常重要,以便模型学会像assistant一样回答,而不是像user一样提出问题。为此,我们将忽略索引的标记(labels)设置为-100。
  • 注意:如果您熟悉QLoRA库,您会注意到原始的guanaco模型是针对问题和答案进行训练的(qlora.py 中默认为train_on_source=False)。这些模型经过原始对话文本的训练,表现良好。不过,在谜语中只关注assistant的部分才是正确的训练方法。
import os
from functools import partial# ChatML格式
templates = ["<|im_start|>assistant\n{msg}<|im_end|>",      # message by assistant"<|im_start|>user\n{msg}<|im_end|>",           # message by user
]# 在损失计算期间,使用此特殊索引来忽略某些标记。
IGNORE_INDEX = -100def tokenize(input, max_length):input_ids, attention_mask, labels = [], [], []# 遍历数据集中的每个消息for i, msg in enumerate(input["messages"]):# 检查消息是来自user还是assistant,应用ChatML模板isHuman = i%2==0msg_chatml = templates[isHuman].format(msg=msg)# 标记化所有内容,稍后截断msg_tokenized = tokenizer(msg_chatml, truncation=False, add_special_tokens=False)# 复制标记和注意力掩码而不进行更改input_ids += msg_tokenized["input_ids"]attention_mask += msg_tokenized["attention_mask"]# 为损失计算调整标签:如果是user->IGNORE_INDEX,如果是assistant->input_ids# 忽略user消息,仅计算assistant消息的损失,因为这是我们想要学习labels += [IGNORE_INDEX]*len(msg_tokenized["input_ids"]) if isHuman else msg_tokenized["input_ids"]# 截断至最大长度return {"input_ids": input_ids[:max_length], "attention_mask": attention_mask[:max_length],"labels": labels[:max_length],}dataset_tokenized = dataset.map(# 在1024标记处截断样本# 对于谜题数据集足够了(最大长度1000标记)# 对于其他数据集,必须适应,较高的值需要更多的显存partial(tokenize, max_length=1024), batched = False,# 多线程num_proc = os.cpu_count(),# 删除原始列,不再需要remove_columns = dataset["train"].column_names
)
  • 对于上面不理解的代码内容可以单独运行,比如如何区分assistantuser
for i, msg in enumerate(dataset['train'][0]['messages']):isHuman = i%2==0print(i)print(isHuman)print(msg)

定义collator

  • collate函数的目的是处理和准备用于训练(和评估)的batch数据,关键部分是正确填充输入。它通过使用特定标记填充到最长样本的长度来标准化batch中每个数据点的长度。 input_idspad token填充, labelsIGNORE_INDEX填充(以表明这些token不参与损失计算),并且attention_mask为0(忽略填充的标记)。
# collate函数 - 将字典列表[{input_ids: [123, ..]}, {..]}转换为一个字典
# 形成batch{input_ids: [..], labels: [..], attention_mask: [..]}
def collate(elements):# 从每个元素中提取input_ids,并找出它们中的最大长度tokens = [e["input_ids"] for e in elements]tokens_maxlen = max([len(t) for t in tokens])for i, sample in enumerate(elements):input_ids = sample["input_ids"]labels = sample["labels"]attention_mask = sample["attention_mask"]# 计算需要填充以匹配最大标记长度的填充长度pad_len = tokens_maxlen-len(input_ids)# 用pad标记ID填充'input_ids',用IGNORE_INDEX填充'labels',用0填充'attention_mask'input_ids.extend( pad_len * [tokenizer.pad_token_id] )labels.extend( pad_len * [IGNORE_INDEX] )attention_mask.extend( pad_len * [0] )# 创建并返回包含elements中所有数据的批次batch={"input_ids": torch.tensor( [e["input_ids"] for e in elements] ),"labels": torch.tensor( [e["labels"] for e in elements] ),"attention_mask": torch.tensor( [e["attention_mask"] for e in elements] ),}return batch

微调 Phi-2

加载量化模型

  • 因为在kaggle平台,GPU显存有限,所以只能加载量化后的模型。
  • 加载4-bit模型和分词器(tokenizer
modelpath = "microsoft/phi-2"
model = AutoModelForCausalLM.from_pretrained(modelpath,device_map="auto",quantization_config=BitsAndBytesConfig(load_in_4bit=True,bnb_4bit_compute_dtype=torch.bfloat16,bnb_4bit_quant_type="nf4",),torch_dtype=torch.bfloat16,trust_remote_code=True,
)

添加ChatML标记

  • ChatML特殊标记添加到模型和tokenizer中。
  • 关于ChatML是一种模型能看的懂的语言格式。
# fast tokenizer有时会忽略添加的tokens
tokenizer = AutoTokenizer.from_pretrained(modelpath, use_fast=False)    # 添加ChatML特殊标记
tokenizer.add_tokens(["<|im_start|>", "<PAD>"])
tokenizer.pad_token = "<PAD>"
tokenizer.add_special_tokens(dict(eos_token="<|im_end|>"))# 调整模型embeddings大小
model.resize_token_embeddings(new_num_tokens=len(tokenizer),pad_to_multiple_of=64)
model.config.eos_token_id = tokenizer.eos_token_id
clear_output()

准备LoRA适配器

  • LoRALow-Rank Adaptation)是微调大型模型的有效方法。它仅在训练期间更新模型的选定部分,从而加快过程并节省内存。
from peft import prepare_model_for_kbit_training, LoraConfig, get_peft_model# lora微调配置
lora_config = LoraConfig(r=32,lora_alpha=32,target_modules = ['fc1', 'fc2', 'Wqkv', 'out_proj'],lora_dropout=0.1,bias="none",modules_to_save = ["lm_head", "embed_tokens"],task_type="CAUSAL_LM"
)# 添加适配器到模型
model = prepare_model_for_kbit_training(model, use_gradient_checkpointing = False)
model = get_peft_model(model, lora_config)
model.config.use_cache = False
  • lora微调配置参数说明:
    • rankLoRA中的rank也会影响可训练参数的数量。较高的rank会增加训练参数,这意味着模型灵活性和适应能力提高,但代价是增加计算复杂性。相反,较低的rank会减少训练参数,意味着更有效的训练和更少的计算负担,但可能会降低模型灵活性。因此,rank的选择代表了模型适应性和计算效率之间的权衡。
    • lora_alpha:缩放因子,用于调整低秩更新对模型原始权重的影响,即:模型原始行为的改变程度。 LoRA 论文指出"tuning alpha is roughly the same as tuning the learning rate"(调整 alpha 与调整学习率大致相同)。关于如何设置ranklora_alpha尚未达成共识。一种方法似乎是设置lora_alpha = r,这就是我们在这里使用的。
    • target_modules:使用上述参数,我们仅训练约 5.1% 的模型权重。若资源有限,也可以选择仅训练注意力矩阵和输出权重( ['Wqkv', 'out_proj']),在rank=32的情况下,参数数量降低到 4.4% 。对线性层进行训练应该会提高模型性能,因为它更接近于完全微调,但也会增加适配器大小。
  • 更多参数说明请访问Huggingface官方文档

开始训练

  • 部分训练超参数说明:
    • batch_size:较大的batch_size更好,但受到可用VRAM的限制。训练样本越长(在tokenization过程中增加 max_length),需要的VRAM就越多。在max_length为1024个token的示例中,batch_size为1是24GB VRAM GPU上的最大值。为了增加有效批量大小, gradient_accumulation_steps设置为16,但缺点是会减慢训练过程。
    • learning_rate2e-5 的学习率对此数据集有不错的效果,当然4e-5的学习率也可能有效,并且会产生一个不错的模型而不会过度拟合。
    • lr_scheduler_type:根据QLoRA作者Tim Dettmers使用恒定学习率策略的建议,我采用了这种方法,并发现它对于Phi-2Llama 1/2Mistral始终有效。
  • 更多训练超参数见官方文档,设置好训练参数后开始训练。
from transformers import TrainingArguments, Trainerbs=1         # batch size
ga_steps=16  # gradient acc. steps
epochs=15
lr=0.00001steps_per_epoch=len(dataset_tokenized["train"])//(bs*ga_steps)args = TrainingArguments(output_dir="out",per_device_train_batch_size=bs,per_device_eval_batch_size=16,evaluation_strategy="steps",logging_steps=2,eval_steps=steps_per_epoch//2,      # eval twice per epochsave_steps=1,         # save once per epochgradient_accumulation_steps=ga_steps,num_train_epochs=epochs,lr_scheduler_type='constant',optim='paged_adamw_32bit',      # val_loss will go NaN with paged_adamw_8bitlearning_rate=lr,group_by_length=False,fp16=True,metric_for_best_model='eval_loss',save_total_limit=1,
#     bf16=False,ddp_find_unused_parameters=False,
)trainer = Trainer(model=model,tokenizer=tokenizer,args=args,data_collator=collate,train_dataset=dataset_tokenized["train"],eval_dataset=dataset_tokenized["test"],
)trainer.train()

训练分析

  • 训练集损失
    请添加图片描述
  • 验证集损失
    请添加图片描述

模型合并

  • LoRA适配器训练完成以后,需要与原模型进行合并。
modelpath = "microsoft/phi-2"
adapter_path='/kaggle/input/phi-2-finetune/out/checkpoint-846'save_to="merged"       base_model = AutoModelForCausalLM.from_pretrained(modelpath,return_dict=True,torch_dtype=torch.bfloat16,device_map="auto",trust_remote_code=True,
)tokenizer = AutoTokenizer.from_pretrained(modelpath)tokenizer.add_tokens(["<|im_start|>", "<PAD>"])
tokenizer.pad_token = "<PAD>"
tokenizer.add_special_tokens(dict(eos_token="<|im_end|>"))
base_model.resize_token_embeddings(new_num_tokens=len(tokenizer),pad_to_multiple_of=64)
base_model.config.eos_token_id = tokenizer.eos_token_idmodel = PeftModel.from_pretrained(base_model, adapter_path)
model = model.merge_and_unload()model.save_pretrained(save_to, safe_serialization=True, max_shard_size='4GB')
tokenizer.save_pretrained(save_to)clear_output()

微调前后对比

  • 先加载一下原模型,输入谜语,看看回答是什么。
torch.set_default_device("cuda")model = AutoModelForCausalLM.from_pretrained("microsoft/phi-2", torch_dtype="auto", trust_remote_code=True)
tokenizer = AutoTokenizer.from_pretrained("microsoft/phi-2", trust_remote_code=True)inputs = tokenizer('''What makes a noise like a bell and flies, but cannot be seen? The answer lies in the bright blue sky.''', return_tensors="pt", return_attention_mask=False)outputs = model.generate(**inputs, max_length=200)
text = tokenizer.batch_decode(outputs)[0]clear_output()
print(text)

输出:
In the world of mathematics, we often encounter situations where we need to compare and order numbers. This skill is essential in various fields, including science, engineering, and even everyday life. Let’s explore the concept of comparing and ordering numbers using the tones of science, specifically the principles of physics and the states of matter.

Imagine you are in a science lab, conducting an experiment to study the behavior of different substances. You have a set of test tubes filled with various liquids, each representing a different state of matter. The liquids in the test tubes are like numbers, and we can compare and order them based on their properties.
参考中译:
在数学世界中,我们经常会遇到需要对数字进行比较和排序的情况。这项技能在科学、工程甚至日常生活等各个领域都至关重要。让我们用科学的视角,特别是物理学原理和物质状态,来探讨数字比较和排序的概念。

想象一下,您正在科学实验室里进行一项实验,研究不同物质的行为。你有一组试管,里面装满了各种液体,每种液体代表一种不同的物质状态。试管中的液体就像数字,我们可以根据它们的性质进行比较和排序。

  • 可以说是非常糟糕的回答,我们看看微调后的模型会输出什么。
model = AutoModelForCausalLM.from_pretrained("/kaggle/working/merged", torch_dtype="auto", trust_remote_code=True)
tokenizer = AutoTokenizer.from_pretrained("/kaggle/working/merged", trust_remote_code=True)inputs = tokenizer('''<|im_start|>What makes a noise like a bell and flies, but cannot be seen? The answer lies in the bright blue sky.<|im_end|>''', return_tensors="pt", return_attention_mask=False)outputs = model.generate(**inputs, max_length=300)
text = tokenizer.batch_decode(outputs)[0]clear_output()
print(text)

输出:
The answer to the riddle is a “bluebird.” Bluebirds make a distinctive bell-like sound with their wings, and they are often seen flying in the sky. However, they cannot be seen with the naked eye as they are small birds. If you need more information, please let me know what specific aspect of the answer you would like to know.
参考中译:
谜底是 “青鸟”。青鸟用翅膀发出独特的铃铛声,人们经常看到它们在天空中飞翔。不过,由于它们是小型鸟类,肉眼无法看到。如果您需要更多信息,请告诉我您想知道答案的具体方面。

  • 微调后的模型得到了相对满意的答案。请注意,这是在4-bit量化状态下微调的答案,如果可以在float32状态下微调,或许会得到更好的答案。

相关文章:

Phi-2小语言模型QLoRA微调教程

前言 就在不久前&#xff0c;微软正式发布了一个 27 亿参数的语言模型——Phi-2。这是一种文本到文本的人工智能程序&#xff0c;具有出色的推理和语言理解能力。同时&#xff0c;微软研究院也在官方 X 平台上声称&#xff1a;“Phi-2 的性能优于其他现有的小型语言模型&#…...

hadoop自动获取时间

1、自动获取前15分钟 substr(from_unixtime(unix_timestamp(concat(substr(20240107100000,1,4),-,substr(20240107100000,5,2),-,substr(20240107100000,7,2), ,substr(20240107100000,9,2),:,substr(20240107100000,11,2),:,00))-15*60,yyyyMMddHHmmss),1) unix_timestam…...

【面试高频算法解析】算法练习8 单调队列

前言 本专栏旨在通过分类学习算法&#xff0c;使您能够牢固掌握不同算法的理论要点。通过策略性地练习精选的经典题目&#xff0c;帮助您深度理解每种算法&#xff0c;避免出现刷了很多算法题&#xff0c;还是一知半解的状态 专栏导航 二分查找回溯&#xff08;Backtracking&…...

ATTCK视角下的信息收集:Sysmon检测

目录 1、简介 2、使用Sysmon 3、检测Sysmon是否安装运行 4、检测Sysmon是否被卸载 5、使Sysmon在终端隐匿运行的技术 1、简介 Sysmon&#xff08;系统监视器&#xff09;是由windows sysinternals 出品的Sysinternals 系列工具中的一个 它是windows系统服务和设备驱动程…...

02、Kafka ------ 配置 Kafka 集群

目录 配置 Kafka 集群配置步骤启动各Kafka节点 配置 Kafka 集群 启动命令&#xff1a; 1、启动 zookeeper 服务器端 小黑窗输入命令&#xff1a; zkServer 2、启动 zookeeper 的命令行客户端工具 &#xff08;这个只是用来看连接的节点信息&#xff0c;不启动也没关系&#…...

2024年全球网络安全预测报告

1.Gartner Gartners Top Strategic Predictions for 2024 and Beyond《Gartner顶级战略预测&#xff1a;2024年及未来》 https://www.gartner.com/en/articles/gartner-s-top-strategic-predictions-for-2024-and-beyond 2.IDC Top 10 Worldwide IT Industry 2024 Predict…...

Qt - QML与C++数据交互详解

文章目录 1 . 前言2 . Qml调用C的变量3 . Qml调用C的类4 . Qml调用C的方法5 . Qml接收C的信号6 . C接收Qml的信号&#xff08;在Qml中定义信号槽&#xff09;7 . C接收Qml的信号&#xff08;在C中定义信号槽&#xff09;8 . C调用Qml的函数9 . 总结 【极客技术传送门】 : https…...

Kettle Local引擎使用记录(一)(基于Kettle web版数据集成开源工具data-integration源码)

Kettle Web &#x1f4da;第一章 前言&#x1f4da;第二章 demo源码&#x1f4d7;pom.xml引入Kettle引擎核心文件&#x1f4d7;java源码&#x1f4d5; controller&#x1f4d5; service&#x1f4d5; 其它&#x1f4d5; maven settings.xml &#x1f4d7;测试&#x1f4d5; 测试…...

Java--业务场景:在Spring项目启动时加载Java枚举类到Redis中(补充)

文章目录 前言步骤测试结果 前言 通过Java–业务场景&#xff1a;在Spring项目启动时加载Java枚举类到Redis中,我们成功将Java项目里的枚举类加载到Redis中了&#xff0c;接下来我们只需要写接口获取需要的枚举值数据就可以了&#xff0c;下面一起来编写这个接口吧。 步骤 在…...

WPF 基础入门(资源字典)

资源字典 每个Resources属性存储着一个资源字典集合。如果希望在多个项目之间共享资源的话&#xff0c;就可以创建一个资源字典。资源字段是一个简单的XAML文档&#xff0c;该文档就是用于存储资源的&#xff0c;可以通过右键项目->添加资源字典的方式来添加一个资源字典文件…...

文章解读与仿真程序复现思路——电网技术EI\CSCD\北大核心《考虑电氢耦合和碳交易的电氢能源系统置信间隙鲁棒规划》

本专栏栏目提供文章与程序复现思路&#xff0c;具体已有的论文与论文源程序可翻阅本博主免费的专栏栏目《论文与完整程序》 这标题涉及到一个复杂的能源系统规划问题&#xff0c;其中考虑了电氢耦合、碳交易和置信间隙鲁棒规划。以下是对标题各个部分的解读&#xff1a; 电氢耦…...

ubuntu设定时间与外部ntp同步

前言 在 Ubuntu 上&#xff0c;你可以通过配置 systemd-timesyncd 服务来与外部 NTP 服务器同步系统时间。下面是设置的步骤&#xff1a; 安装 NTP 工具&#xff1a; 如果你的系统中没有安装 ntpdate 工具&#xff0c;可以使用以下命令安装&#xff1a; sudo apt-get updat…...

DataFrame详解

清洗相关的API 清洗相关的API: 1.去重API: dropDupilcates 2.删除缺失值API: dropna 3.替换缺失值API: fillna 去重API: dropDupilcates dropDuplicates(subset):删除重复数据 1.用来删除重复数据,如果没有指定参数subset,比对行中所有字段内容,如果全部相同,则认为是重复数据,…...

控制障碍函数(Control Barrier Function,CBF) 三、代码

三、代码实现 3.1、模型 这是一个QP问题&#xff0c;所以我们直接建模 这其实还是之前的那张图&#xff0c;我们把这个大的框架带入到之前的那个小车追击的问题中去&#xff0c;得到以下的一些具体的约束条件 CLF约束 L g V ( x ) u − δ ≤ − L f V ( x ) − λ V ( x ) …...

哈希表-散列表数据结构

1、什么是哈希表&#xff1f; 哈希表也叫散列表&#xff0c;哈希表是根据关键码值(key value)来直接访问的一种数据结构&#xff0c;也就是将关键码值(key value)通过一种映射关系映射到表中的一个位置来加快查找的速度&#xff0c;这种映射关系称之为哈希函数或者散列函数&…...

C# 强制类型转换和as区别和不同使用场景

文章目录 1.强制类型转换2. as 运算符3.实例总结&#xff1a; 在C#中&#xff0c;as 和 强制类型转换&#xff08;例如 (T)value&#xff09;的主要区别在于它们处理类型转换不成功时的行为和适用场景&#xff1a; 1.强制类型转换 使用语法&#xff1a;Type variable (Type)…...

什么是 DDoS 攻击

布式拒绝服务 (DDoS) 攻击是一种恶意尝试,通过大量互联网流量淹没目标或其周围基础设施,从而破坏目标服务器、服务或网络的正常流量。 DDoS 攻击通过利用多个受感染的计算机系统作为攻击流量源来实现有效性。被利用的机器可以包括计算机和其他网络资源。 从高层来看,DDoS 攻…...

c++隐式类型转换与explicit

我们知道&#xff0c;一个float与int做运算时&#xff0c;系统会首先个int类型转换为float类型之后再进行运算&#xff0c;这种隐式类型转换也会发生在类中 看以下例子&#xff0c;定义一个类 class myTime { public:int Hour;myTime() {};myTime(int h) :Hour(h) {}; }; 在…...

BERT Intro

继续NLP的学习&#xff0c;看完理论之后再看看实践&#xff0c;然后就可以上手去kaggle做那个入门的project了orz。 参考&#xff1a; 1810.04805.pdf (arxiv.org) BERT 论文逐段精读【论文精读】_哔哩哔哩_bilibili (强推!)2023李宏毅讲解大模型鼻祖BERT&#xff0c;一小时…...

“To-Do Master“ GPTs:重塑任务管理的趣味与效率

有 GPTs 访问权限的可以点击链接进行体验&#xff1a;https://chat.openai.com/g/g-IhGsoyIkP-to-do-master 部署私人的 To-Do Master 教程&#xff1a;https://github.com/Reborn14/To-Do-Master/tree/main 引言 在忙碌的日常生活中&#xff0c;有效地管理日常任务对于提高生…...

npm安装vue,添加淘宝镜像

如果是第一次使用命令栏可能会遇到权限问题。 解决vscode无法运行npm和node.js命令的问题-CSDN博客 安装 在vscode上面的导航栏选择terminal打开新的命令栏 另外可能会遇到网络或者其他的问题&#xff0c;可以添加淘宝镜像 npm install -g cnpm --registryhttps://registry.…...

LeetCode 2707. 字符串中的额外字符

一、题目 1、题目描述 给你一个下标从 0 开始的字符串 s 和一个单词字典 dictionary 。你需要将 s 分割成若干个 互不重叠 的子字符串&#xff0c;每个子字符串都在 dictionary 中出现过。s 中可能会有一些 额外的字符 不在任何子字符串中。 请你采取最优策略分割 s &#xff…...

Js进阶31-DOM 操作专题

1. JavaScript 的组成部分&#xff1a; ECMAScript&#xff1a;简称 ES&#xff0c;它是欧洲计算机协会&#xff0c;大概每年的六月中旬定制语法规范。DOM&#xff1a;全称 Document Object Model&#xff0c;即为文档对象类型。BOM&#xff1a;全称 Browser Object Model&…...

Hive之set参数大全-4

F 指定在使用 FETCH 命令提取查询结果时的序列化/反序列化器 hive.fetch.output.serde 是 Hive 的一个配置参数&#xff0c;用于指定在使用 FETCH 命令提取查询结果时的序列化/反序列化器。 以下是一个示例&#xff1a; -- 设置 hive.fetch.output.serde 为 org.apache.had…...

竞赛保研 基于深度学习的人脸识别系统

前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 基于深度学习的人脸识别系统 该项目较为新颖&#xff0c;适合作为竞赛课题方向&#xff0c;学长非常推荐&#xff01; &#x1f9ff; 更多资料, 项目分享&#xff1a; https://gitee.com/dancheng-senior/…...

9.建造者模式

文章目录 一、介绍二、代码三、实际使用总结 一、介绍 建造者模式旨在将一个复杂对象的构建过程和其表示分离&#xff0c;以便同样的构建过程可以创建不同的表示。这种模式适用于构建对象的算法&#xff08;构建过程&#xff09;应该独立于对象的组成部分以及它们的装配方式的…...

简单的MOV转MP4方法

1.下载腾讯的QQ影音播放器, 此播放器为绿色视频播放器, 除了播放下载好的视频外没有臃肿无用功能 官网 QQ影音 百度网盘链接&#xff1a;https://pan.baidu.com/s/1G0kSC-844FtRfqGnIoMALA 提取码&#xff1a;dh4w 2.用QQ影音打开MOV文件 3.右下角打开影音工具箱 , 选择截取…...

YOLOv8改进 | Neck篇 | 利用ASF-YOLO改进特征融合层(适用于分割和目标检测)

一、本文介绍 本文给大家带来的改进机制是ASF-YOLO(发布于2023.12月份的最新机制),其是特别设计用于细胞实例分割。这个模型通过结合空间和尺度特征,提高了在处理细胞图像时的准确性和速度。在实验中,ASF-YOLO在2018年数据科学竞赛数据集上取得了卓越的分割准确性和速度,…...

基于模块自定义扩展字段的后端逻辑实现(一)

目录 一&#xff1a;背景介绍 二&#xff1a;实现过程 三&#xff1a;字段标准化 四&#xff1a;数据存储 五&#xff1a;数据扩展 六&#xff1a;表的设计 一&#xff1a;背景介绍 最近要做一个系统&#xff0c;里面涉及一个模块是使用拖拉拽的形式配置模块使用的字段表…...

力扣:18.四数之和

一、做题链接&#xff1a;18. 四数之和 - 力扣&#xff08;LeetCode&#xff09; 二、题目分析 1.做这一道题之前本博主建议先看上一篇《三数之和》 2.题目分析 给你一个由 n 个整数组成的数组 nums &#xff0c;和一个目标值 target 。请你找出并返回满足下述全部条件且不重…...

.netcore 6 ioc注入的三种方式

1、定义接口 public interface MyInterceptorInterface 2、实现接口 public class MyInterceptorImpl : MyInterceptorInterface 在构造中增加以下代码&#xff0c;便于观察 static ConcurrentDictionary<string, string> keyValues new ConcurrentDictionary<s…...

Python轴承故障诊断 (十)基于VMD+CNN-Transfromer的故障分类

目录 1 变分模态分解VMD的Python示例 2 轴承故障数据的预处理 2.1 导入数据 2.2 故障VMD分解可视化 3 基于VMDCNN-Transformer的轴承故障诊断分类 3.1 定义VMD-CNN-Transformer分类网络模型 3.2 设置参数&#xff0c;训练模型 3.3 模型评估 代码、数据如下&#xff1a…...

【复习】人工智能 第7章 专家系统与机器学习

专家系统就是让机器人当某个领域的专家&#xff0c;但这章专家系统不咋考&#xff0c;主要靠书上没有的机器学习。 一、专家系统的基本组成 二、专家系统与传统程序的比较 &#xff08;1&#xff09;编程思想&#xff1a; 传统程序 数据结构 算法 专家系统 知识 推理 &…...

使用 Apache PDFBox 操作PDF文件

简介 Apache PDFBox库是一个开源的Java工具&#xff0c;专门用于处理PDF文档。它允许用户创建全新的PDF文件&#xff0c;编辑现有的PDF文档&#xff0c;以及从PDF文件中提取内容。此外&#xff0c;Apache PDFBox还提供了一些命令行实用工具。 Apache PDFBox提供了创建、渲染、…...

【Python 常用脚本及命令系列 3.2 -- 检测到弹框跳出然后关掉它--脚本实现】

文章目录 简介脚本实现 简介 在Python中&#xff0c;你可以使用第三方库如pyautogui和pygetwindow来检测屏幕上的弹框并关闭它。这些库可以模拟鼠标和键盘操作&#xff0c;也可以获取窗口信息。 首先&#xff0c;需要安装这些库&#xff08;如果你还没有安装的话&#xff09;&…...

junit单元测试:使用@ParameterizedTest 和 @CsvSource注解简化单元测试方法

在平常的开发工作中&#xff0c;我们经常需要写单元测试。比如&#xff0c;我们有一个校验接口&#xff0c;可能会返回多种错误信息。我们可以针对这个接口&#xff0c;写多个单元测试方法&#xff0c;然后将其场景覆盖全。那么&#xff0c;怎么才能写一个测试方法&#xff0c;…...

C# winform判断自身程序是否已运行,如果已运行则激活窗体

C# winform判断自身程序是否已运行&#xff0c;如果已运行则激活窗体 using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.InteropServices; using System.Threading; using Syst…...

超维空间M1无人机使用说明书——21、基于opencv的人脸识别

引言&#xff1a;M1型号无人机不仅提供了yolo进行物体识别&#xff0c;也增加了基于opencv的人脸识别功能包&#xff0c;仅需要启动摄像头和识别节点即可 链接: 源码链接 一、一键启动摄像头和人脸识别节点 roslaunch robot_bringup bringup_face_detect.launch无报错&#…...

Redis 持久化——AOF

文章目录 为什么需要AOF?概念持久化查询和设置1. 查询AOF启动状态2. 开启AOF持久化2.1 命令行启动AOF2.2 配置文件启动 AOF 3. 触发持久化3.1 自动触发3.3 手动触发 4. AOF 文件重写4.1 什么是AOF重写&#xff1f;4.2 AOF 重写实现4.3 AOF 重写流程 5. 配置说明6. 数据恢复6.1…...

华为云服务介绍(二)

在 华为云服务介绍(一) 中我们看到华为云提供了一系列的云服务,包括计算、存储、网络、数据库、安全等方面的解决方案。通过灵活的系统架构设计,可以充分利用这些云服务技术,从而更好地满足用户的需求。 本文从系统架构的角度出发,通过充分利用华为云提供的各种云服务技…...

mysql列题

mysql列题 1.查询学过「张三」老师授课的同学的信息2.查询没有学全所有课程的同学的信息3.查询没学过"张三"老师讲授的任一门课程的学生姓名4.查询两门及其以上不及格课程的同学的学号&#xff0c;姓名及其平均成绩5.检索" 01 "课程分数小于 60&#xff0c…...

cpu缓存一致性

文章目录 cpu缓存一致性缓存的出现&#xff1a;多核之后带来的缓存一致性问题&#xff0c;如何解决LOCK 指令&#xff08;刚好可以实现上述的目标&#xff09;LOCK 指令特性内存屏障特性编译器屏障的作用MESI协议为什么有了 MESI协议 还需要 内存屏障问题&#xff1a;总结&…...

Android Framework 常见解决方案(25-1)定制CPUSET解决方案-framework部分修改

1 原理说明 这个方案有如下基本需求&#xff1a; 构建自定义CPUSET&#xff0c;/dev/cpuset中包含一个全新的cpuset分组。且可以通过set_cpuset_policy和set_sched_policy接口可以设置自定义CPUSET。开机启动后可以通过zygote判定来对特定的应用进程设置CPUSET&#xff0c;并…...

PyTorch 参数化深度解析:自定义、管理和优化模型参数

目录 torch.nn子模块parametrize parametrize.register_parametrization 主要特性和用途 使用场景 参数和关键字参数 注意事项 示例 parametrize.remove_parametrizations 功能和用途 参数 返回值 异常 使用示例 parametrize.cached 功能和用途 如何使用 示例…...

自承载 Self-Host ASP.NET Web API 1 (C#)

本教程介绍如何在控制台应用程序中托管 Web API。 ASP.NET Web API不需要 IIS。 可以在自己的主机进程中自托管 Web API。 创建控制台应用程序项目 启动 Visual Studio&#xff0c;然后从“开始”页中选择“新建项目”。 或者&#xff0c;从“ 文件 ”菜单中选择“ 新建 ”&a…...

Vue2-子传父和父传子的基本用法

在Vue 2中&#xff0c;可以使用props和$emit来实现子组件向父组件传值&#xff08;子传父&#xff09;和父组件向子组件传值&#xff08;父传子&#xff09;。 子传父&#xff08;子组件向父组件传值&#xff09;的基本用法如下&#xff1a; 在父组件中定义一个属性&#xff…...

使用numpy处理图片——镜像翻转和旋转

在《使用numpy处理图片——基础操作》一文中&#xff0c;我们介绍了如何使用numpy修改图片的透明度。本文我们将介绍镜像翻转和旋转。 镜像翻转 上下翻转 from PIL import Image import numpy as np img Image.open(example.png) data np.array(img)# axis0 is vertical, a…...

HTML5 article标签,<time>...</time>标签和pubdate属性的运用

1、<article>...</article>标签的运用 article标签代表文档、页面或应用程序中独立的、完整的、可以独自被外部引用的内容。它可以是一篇博客或报竟杂志中的文章、一篇论坛帖子、一段用户评论或一个独立的插件&#xff0c;或者其他任何独立的内容。把文章正文放在h…...

Amazing OpenAI API:把非 OpenAI 模型都按 OpenAI API 调用

分享一个有趣的小工具&#xff0c;10MB 身材的小工具&#xff0c;能够将各种不同的模型 API 转换为开箱即用的 OpenAI API 格式。 让许多依赖 OpenAI API 的软件能够借助开发者能够接触到的&#xff0c;非 OpenAI 的 API 私有部署和使用起来。 写在前面 这个小工具软件写于两…...

RK3568平台开发系列讲解(驱动篇)pinctrl 函数操作集结构体讲解

🚀返回专栏总目录 文章目录 一、pinctrl_ops二、pinmux_ops三、pinconf_ops沉淀、分享、成长,让自己和他人都能有所收获!😄 pinctrl_ops:提供有关属于引脚组的引脚的信息。pinmux_ops:选择连接到该引脚的功能。pinconf_ops:设置引脚属性(上拉,下拉,开漏,强度等)。…...