大模型笔记2 Longformer for Extractive Summarization任务的模型修改

目录

LongformerForTokenClassification调通

将7分类的预训练模型改为2分类

利用分类标签取出token对应子词

将token转换为完整单词取出


LongformerForTokenClassification调通

对应文档:

https://huggingface.co/docs/transformers/en/model_doc/longformer#transformers.LongformerForTokenClassification

下载预训练模型:

https://huggingface.co/docs/transformers/en/model_doc/longformer#transformers.LongformerForTokenClassification

修改使用模型预测与训练时的输出获取

from transformers import AutoTokenizer, LongformerForTokenClassification

import torch

# tokenizer = AutoTokenizer.from_pretrained("brad1141/Longformer-finetuned-norm")

# model = LongformerForTokenClassification.from_pretrained("brad1141/Longformer-finetuned-norm")

tokenizer = AutoTokenizer.from_pretrained("tmp/Longformer-finetuned-norm")

model = LongformerForTokenClassification.from_pretrained("tmp/Longformer-finetuned-norm")

inputs = tokenizer(

    "HuggingFace is a company based in Paris and New York", add_special_tokens=False, return_tensors="pt"

)

#预测

with torch.no_grad():

    outputs=model(**inputs)

    # 如果输出是元组,可以手动解析

    if isinstance(outputs, tuple):

        logits, = outputs

    else:

        logits = outputs.logits

predicted_token_class_ids = logits.argmax(-1)

# Note that tokens are classified rather then input words which means that

# there might be more predicted token classes than words.

# Multiple token classes might account for the same word

predicted_tokens_classes = [model.config.id2label[t.item()] for t in predicted_token_class_ids[0]]

predicted_tokens_classes

print("predicted_tokens_classes:", predicted_tokens_classes)

# 训练

labels = predicted_token_class_ids

# loss = model(**inputs, labels=labels).loss

outputs = model(**inputs, labels=labels)

if isinstance(outputs, tuple):

    loss,logits = outputs

else:

    loss = outputs.loss

round(loss.item(), 2)

print("loss:", round(loss.item(), 2))

目前输出是NER任务的针对每一个token分类:

predicted_tokens_classes ['Evidence', 'Evidence', 'Evidence', 'Evidence', 'Evidence', 'Evidence', 'Evidence', 'Evidence', 'Evidence', 'Evidence', 'Evidence', 'Evidence']

Debug很重要的一步是看模型输出的各个维度什么意思, 这个可以从源文件和文档找,

此处longformer

logits (torch.FloatTensor of shape (batch_size, sequence_length, config.num_labels)) — Classification scores (before SoftMax).

将7分类的预训练模型改为2分类

例子中的logits是[1, 12, 7], 其中sequence_length是句子中所有token的数量. config.num_labels 由config文件的id2label计算:

  "id2label": {

    "0": "Lead",

    "1": "Position",

    "2": "Evidence",

    "3": "Claim",

    "4": "Concluding Statement",

    "5": "Counterclaim",

    "6": "Rebuttal"

  },

此处将config原件保存副本, 然后修改类别为2个

"id2label": {

    "0": "Non-dataset description",

    "1": "Dataset description"

  },

为了将 Longformer 的输出从 7 分类修改为 2 分类,需要调整模型的分类层(classifier layer):

加载预训练的 LongformerForTokenClassification 模型。

修改模型的分类层。

重新初始化模型的分类层。

# 修改分类层为2分类

model.num_labels = 2

model.classifier = nn.Linear(model.config.hidden_size, model.num_labels)

# 初始化分类层权重

model.classifier.weight.data.normal_(mean=0.0, std=model.config.initializer_range)

if model.classifier.bias is not None:

    model.classifier.bias.data.zero_()

报错:

Some weights of LongformerForTokenClassification were not initialized from the model checkpoint at tmp/Longformer-finetuned-norm and are newly initialized: ['longformer.pooler.dense.weight', 'longformer.pooler.dense.bias']

You should probably TRAIN this model on a down-stream task to be able to use it for predictions and inference.

Traceback (most recent call last):

  File "d:/Projects/longformer/tests/try_tkn_clsfy.py", line 7, in <module>

    model = LongformerForTokenClassification.from_pretrained("tmp/Longformer-finetuned-norm")

  File "D:\Users\laugo\anaconda3\envs\longformer\lib\site-packages\transformers\modeling_utils.py", line 972, in from_pretrained

    model.__class__.__name__, "\n\t".join(error_msgs)

