PaddleNLP实战——信息抽取(InfoExtraction)

[ 文章目录 ]

  • 1. 信息抽取任务是什么?
  • 2. 基于PaddleNLP的信息抽取任务
    • 2.1 训练任务概览
    • 2.2 Predicate列表
    • 2.3 SPO列表
    • 2.4 代码解析

1. 信息抽取任务是什么?

在NLP任务中,通常当我们拿到一段文本时,我们希望机器去理解这段文本描述的是什么内容,进而完成一些特定的任务。

例如,现在有这么一句话:

  • 今日,在玩家们的期待中,王者荣耀终于上架了李白的新皮肤——凤求凰。

这句话中具体描述了什么事件呢?人类一看就知道,哦,王者出了一款李白的新皮肤。

没错,这句话的核心就是「王者」「出了」「李白」「新皮肤」。

至于「…在玩家们的…」这些文字大概率直接被读者自动给过滤掉了,这就是人类天然存在的超强信息提取的能力。

扩展:人类除了在阅读文字上有着超强的信息抽取能力,在听觉上同样如此,大部分人都能在多人同时说话的场景下清楚的听取想听的那个人说话的内容。同样的,学者们也尝试让机器具备同样的能力,Speech Separation的其中一个研究方向便是如此。

为此,我们希望机器也能具备人类一样的信息抽取能力,能够在一段文字中自动抽出一组一组成对的关键信息

我们再来回顾一下刚才那句话,句子中包含两个主要信息:

  1. 王者出了一款新皮肤。
  2. 这款新皮肤是李白的。

这两个主要信息都可以用基本的三元组的结构来表示:

  1. 王者(主语) - 出了(谓语) - 新皮肤(宾语)
  2. 新皮肤(主语) - 属于(谓语) - 李白(宾语)

不难看出,不管多么复杂的句子和多么复杂的关系,最后都是可以被细分为若干个三元组,即:
(Entity1,Relation,Entity2)(Entity_1, Relation, Entity_2) (Entity1,Relation,Entity2)

**实体(Entity)**是NLP领域中的常用语,用于描述某一个「东西」,这个「东西」通常用于描述一种词语类别.

比如「游戏」就可以被定义为一种实体,举例来说,有如下句子:王者荣耀和和平精英都是当下比较流行的游戏。

该句子中就包含了2个「游戏」实体:王者荣耀(GameEntity1)和和平精英(GameEntity2)都是当下比较流行的游戏。

此外,在信息提取(InfoExtraction)领域中,我们需要将关系(Relation)前后的两个实体稍稍区分一下:

关系(Relation)前面的实体(Entity1)我们称之为头实体(Subject);

关系(Relation)后面的实体(Entity2)我们称之为尾实体(Object);

这就是我们常说的SPO表示法。S-头实体,O-尾实体,P-Predicate,即「关系(Relation)」更专业的叫法。
王者荣耀(S)−出了(Predicate)−凤求凰(O)凤求凰(S)−属于(Predicate)−李白(O)王者荣耀(S)- 出了(Predicate)- 凤求凰(O)\\ 凤求凰(S)- 属于(Predicate)- 李白(O) 耀SPredicateOSPredicateO
至此,我们已经明白了什么是信息抽取(抽取句子中的SPO结构体),以及什么是SPO结构体(描述实体关系的最小单位),那么接下来就开始进行实战吧。

2. 基于PaddleNLP的信息抽取任务

这篇文章中将选择使用PaddleNLP作为辅助来完成信息抽取任务,所用的数据集/示例代码均能在PaddleNLP官网上找到,并且很方便的为我们提供了运行环境,不用自己手搭环境、下载数据集。接下来的内容只是在官方资料的基础上加上一些自己的理解,有兴趣小伙伴可以参考下面的官方资料:

  • 官方视频资料:https://aistudio.baidu.com/aistudio/education/lessonvideo/2016982
  • 官方示例代码:https://aistudio.baidu.com/aistudio/projectdetail/3190877?forkThirdPart=1

2.1 训练任务概览