RuntimeError: Error(s) in loading state_dict for LongformerForTokenClassification:

        size mismatch for classifier.weight: copying a param with shape torch.Size([7, 768]) from checkpoint, the shape in current model is torch.Size([2, 768]).

        size mismatch for classifier.bias: copying a param with shape torch.Size([7]) from checkpoint, the shape in current model is torch.Size([2]).

还没有运行到修改分类层就报错了,

在加载模型LongformerForTokenClassification.from_pretrained这一步报错. 因为其中需要读取config.num_labels, 此时config.num_labels是2, 与它不匹配

Config中的Id2label加载时候先不改后面再代码中再改

model.config.id2label = {0: 'Non-dataset description', 1: 'Dataset description'}

model.config.label2id = {'Non-dataset description': 0, 'Dataset description': 1}

还有一个警告:

Some weights of LongformerForTokenClassification were not initialized from the model checkpoint at tmp/Longformer-finetuned-norm and are newly initialized: ['longformer.pooler.dense.weight', 'longformer.pooler.dense.bias']

手动初始化权重

model.longformer.pooler.dense.weight.data.normal_(mean=0.0, std=model.config.initializer_range)

model.longformer.pooler.dense.bias.data.zero_()

得到输出:

predicted_tokens_classes ['Dataset description', 'Non-dataset description', 'Non-dataset description', 'Non-dataset description', 'Non-dataset description', 'Non-dataset description', 'Non-dataset description', 'Non-dataset description', 'Non-dataset description', 'Non-dataset description', 'Non-dataset description', 'Non-dataset description']

利用分类标签取出token对应子词

现在将分类为1, 即predicted_tokens_classes 为'Dataset description'的取出.

for k, j in enumerate(predicted_tokens_classes):# j is label, k is index

    if (len(predicted_tokens_classes)>1):

        if (j=='Dataset description') & (k==0):

            # print("j:",j,";k:",k)

            #if it's the first word in the first position

            #print('At begin first word')

            begin = tokenized_sub_sentence[k]

            kword = begin

        elif (j=='Dataset description') & (k>=1) & (predicted_tokens_classes[k-1]=='Non-dataset description'):

            #begin word is in the middle of the sentence

            begin = tokenized_sub_sentence[k]

            previous = tokenized_sub_sentence[k-1]

            if begin.startswith('Ġ'):

                kword = previous + begin[1:]

            else:

                kword = begin

            if k == (len(predicted_tokens_classes) - 1):

                #print('begin and end word is the last word of the sentence')

                kword_list.append(kword.rstrip().lstrip())

        elif (j=='Dataset description') & (k>=1) & (predicted_tokens_classes[k-1]=='Dataset description'):

            # intermediate word of the same keyword

            inter = tokenized_sub_sentence[k]

            if inter.startswith('Ġ'):

                kword = kword + "" + inter[1:]

            else:

                kword = kword + " " + inter

            if k == (len(predicted_tokens_classes) - 1):

                #print('begin and end')

                kword_list.append(kword.rstrip().lstrip())

        elif (j=='Non-dataset description') & (k>=1) & (predicted_tokens_classes[k-1] =='Dataset description'):

            # End of a keywords but not end of sentence.

            kword_list.append(kword.rstrip().lstrip())

            kword = ''

            inter = ''

    else:

        if (j=='Dataset description'):

            begin = tokenized_sub_sentence[k]

            kword = begin

            kword_list.append(kword.rstrip().lstrip())

输出结果

Hug ging Face is a company based in Paris and New York

tokenized_sub_sentence: ['ĠHug', 'ging', 'Face', 'Ġis', 'Ġa', 'Ġcompany', 'Ġbased', 'Ġin', 'ĠParis', 'Ġand', 'ĠNew', 'ĠYork']

kword_list shape: 2

 ['ĠHug ging Face', 'Ġcompany']

kword_text:

 <unk> company

Hug ging Face is a company based in Paris and New York

可以看出是Hug ging Face由于中间空格没有去除, token转id识别不出来

因此注释了输出中添加空格的代码

            # else:

                # kword = kword + " " + inter

现在可以正常输出, 但是对于一个单词包含多个token的情况, 它识别出其中部分token导致输出(kword_text)不是完整单词