本次实战的数据集来自于千言数据集,是一个很全面的中文开源数据集合,这次我们将选取其中「信息抽取」任务相关的数据集。

我们先从训练数据集中随机挑出一条样本来看看:

{"text": "2013年,哈密地区户籍人口约58万人", "spo_list": [{"predicate": "人口数量", "object_type": {"@value": "Number"}, "subject_type": "行政区", "object": {"@value": "58万"}, "subject": "哈密"}]
}

分析一下这一条数据,输入的是一句话:「2013年,哈密地区户籍人口约58万人」。

我们需要提取出该句子中全部的SPO关系(1个,spo_list中表示):
哈密(S)−人口数量(P)−58万(O)哈密(S)- 人口数量(P)- 58万(O) SP58O
其中,“subject”、“predicate”、"object"分别代表SPO三个值;

“subject_type” 和 "object_type"代表头/尾实体的类型,这个我们将放在后面讲。

至此我们已经明白了数据集中样本长什么样,我们的任务目标就是将一个句子(text)当中所有的SPO结构体(spo_list)给提取出来

2.2 Predicate列表

在明确了提取SPO的任务目标后,我们首先要做的事情就是对所有可能的Predicate进行枚举。

Predicate的本质是定义了两个实体之间的「关系」,因此,我们需要告诉模型,模型需要提取哪些「关系」。

例如,有如下句子:

  • 张裕妃,顺天府涿州人,父张世登,母段氏

这个句子中就存在两种实体关系

  1. 张裕妃(S)- 父亲(P1)- 张世登(O1)
  2. 张裕妃(S)- 母亲(P2)- 段氏(O2)

其中,父亲母亲就是两种不同的实体关系(即不同的Predicate)。

因此,我们首先需要先对数据集进行分析,枚举出所有实体之间可能存在的实体关系,并记录下来。

这个「实体关系列表」就是项目文件下的 “predicate2id.json” 文件所表达的意思,我们将该文件打印出来看看:

{"O": 0, "I": 1, "注册资本": 2, "作者": 3, "所属专辑": 4, "歌手": 5,..."上映时间_@value": 8, "上映时间_inArea": 9,...
}

这个json文件中定义了所有可能的实体关系(Predicate),其中O和I和BIO(Begin,Intermediate,Other)标记法中的O、I完全一致,这里不再赘述,除了O、I以外,剩下的就是数据集中所有可能的实体关系了。

例如,

作者」就代表了一种实体关系:

[+]《道学的病理》是2007年商务印书馆出版的图书,作者是韩东育 →\rightarrow《道学的病理》的作者是韩东育

歌手」也代表了一种实体关系:

[+] 写历史作业时,林俊杰的《曹操》和周杰伦的《爱在西元前》混搭,绝配 →\rightarrow《曹操》的歌手是林俊杰

注意,实体关系(Predicate)不一定必须出现在原文本中。如「作者」出现在了第一句中;但「歌手」没有出现在第二句文本中。

这里可能有同学注意到了8号&9号实体关系有些奇怪,同样都是「上映时间」为什么后缀不同,一个是_@value,一个是_inArea,这个我们放到下一节讲。

2.3 SPO列表

在我们了解完实体关系(Predicate)列表后,我们已经明白数据集当中有哪些实体关系了,现在我们需要关注数据集当中有哪些实体了。

还记得实体是什么吗?

我们之前提到过,实体关系是用来连接首、尾实体的,因此,这里的实体应当枚举数据集中所有存在的实体类型

那什么是实体类型呢?实体类型的实质就是对所有的实体按类别进行归类后,得到的类别标签。

举例来讲,

[+] 杨幂出演了《绣春刀》里的北斋。

[+] 胡歌出演了《琅琊榜》中的梅长苏。

这两句话中,「杨幂」和「胡歌」是两个实体,但这两个实体都对应同一种实体类型——演员。

实体类型是可以按照自己的需求来自己定义的,这取决于要做什么任务。

这很好理解:

如果我们要做一个针对影视作品的信息提取模型,那我们的实体类型就可能是:影视作品、演员、导演…等等。

但如果我们要做一个游戏内容的提取模型,那我们的实体类型就有可能是:英雄、技能、皮肤…等等。

在SPO列表中,对于头实体(S)和尾实体(O)的类型进行了分开表示,即,分为头实体类型(subject_type)尾实体类型(object_type)

类型列表在项目目录下 “id2spo.json” 文件中存储,我们打印该文件看看:

{"predicate": ["empty", "empty", "注册资本", "作者", "所属专辑", ...], "subject_type": ["empty", "empty", "企业", "图书作品", "歌曲", ...], "object_type": ["empty", "empty", "Number", "人物", "音乐专辑", ...]
}

可以看到,该json文件下存放了三个list,分别代表了SPO的对应type类型。

其中,每一个列表中对应的索引是可以构成一个合法三元组的,我们将相同索引的各列表中的列表组合打印出来,结果如下:

----------------------   S  |   P   |   O
----------------------
empty | empty | empty
empty | empty | empty
企业 | 注册资本 | Number
图书作品 | 作者 | 人物
歌曲 | 所属专辑 | 音乐专辑
歌曲 | 歌手 | 人物
行政区 | 邮政编码 | Text
影视作品 | 主演 | 人物
影视作品 | 上映时间 | Date_@value
影视作品 | 上映时间 | 地点_inArea
娱乐人物 | 饰演 | 人物_@value
娱乐人物 | 饰演 | 影视作品_inWork
...

其中,前2个empty是为了O和I标签留的,因为之前定义的predicate列表中的前2个标签分别为O、I,这两个标签不会起到连接首尾实体的作用,因此需要置为empty。

注意看这两行:

...
影视作品 | 上映时间 | Date_@value
影视作品 | 上映时间 | 地点_inArea
...

还记得我们在1.2.2节中提到的奇怪的问题吗,为什么同一个实体关系「上映时间」会有两个不同的后缀——上映时间_@value和上映时间_inArea?

想必你已经在这个表中找到答案了吧?

原因就是,同一个「头实体(S) - 实体关系(P)- ?」可能会对应多个不同的尾实体(O)。

举例来讲,

[+]《大耳朵图图之美食狂想曲》的动画电影将于2017年7月28日在中国上映

这句话当中,《大耳朵图图之美食狂想曲》(S)- 上映(P)- ?,同一个SP可以对应两个不同的O:

  1. 《大耳朵图图之美食狂想曲》(S)- 上映(P)- 2017年7月28日(O1)
  2. 《大耳朵图图之美食狂想曲》(S)- 上映(P)- 中国(O2)

第一个SPO代表电影-上映-上映时间;

第二个SPO代表电影-上映-上映地点;

由此我们可以看出,对于同一个S-P,句子中是可能存在多个不同的合法O的,那我们就需要使用两个或多个不同的S-P来对应这些不同的O。

一种最常见的方法就是对P再进行细分,尾实体O不是既有可能是上映时间,也有可能是上映地点吗。那我就直接分别设定两个不同的P(上映时间)标签就好了,即:

  1. 上映时间_@value:用于连接实体类型为「时间」的尾实体。
  2. 上映时间_inArea:用于连接实体类型为「地点」的尾实体。

这就是我们对应在尾实体列表(object_type)中看到存在 […, Date_@value, 地点_inArea, …] ,在predicate2id文件中看到 […, “上映时间_@value”, “上映时间_inArea”, …] 的原因。

这里顺带再提一句,我们看看在训练数据集中这种关系是如何表示的:

{	... "spo_list": [{"predicate": "上映时间", "object_type": {"inArea": "地点", "@value": "Date"}, "subject_type": "影视作品", "object": {"inArea": "中国", "@value": "4月14日"}, "subject": "垫底辣妹"}...
}

可以看到,训练数据集中,“object_type” 和 “object” 字段对应的都是一个字典(可以包含多个值),而SP对应的都是一个唯一的值。

这就印证了我们刚才的说法,确定一组S-P,可以对应多个不同的尾实体O。

但是,这里和prediacte2id.json中不同,训练集中的predicate的值并不包含标签后缀,不是「上映时间_@value」,而直接就是「上映时间」。

这样将原来的predicate后缀变化到 "object"字段中的key中,其实更符合人们的认知,毕竟关系不应该存在区别,区别的应该是实体类型。

2.4 代码解析

在该任务中,我们将实体关系抽取问题建模为Token Classification的问题。

我们知道,在命名实体识别(Named Entity Recognition,NER)问题中,通常会用Token Classification的方式来进行任务求解,即判断每个字符(token)属于哪个类别(某个实体?非实体?)。

在NER任务中使用字符分类的方式我们非常容易就理解,但是,我们怎么通过对字符分类的方式来提取出不同实体之间的关系呢?

答案就是:在字符类别中添加入「关系标签」,即该字符是否能和这句话当中的其他字符产生关联关系。

这个想法相当简单暴力,也相当符合神经网络「硬train一发」的核心原则。

模型结构图如下所示:

可以看到,对每个token,label一共有(2N + 2)维,其中 N 为我们之前所讲的 predicate 的类别个数。

这还是比较好理解,每个词既可能作为一个实体关系(Predicate)的头实体(S),也有可能作为尾实体(O),所以实体关系类别有N个,那么一个字符总共可能的 label 数就为 2N。

那么为什么还要 +2呢?因为某些字符可能只是无效信息(O),或是词中字符(I)(注:这个标注体系中只对B-进行实体类型分类,I就不用做分类了),因此整体维度还要再 +2。

还有一点非常重要,在传统的多分类任务中,我们是在N个label中选择1个类别作为最后的结果,使用的是softmax + corss_entropy;但在这个任务中,我们不使用softmax + CE,而是使用Binary Cross Entropy Loss(BCE Loss)

仔细想想,这个任务和传统的多分类任务有何不同。对于每个字符来讲,其只能属于某一种类别吗?

举例来讲:

[+] 李白的皮肤叫凤求凰,技能为青莲剑歌。

这句话中李白(S)即可以是皮肤凤求凰(O)的头实体,也可以是技能青莲剑歌(O)的头实体。

即,在这2个类别的对应label都应该为1。

这种可能属于多个不同标签的任务叫做多标签分类任务(不同于多分类任务),其对于每个标签都建立一个sigmoid函数,判断其属于这个标签结果为0还是1(不同于softmax只选择概率最大的一个标签)。

  • 模型搭建

该任务是基于ERNIE 1.0(基于Transformer Encoder的模型,大体和BERT一样,预训练方式不同,对中文支持更友好)作为pre-trained model实现的,paddle提供了很方便的高阶API,能够让我们快速导入ERNIE模型。

from paddlenlp.transformers import ErnieForTokenClassification, ErnieTokenizerlabel_map_path = os.path.join('data', "predicate2id.json")
num_classes = (len(label_map.keys()) - 2) * 2 + 2			     # 每个token可能的类别总数model = ErnieForTokenClassification.from_pretrained("ernie-1.0", num_classes=num_classes)
tokenizer = ErnieTokenizer.from_pretrained("ernie-1.0")
inputs = tokenizer(text="这是一条测试数据", max_seq_len=20)
print(inputs)

model 和 tokenizer可以直接导入预训练模型(model为神经网络模型,tokenizer为文本预处理模型)。

我们输入一条测试文本「这是一条测试数据」,并打印出被tokenizer encode后的结果:

{'input_ids': [1, 47, 10, 7, 304, 558, 525, 179, 342, 2], 'token_type_ids': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
}

encode后结果是一个json,包含 ‘input ids’ 和 ‘token_type_ids’。

> input ids

文字对应的索引index,文字与index的对应关系在模型预训练的时候就已经规定好了,我们可以看看ERNIE模型中的文字-索引对应关系(只展示前10个数据):

[PAD]
[CLS]
[SEP]
[MASK]
,
的
、
一
人
有
...
...
...

可以看到,ERNIE 1.0的前4个token id都对应的是功能token,从第5个token id起为文字、标点对应的token id。

> token_type_ids

这个列表用于表示当前token属于第几个句子

在某些任务中,例如QA(问答系统)任务,我们的输入会是两条(问题 & 文章)甚至两条以上的句子,token_type_ids用于表征当前字符token属于第几个句子(从0开始表示第一个句子)。

注意,开始符[CLS]和句子分割符[SEP]都会归类为第一条/上一条句子。

  • 损失函数构建 & 模型训练

搭建完模型后,我们现在对损失函数进行设计,进而进行模型训练。

在小节开头我们说明了,该任务为一个多标签分类任务,应使用的BCE作为Loss Function,实现如下:

import paddle.nn as nnclass BCELossForDuIE(nn.Layer):def __init__(self, ):super(BCELossForDuIE, self).__init__()self.criterion = nn.BCEWithLogitsLoss(reduction='none')def forward(self, logits, labels, mask):loss = self.criterion(logits, labels)mask = paddle.cast(mask, 'float32')loss = loss * mask.unsqueeze(-1)loss = paddle.sum(loss.mean(axis=2), axis=1) / paddle.sum(mask, axis=1)loss = loss.mean()return loss

其中mask(0/1列表)的作用为去掉一些特殊符号(如[SEP],[CLS]等功能符号)的分类结果Loss,因为这些功能符号的token分类结果无关紧要,因此不计算它们的token loss用作反向传播。

接下来实例化优化器Optimizer:

from paddlenlp.transformers import LinearDecayWithWarmuplearning_rate = 2e-5
num_train_epochs = 5
warmup_ratio = 0.06criterion = BCELossForDuIE()# Defines learning rate strategy.
steps_by_epoch = len(train_data_loader)
num_training_steps = steps_by_epoch * num_train_epochs
lr_scheduler = LinearDecayWithWarmup(learning_rate, num_training_steps, warmup_ratio)
optimizer = paddle.optimizer.AdamW(learning_rate=lr_scheduler,parameters=model.parameters(),apply_decay_param_fun=lambda x: x in [p.name for n, p in model.named_parameters()if not any(nd in n for nd in ["bias", "norm"])])		# 只对weights做退火策略

通常,在进行大模型的Fine-Tune过程中我们需要使用DecayWithWarmup 策略来使得模型具备更好的训练效果。

这是因为,pre-trained model通常比较大,且在较为复杂的数据集上完成了训练。当我们将模型用在自己较小的数据集上进行训练时,如果一开始就设置比较大的学习率,可能会导致过拟合,或者模型直接训坏。

为此,我们需要一开始时用比较柔和的更新策略,即设置较小的学习率,慢慢地增大学习率;等到了一段时间后,在将学习率慢慢降低,先WarmUp,再Decay。

常见的DecayWithWarmup方式有线性(Linear)和余弦(Cosine)两种方式,该项目中我们使用线性衰减的方式,如下图所示:

注意:在warmup和decay过程中,我们都只对weights进行修改,而对bias和layer norm的参数都不做升温和退火处理。

最后,编写模型训练函数即可:

for epoch in range(num_train_epochs):for step, batch in enumerate(train_data_loader):input_ids, seq_lens, tok_to_orig_start_index, tok_to_orig_end_index, labels = batchlogits = model(input_ids=input_ids)mask = (input_ids != 0).logical_and((input_ids != 1)).logical_and((input_ids != 2))loss = criterion(logits, labels, mask)loss.backward()optimizer.step()lr_scheduler.step()optimizer.clear_gradients()loss_item = loss.numpy().item()if global_step % save_steps == 0 and global_step != 0:precision, recall, f1 = evaluate(model, criterion, test_data_loader, 				eval_file_path, "eval")paddle.save(model.state_dict(), os.path.join(output_dir, "model_%d.pdparams" % global_step))global_step += 1

(完整代码在这里)

以上便是信息抽取(Info Extraction)的全部内容。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ThinkPad X220i 刷白名单BIOS,改装第三方无线网卡

ThinkPad X220i自带的网卡是REALTEK RTL8188CE,这张卡在Mac下目前是无解的.国外网站有该卡liunx、unix内核的驱动,但还是没有高人编译出来. 不等了,这卡没戏.正好手边有一台Dell E6400,E6400的无线网卡是DELL Wireless 1397 WLAN Mini-Card,具体型号是&a…

C# 离线人脸识别 ArcSoft

人脸识别&比对发展到今天,已经是一个非常成熟的技术了,而且应用在生活的方方面面,比如手机、车站、天网等。虹软人脸识别服务是免费的。最重要的是它还支持离线识别,并且提供Android、iOS、C、C#版SDK,现在已经升级…

【mongoDB运维篇③】replication set复制集

介绍 replicattion set 多台服务器维护相同的数据副本,提高服务器的可用性,总结下来有以下好处: 数据备份与恢复读写分离MongoDB 复制集的结构以及基本概念 正如上图所示,MongoDB 复制集的架构中,主要分为两部分:主节点(Primary&a…

c++ long 转 short_C精品编程之——C语言的数据类型、运算符、表达式,精品课程...

在前边的文章分享中,我们已经看到程序中使用的各种变量都应预先加以说明,即先说明,后使用。对变量的说明可以包括三个方面:数据类型存储类型作用域在本课中,我们只介绍数据类型说明。其它说明在以后各章中陆续介绍。所…

李宏毅Reinforcement Learning强化学习入门笔记

文章目录Concepts in Reinforcement LearningDifficulties in RLA3C Method Brief IntroductionPolicy-based Approach - Learn an Actor (Policy Gradient Method)1. Decide Function of Actor Model (NN? ...)2. Decide Goodness of this Function3. Choose the best functi…

《BI项目笔记》数据源视图设置

原文:《BI项目笔记》数据源视图设置目的数据源视图是物理源数据库和分析维度与多维数据集之间的逻辑数据模型。在创建数据源视图时,需要在源数据库中指定包含创建维度和多维数据集所需要的数据表格和视图。BIDS与数据库连接,读取表格和视图定义&#xff…

201521123070 《JAVA程序设计》第13周学习总结

1. 本章学习总结 以你喜欢的方式(思维导图、OneNote或其他)归纳总结多网络相关内容。 2. 书面作业 Q1. 网络基础 1.1 比较ping www.baidu.com与ping cec.jmu.edu.cn,分析返回结果有何不同?为什么会有这样的不同? 1.2 t…

.NET 7 预览版2 的亮点之 NativeAOT 回顾

.NET 中备受追捧和期待已久的功能NativeAOT终于出现在本周的.NET 7 预览版2中,该项目的工作仍在继续,该版本将 NativeAOT 从实验性的 dotnet/runtimelab repo 中移出合并进入稳定的运行时库 dotnet/runtime repo,但尚未在 dotnet SDK 中添加足…

c语言十佳运动员有奖评选系统_2019年沃德十佳内饰解读

​2019年沃德十佳内饰解读​mp.weixin.qq.com在这个世界上,要判定一件事物的成功与否并不容易,仅靠主观判断远远不够,而是需要能够进行量化判断的标准和成果。正如运动员需要金牌和冠军积淀,导演和演员需要奖项傍身一样&#xff0…

Mybatis——返回类型为 集合嵌套集合 应该如何处理

2019独角兽企业重金招聘Python工程师标准>>> 最近在练习时 遇到了类似于 企鹅里的好友分组功能&#xff0c;使用的持久层框架是mybatis 第一次处理这种关系 记录一下 备忘。。 首先是表结构&#xff1a; <user_group > 好友分组 、 <t_group> 用户与好友…

为什么用 windbg 看 !address 显示出的Free是128T 大小?

总是被朋友问&#xff0c;用 !address -summary 显示出上面的 Free ≈ 128T 到底是什么意思&#xff1f;我的空闲内存不可能有这么大,不管怎么说&#xff0c;先上命令。0:009> !address -summary--- Usage Summary ---------------- RgnCount ----------- Total Size ------…

DeepMind 的马尔可夫决策过程(MDP)课堂笔记

DeepMind Teaching by David Silver 视频课程链接&#xff08;Youtube资源&#xff0c;需梯子&#xff09;&#xff1a;https://youtu.be/lfHX2hHRMVQ 文章目录DeepMind Teaching by David Silver1. 马尔可夫过程&#xff08;Markov Processes&#xff09;2. 马尔可夫回报过程…

深入Java集合学习系列:ConcurrentHashMap之实现细节

http://www.iteye.com/topic/344876 ConcurrentHashMap是Java 5中支持高并发、高吞吐量的线程安全HashMap实现。在这之前我对ConcurrentHashMap只有一些肤浅的理解&#xff0c;仅知道它采用了多个锁&#xff0c;大概也足够了。但是在经过一次惨痛的面试经历之后&#xff0c;我觉…

基于小波变换的信号降噪处理及仿真研究_信号处理方法推荐--1(转载自用,侵删)...

综述作者&#xff1a;aresmiki链接&#xff1a;https://www.zhihu.com/question/23701194/answer/167005497来源&#xff1a;知乎著作权归作者所有。商业转载请联系作者获得授权&#xff0c;非商业转载请注明出处。非平稳信号处理应该是现在信号处理技术最新的也是最热的研究方…

js温故而知新11(AJAX)——学习廖雪峰的js教程

Asynchronous JavaScript and XML&#xff0c;意思就是用JavaScript执行异步网络请求。 如果仔细观察一个Form的提交&#xff0c;你就会发现&#xff0c;一旦用户点击“Submit”按钮&#xff0c;表单开始提交&#xff0c;浏览器就会刷新页面&#xff0c;然后在新页面里告诉你操…

最流行的 .NET 开源项目合集

Github 上有很多优秀的 .NET 开源项目&#xff0c;它们很适合用来学习 .NET 、设计模式和架构。nopCommerce https://github.com/nopSolutions/nopCommercestar: 7k ⭐nopCommerce 是最受欢迎最好的开源电子商务购物车解决方案之一&#xff0c;它基于 ASP.NET Core&#xff…

GFS(Genetic Fuzzy Systems)—— 基于专家先验规则库和遗传算法相结合的智能体决策算法

文章目录1. FIS 系统&#xff08;Fuzzy Inference Systems&#xff09;1.1 什么是 FIS 系统&#xff1f;1.2 使用 FIS 算法的几个步骤2. GFS 系统&#xff08;GA FIS&#xff09;2.1 什么是基因遗传算法&#xff08;GA&#xff09;?2.2 使用GA算法进化FIS规则库在大规模的多智…

3-unit1 IPv6网络的管理

##########IPv6网络的管理#############学习目标了解IPv6管理IPv6##)IPv6简介Internet Protocol Version 6IPv6是IETF&#xff08;和互联网工程任务组&#xff09;设计的用与替代现行版本IP协议的下一代IP协议。IPv6采用128位2进制数码表示##IPv6示意图:##IPv6表示方式为方便操…

Xamarin效果第一篇之时间轴

一直都想找个时间玩玩移动端,中间也去各种的调研快速的方式去开发;过程中还是太浮躁木有沉下心去学习;好早尝试过Flutter,二点让我不爽:1、配置环境好费劲(VS把我惯坏了)&#xff1b;2、套娃的写法真是恶心;来看看酸爽不:因为一直都是C#开发,所以这次再次摸索Xamarin去开发;前面…

Lync 小技巧-42-动态-IP-统一沟通-环境-IP-变更后-操作

1. 查看-你的-公网IPhttp://www.ip138.com/2. 修改-你的-公网A记录https://www.godaddy.com/3. 修改-你的-拓朴-For-边缘服务器3.1.远程-前端服务器3.2.下载-拓朴3.3.选择-边缘服务器3.4.选择-边缘服务器3.5.修改-公网IP116.230.255.783.5.发布-拓朴3.6.导出-拓朴3.7.复制-拓朴…