tokenized_sub_sentence: ['ĠHug', 'ging', 'Face', 'Ġis', 'Ġa', 'Ġcompany', 'Ġbased', 'Ġin', 'ĠParis', 'Ġand', 'ĠNew', 'ĠYork']

 ['gingFace', 'Ġcompany']

kword_text:

 gingFace company

在 BPE 中,子词 token 通常以 ## 开头,表示这是前一个 token 的一部分

但这里用的是另一个字符Ġ

from transformers import AutoTokenizer, LongformerForTokenClassification

现在需要处理包含多个token的单词, 将包含token分类为1的单词不重复地输出

将token转换为完整单词取出

但是当后面的token在列表中, 前面的不在, 只输出了后面一半的token

kword_list: ['ging', 'Face', 'Ġis', 'Ġa', 'Ġcompany', 'Ġbased', 'Ġin', 'ĠParis', 'Ġand', 'ĠNew', 'ĠYork']

kword_text:

 gingFace is a company based in Paris and New York

unique_kword_list:

 ['ging', 'Face', 'Ġis', 'Ġa', 'Ġcompany', 'Ġbased', 'Ġin', 'ĠParis', 'Ġand', 'ĠNew', 'ĠYork']

合并单词

目前得到的token为tokenized_sub_sentence,

predicted_tokens_classes是针对每一个token是否符合要求的分类,

当单词中包含'Dataset description'类的token, 将该单词取出.

使用 'Ġ' 来检测新单词的开始,并将这些子词正确地连接在一起。这样可以避免不同单词被错误地连接在一起。

这个似乎是成功了

  使用 'Ġ' 检测新单词的开始。

  拼接属于同一个单词的 token。

  如果一个单词中的任何一个 token 被预测为 'Dataset description',则将整个单词加入到 dataset_description_words 列表中。

dataset_description_words = []

current_word = ""

current_word_pred = False

for token, pred_class in zip(tokenized_sub_sentence, predicted_tokens_classes):

    if token.startswith("Ġ"):

        if (len(current_word)!=0) & current_word_pred:#前面有上一个单词, 且其中有描述token, 则把它存入句子

            dataset_description_words.append(current_word)

        current_word = token[1:]

        current_word_pred = (pred_class == 'Dataset description')

        # print("start: ",current_word)

        # print("dataset_description_words: ",dataset_description_words)

        # print("current_word_pred: ",current_word_pred)

    else:

        current_word += token

        current_word_pred = current_word_pred or (pred_class == 'Dataset description')#如果不是词开头, 现在token和之前已有token只要有1类的都行

        # print("mid: ",current_word)

        # print("current_word_pred: ",current_word_pred)

#最后一个单词后没有下一个单词的开始符号, 无法进入循环, 单独判断

if (len(current_word)!=0) & current_word_pred:

    dataset_description_words.append(current_word)

拼接所有'Dataset description' 类 token 的单词为一个完整的字符串

final_dataset_description_string = " ".join(dataset_description_words)

示例分类:

tokenized_sub_sentence: ['ĠHug', 'ging', 'Face', 'Ġis', 'Ġa', 'Ġcompany', 'Ġbased', 'Ġin', 'ĠParis', 'Ġand', 'ĠNew', 'ĠYork']

predicted_tokens_classes=['Non-dataset description', 'Dataset description', 'Non-dataset description', 'Dataset description', 'Non-dataset description', 'Dataset description', 'Dataset description', 'Dataset description', 'Dataset description', 'Dataset description', 'Dataset description', 'Dataset description']

输出结果:

predicted_tokens_classes ['Dataset description', 'Dataset description', 'Dataset description', 'Dataset description', 'Non-dataset description', 'Non-dataset description', 'Non-dataset description', 'Dataset description', 'Dataset description', 'Dataset description', 'Dataset description', 'Dataset description']

tokenized_sub_sentence: ['ĠHug', 'ging', 'Face', 'Ġis', 'Ġa', 'Ġcompany', 'Ġbased', 'Ġin', 'ĠParis', 'Ġand', 'ĠNew', 'ĠYork']

dataset_description_string: HuggingFace is in Paris and New York

运行过程:

start:  Hug

dataset_description_words:  []

current_word_pred:  False

mid:  Hugging

current_word_pred:  True

mid:  HuggingFace

current_word_pred:  True

start:  is

dataset_description_words:  ['HuggingFace']

current_word_pred:  True

start:  a

dataset_description_words:  ['HuggingFace', 'is']

current_word_pred:  False

start:  company

dataset_description_words:  ['HuggingFace', 'is']

current_word_pred:  True

start:  based

dataset_description_words:  ['HuggingFace', 'is', 'company']

current_word_pred:  True

start:  in

dataset_description_words:  ['HuggingFace', 'is', 'company', 'based']

current_word_pred:  True

start:  Paris

dataset_description_words:  ['HuggingFace', 'is', 'company', 'based', 'in']

current_word_pred:  True

start:  and

dataset_description_words:  ['HuggingFace', 'is', 'company', 'based', 'in', 'Paris']

current_word_pred:  True

start:  New

dataset_description_words:  ['HuggingFace', 'is', 'company', 'based', 'in', 'Paris', 'and']

current_word_pred:  True

start:  York

dataset_description_words:  ['HuggingFace', 'is', 'company', 'based', 'in', 'Paris', 'and', 'New']

current_word_pred:  True

unfiltered_dataset_description_string: HuggingFace is company based in Paris and New York

final_dataset_description_string: is based Paris and New York

完整代码:

from transformers import AutoTokenizer, LongformerForTokenClassification

# from transformers import Trainer, TrainingArguments

import torch

import torch.nn as nn

tokenizer = AutoTokenizer.from_pretrained("tmp/Longformer-finetuned-norm")

model = LongformerForTokenClassification.from_pretrained("tmp/Longformer-finetuned-norm")

# print("set num_labels begin")

# 修改分类层为2分类

model.num_labels = 2

model.config.num_labels = 2

model.classifier = nn.Linear(model.config.hidden_size, model.num_labels)

# 手动初始化权重

model.longformer.pooler.dense.weight.data.normal_(mean=0.0, std=model.config.initializer_range)

model.longformer.pooler.dense.bias.data.zero_()

# 初始化分类层权重

model.classifier.weight.data.normal_(mean=0.0, std=model.config.initializer_range)

if model.classifier.bias is not None:

    model.classifier.bias.data.zero_()

   

# print("set weight zero")

# 更新 id2label 和 label2id

model.config.id2label = {0: 'Non-dataset description', 1: 'Dataset description'}

model.config.label2id = {'Non-dataset description': 0, 'Dataset description': 1}

sentence="HuggingFace is a company based in Paris and New York."

inputs = tokenizer(

    sentence, add_special_tokens=False, return_tensors="pt"

)

# print("inputs id:",inputs["input_ids"])#id无法判断token是不是同一个词, 所以不能使用

#预测

with torch.no_grad():

    outputs=model(**inputs)

    # 如果输出是元组,可以手动解析

    if isinstance(outputs, tuple):

        logits, = outputs

    else:

        logits = outputs.logits

predicted_token_class_ids = logits.argmax(-1)

# Note that tokens are classified rather then input words which means that

# there might be more predicted token classes than words.

# Multiple token classes might account for the same word

predicted_tokens_classes = [model.config.id2label[t.item()] for t in predicted_token_class_ids[0]]

print("predicted_tokens_classes",predicted_tokens_classes)

#token类别转化为词输出

tokenized_sub_sentence = tokenizer.convert_ids_to_tokens(inputs["input_ids"][0])

print("tokenized_sub_sentence:", tokenized_sub_sentence)

# 示例分类

# predicted_tokens_classes=['Non-dataset description', 'Dataset description', 'Non-dataset description', 'Dataset description', 'Non-dataset description', 'Dataset description', 'Dataset description', 'Dataset description', 'Dataset description', 'Dataset description', 'Dataset description', 'Dataset description']

# 将预测类别为 'Dataset description' 的 token 所在的单词取出

dataset_description_words = []

current_word = ""

current_word_pred = False

for token, pred_class in zip(tokenized_sub_sentence, predicted_tokens_classes):

    if token.startswith("Ġ"):

        if (len(current_word)!=0) & current_word_pred:#前面有上一个单词, 且其中有描述token, 则把它存入句子

            dataset_description_words.append(current_word)

        current_word = token[1:]

        current_word_pred = (pred_class == 'Dataset description')

        # print("start: ",current_word)

        # print("dataset_description_words: ",dataset_description_words)

        # print("current_word_pred: ",current_word_pred)

    else:

        current_word += token

        current_word_pred = current_word_pred or (pred_class == 'Dataset description')#如果不是词开头, 现在token和之前已有token只要有1类的都行

        # print("mid: ",current_word)

        # print("current_word_pred: ",current_word_pred)

#最后一个单词后没有下一个单词的开始符号, 无法进入循环, 单独判断

if (len(current_word)!=0) & current_word_pred:

    dataset_description_words.append(current_word)

# 拼接所有包含 'Dataset description' 类 token 的单词为一个完整的字符串

dataset_description_string = " ".join(dataset_description_words)

print("dataset_description_string:", dataset_description_string)

##############################################################

# 训练

labels = predicted_token_class_ids

# loss = model(**inputs, labels=labels).loss

outputs = model(**inputs, labels=labels)

if isinstance(outputs, tuple):

    loss,logits = outputs

else:

    loss = outputs.loss

loss_value=round(loss.item(), 2)

print("loss_value",loss_value)

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

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

相关文章

【大模型LLM面试合集】大语言模型架构_attention

1.attention 1.Attention 1.1 讲讲对Attention的理解&#xff1f; Attention机制是一种在处理时序相关问题的时候常用的技术&#xff0c;主要用于处理序列数据。 核心思想是在处理序列数据时&#xff0c;网络应该更关注输入中的重要部分&#xff0c;而忽略不重要的部分&…

java webservice 根据wsdl文件生成客户端代码;webservice可视化测试工具SOAPUI;

背景 最近要对接HIS系统&#xff0c;对方提供的接口是webservice的&#xff08;有点古老&#xff09;&#xff0c;对方是webservice的提供方&#xff0c;提供了wsdl文件&#xff0c;我方需要根据wsdl文件生成java代码&#xff0c;intellij idea生成webservice客户端代码支持的…

复分析——第10章——Θ函数应用(E.M. Stein R. Shakarchi)

第10章 Θ函数的应用 (Applications of Theta Functions) The problem of the representation of an integer n as the sum of a given number k of integral squares is one of the most celebrated in the theory of numbers. Its history may be traced back to Diopha…

列表渲染 v-for

列表渲染v-for 使用v-for指令基于数组渲染一个列表&#xff0c;v-for指令的值需要使用item in/of items形式的特殊语法&#xff0c;其中items是源数据的数组&#xff0c;而item是迭代的别名。 代码实例&#xff1a; <template> <div><p v-for"item in na…

Java基础概念

1.注释和关键字 &#xff08;1&#xff09;注释 什么是注释&#xff1f;注释就是对代码进行解释说明的文字 注释的分类&#xff1f;单行注释&#xff0c;多行注释&#xff0c;文档注释 注释的使用细节&#xff1f; 注释的内容不会参与编译和运行&#xff0c;仅仅是对代码的…

使用vllm部署大语言模型

vLLM是一个快速且易于使用的库&#xff0c;用于LLM&#xff08;大型语言模型&#xff09;推理和服务。通过PagedAttention技术&#xff0c;vLLM可以有效地管理注意力键和值内存&#xff0c;降低内存占用和提高计算效率。vLLM能够将多个传入的请求进行连续批处理&#xff0c;从而…

智能视频监控如何助力体育场馆安全管理:安防监控EasyCVR视频综合管理方案

近期有新闻报道&#xff0c;6月30日&#xff0c;17岁的中国国家羽毛球运动员在亚洲青年羽毛球锦标赛中&#xff0c;突然晕倒并抽搐&#xff0c;尽管被送往医院抢救&#xff0c;该运动员仍在当晚不幸离世。运动猝死不仅发生于职业运动员身上&#xff0c;在普通健身者中也时有发生…

nodejs + vue3 模拟 fetchEventSouce进行sse流式请求

先上效果图: 前言: 在GPT爆发的时候,各项目都想给自己的产品加上AI,蹭上AI的风口,因此在最近的一个需求,就想要给项目加入Ai的功能,原本要求的效果是,查询到对应的数据后,完全展示出来,也就是常规的post请求,后来这种效果遇到了一个很现实的问题:长时间的等待。我…

4个方法帮助你解决RAR解压文件时提示密码错误问题

在日常工作和学习中&#xff0c;我们经常需要处理各种压缩文件&#xff0c;这些文件有时为了保护内容安全&#xff0c;会被设置密码。然而&#xff0c;在解压这些文件时&#xff0c;如果遇到“密码错误”的提示&#xff0c;可能会让人感到十分棘手。今天&#xff0c;我们就来探…

[ICS] Modbus未授权攻击S7协议漏洞利用

工业控制系统历史 在可编程逻辑控制器(plc)成为标准之前&#xff0c;工厂车间自动化是通过机架和机架的工业继电器&#xff0c;气动柱塞计时器和电磁计数器来控制电机的启动和停止&#xff0c;阀门的打开以及其他与控制相关的过程交互。运行这种设置的控制程序根本不是程序&am…

如何使用 pytorch 创建一个神经网络

我已发布在&#xff1a;如何使用 pytorch 创建一个神经网络 SapientialM.Github.io 构建神经网络 1 导入所需包 import os import torch from torch import nn from torch.utils.data import DataLoader from torchvision import datasets, transforms2 检查GPU是否可用 dev…

Vue3基础知识:组合式API中的provide和inject,他们作用是什么?如何使用?以及案例演示

1.provide和inject相较于父子传递的不同在于provide,inject可以用于跨层级通信&#xff08;通俗易懂的讲就是可以实现爷孙之间的直接信息传递&#xff09;。 1.跨层级传递数据 1.在顶层组件通过provide函数提供数据 2.底层组件通过inject函数获取数据 演示一&#xff1a;跨…

Linux安装Jmeter及简单使用教程

Linux安装Jmeter 首先需要java环境 java --version官网 下载二进制包 #创建文件夹 sudo mkdir /usr/local/jmeter #解压 sudo tar zxvf apache-jmeter-5.6.3.tgz -C /usr/local/jmeter编辑配置文件 sudo vim /etc/profile&#xff0c;添加以下内容 export JMETER_HOME/usr/l…

【Linux系列2】Cmake安装记录

方法一 1. 查看当前cmake版本 [rootlocalhost ~]# cmake -version cmake version 2.8.12.22. 进行卸载 [rootlocalhost ~]# yum remove -y cmake3. 进行安装包的下载&#xff0c;也可以下载好安装包后传至相应的目录 [rootlocalhost ~]# mkdir /opt/cmake [rootlocalhost ~…

安防监控/视频汇聚平台EasyCVR设备录像回看请求播放时间和实际时间对不上,是什么原因?

安防监控EasyCVR视频汇聚平台可提供多协议&#xff08;RTSP/RTMP/国标GB28181/GAT1400/海康Ehome/大华/海康/宇视等SDK&#xff09;的设备接入、音视频采集、视频转码、处理、分发等服务&#xff0c;系统具备实时监控、云端录像、回看、告警、平台级联以及多视频流格式分发等视…

二手闲置平台小程序的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;用户管理&#xff0c;卖家管理&#xff0c;商品分类管理&#xff0c;商品信息管理&#xff0c;商品购买管理&#xff0c;商品配送管理 微信端账号功能包括&#xff1a;系统首页&#xff0c;商品信息&a…

Xilinx FPGA:vivado关于IIC的一些零碎知识点

一、简介 IlC(inter-Integrated circuit)总线是一种由NXP(原PHILIPS)公司开发的两线式串行总线&#xff0c;用于连接微控制器及其外围设备。多用于主控制器和从器件间的主从通信&#xff0c;在小数据量场合使用&#xff0c;传输距离短&#xff0c;任意时刻只能有一个主机等特性…

RoPE旋转位置编码从复数到欧拉公式

第二部分 从复数到欧拉公式 先复习下复数的一些关键概念 我们一般用表示复数&#xff0c;实数a叫做复数的实部&#xff0c;实数b叫做复数的虚部 复数的辐角是指复数在复平面上对应的向量和正向实数轴所成的有向角 的共轭复数定义为&#xff1a;&#xff0c;也可记作&#xff0…

鸿蒙开发:Universal Keystore Kit(密钥管理服务)【密钥使用介绍及通用流程】

密钥使用介绍及通用流程 为了实现对数据机密性、完整性等保护&#xff0c;可使用生成/导入的密钥&#xff0c;对数据进行密钥操作&#xff0c;比如&#xff1a; [加密解密][签名验签][密钥协商][密钥派生]开发前请熟悉鸿蒙开发指导文档&#xff1a;gitee.com/li-shizhen-skin…

前端面试题28(Vue3的Teleport功能在什么场景下特别有用?能给个例子吗?)

Vue 3 的 Teleport 功能在需要将组件的渲染结果放置在 DOM 树中与当前组件位置无关的任意位置时特别有用。这通常涉及到需要将某些UI元素&#xff08;如模态框、弹出菜单、通知、工具提示等&#xff09;从其逻辑上的父级组件中“提取”出来&#xff0c;放置到页面的更高层级或完…