[oneAPI] 基于BERT预训练模型的英文文本蕴含任务

news/2024/5/20 22:48:17/文章来源:https://blog.csdn.net/qq_43779658/article/details/132437224

[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模型中,从而实现了高效的优化。
在这里插入图片描述

基于BERT预训练模型的英文文本蕴含任务

自然语言推理(简称NLI)是自然语言处理领域的一个重要任务,而多种文本蕴含(Textual Entailment)是其一个具体的子任务。MNLI(MultiNLI)是一个广泛使用的NLI数据集,旨在评估模型对于文本蕴含关系的理解能力。

在MNLI任务中,给定一个前提句子(premise)和一个假设句子(hypothesis),模型需要判断假设句子是否可以从前提句子中推断出来。这涉及到三种类别的关系:蕴含(entailment)、中性(neutral)和矛盾(contradiction)。例如,对于前提句子 “A cat is sitting on the couch.” 和假设句子 “A cat is on a piece of furniture.”,模型应该判断这两个句子之间的关系是蕴含。

MNLI的任务设计具有挑战性,要求模型不仅仅理解句子的字面含义,还需要进行逻辑推理和上下文理解。解决MNLI任务对于构建具有深层次语义理解能力的自然语言处理模型具有重要意义,可以应用于问答系统、文本理解和语义推理等领域。

基于BERT的文本蕴含(文本对分类)任务实质上是对一个文本序列进行分类。只是按照BERT模型的思想,文本对分类任务在数据集的构建过程中需要通过Segment Embedding来区分前后两个不同的序列。换句话说,与普通的单文本分类任务相比,文本对的分类任务在构建模型输入上发生了变换。

语料介绍

在这里,我们使用到的是论文中所提到的MNLI(The Multi-Genre Natural Language Inference Corpus, 多类型自然语言推理数据库)自然语言推断任务数据集。也就是给定前提(premise)语句和假设(hypothesis)语句,任务是预测前提语句是否包含假设(蕴含, entailment),与假设矛盾(矛盾,contradiction)或者两者都不(中立,neutral)。

{"annotator_labels": ["entailment", "neutral", "entailment", "neutral", "entailment"], "genre": "oup", "gold_label": "entailment", "pairID": "82890e", "promptID": "82890", "sentence1": " From Home Work to Modern Manufacture", "sentence1_binary_parse": "( From ( ( Home Work ) ( to ( Modern Manufacture ) ) ) )", "sentence1_parse": "(ROOT (PP (IN From) (NP (NP (NNP Home) (NNP Work)) (PP (TO to) (NP (NNP Modern) (NNP Manufacture))))))", "sentence2": "Modern manufacturing has changed over time.", "sentence2_binary_parse": "( ( Modern manufacturing ) ( ( has ( changed ( over time ) ) ) . ) )", "sentence2_parse": "(ROOT (S (NP (NNP Modern) (NN manufacturing)) (VP (VBZ has) (VP (VBN changed) (PP (IN over) (NP (NN time))))) (. .)))" }
{"annotator_labels": ["neutral", "neutral", "entailment", "neutral", "neutral"], "genre": "nineeleven", "gold_label": "neutral", "pairID": "16525n", "promptID": "16525", "sentence1": "They were promptly executed.", "sentence1_binary_parse": "( They ( ( were ( promptly executed ) ) . ) )", "sentence1_parse": "(ROOT (S (NP (PRP They)) (VP (VBD were) (VP (ADVP (RB promptly)) (VBN executed))) (. .)))", "sentence2": "They were executed immediately upon capture.", "sentence2_binary_parse": "( They ( ( were ( ( executed immediately ) ( upon capture ) ) ) . ) )", "sentence2_parse": "(ROOT (S (NP (PRP They)) (VP (VBD were) (VP (VBN executed) (ADVP (RB immediately)) (PP (IN upon) (NP (NN capture))))) (. .)))"}

由于该数据集同时也可用于其它任务中,因此除了我们需要的前提和假设两个句子和标签之外,还有每个句子的语法解析结构等等。在这里,下载完成数据后只需要执行项目中的format.py脚本即可将原始数据划分成训练集、验证集和测试集。格式化后的数据形式如下所示:

From Home Work to Modern Manufacture_!_Modern manufacturing has changed over time._!_1
They were promptly executed._!_They were executed immediately upon capture._!_2

数据集构建

定义一个类,并在类的初始化过程中根据训练语料完成字典的构建等工作

class LoadSingleSentenceClassificationDataset:def __init__(self,vocab_path='./vocab.txt',  #tokenizer=None,batch_size=32,max_sen_len=None,split_sep='\n',max_position_embeddings=512,pad_index=0,is_sample_shuffle=True):""":param vocab_path: 本地词表vocab.txt的路径:param tokenizer::param batch_size::param max_sen_len: 在对每个batch进行处理时的配置;当max_sen_len = None时,即以每个batch中最长样本长度为标准,对其它进行padding当max_sen_len = 'same'时,以整个数据集中最长样本为标准,对其它进行padding当max_sen_len = 50, 表示以某个固定长度符样本进行padding,多余的截掉;:param split_sep: 文本和标签之前的分隔符,默认为'\t':param max_position_embeddings: 指定最大样本长度,超过这个长度的部分将本截取掉:param is_sample_shuffle: 是否打乱训练集样本(只针对训练集)在后续构造DataLoader时,验证集和测试集均指定为了固定顺序(即不进行打乱),修改程序时请勿进行打乱因为当shuffle为True时,每次通过for循环遍历data_iter时样本的顺序都不一样,这会导致在模型预测时返回的标签顺序与原始的顺序不一样,不方便处理。"""self.tokenizer = tokenizerself.vocab = build_vocab(vocab_path)self.PAD_IDX = pad_indexself.SEP_IDX = self.vocab['[SEP]']self.CLS_IDX = self.vocab['[CLS]']# self.UNK_IDX = '[UNK]'self.batch_size = batch_sizeself.split_sep = split_sepself.max_position_embeddings = max_position_embeddingsif isinstance(max_sen_len, int) and max_sen_len > max_position_embeddings:max_sen_len = max_position_embeddingsself.max_sen_len = max_sen_lenself.is_sample_shuffle = is_sample_shuffle@cachedef data_process(self, filepath, postfix='cache'):"""将每一句话中的每一个词根据字典转换成索引的形式,同时返回所有样本中最长样本的长度:param filepath: 数据集路径:return:"""raw_iter = open(filepath, encoding="utf8").readlines()data = []max_len = 0for raw in tqdm(raw_iter, ncols=80):line = raw.rstrip("\n").split(self.split_sep)s, l = line[0], line[1]tmp = [self.CLS_IDX] + [self.vocab[token] for token in self.tokenizer(s)]if len(tmp) > self.max_position_embeddings - 1:tmp = tmp[:self.max_position_embeddings - 1]  # BERT预训练模型只取前512个字符tmp += [self.SEP_IDX]tensor_ = torch.tensor(tmp, dtype=torch.long)l = torch.tensor(int(l), dtype=torch.long)max_len = max(max_len, tensor_.size(0))data.append((tensor_, l))return data, max_lendef load_train_val_test_data(self, train_file_path=None,val_file_path=None,test_file_path=None,only_test=False):postfix = str(self.max_sen_len)test_data, _ = self.data_process(filepath=test_file_path, postfix=postfix)test_iter = DataLoader(test_data, batch_size=self.batch_size,shuffle=False, collate_fn=self.generate_batch)if only_test:return test_itertrain_data, max_sen_len = self.data_process(filepath=train_file_path,postfix=postfix)  # 得到处理好的所有样本if self.max_sen_len == 'same':self.max_sen_len = max_sen_lenval_data, _ = self.data_process(filepath=val_file_path,postfix=postfix)train_iter = DataLoader(train_data, batch_size=self.batch_size,  # 构造DataLoadershuffle=self.is_sample_shuffle, collate_fn=self.generate_batch)val_iter = DataLoader(val_data, batch_size=self.batch_size,shuffle=False, collate_fn=self.generate_batch)return train_iter, test_iter, val_iterdef generate_batch(self, data_batch):batch_sentence, batch_label = [], []for (sen, label) in data_batch:  # 开始对一个batch中的每一个样本进行处理。batch_sentence.append(sen)batch_label.append(label)batch_sentence = pad_sequence(batch_sentence,  # [batch_size,max_len]padding_value=self.PAD_IDX,batch_first=False,max_len=self.max_sen_len)batch_label = torch.tensor(batch_label, dtype=torch.long)return batch_sentence, batch_labelclass LoadPairSentenceClassificationDataset(LoadSingleSentenceClassificationDataset):def __init__(self, **kwargs):super(LoadPairSentenceClassificationDataset, self).__init__(**kwargs)pass@cachedef data_process(self, filepath, postfix='cache'):"""将每一句话中的每一个词根据字典转换成索引的形式,同时返回所有样本中最长样本的长度:param filepath: 数据集路径:return:"""raw_iter = open(filepath).readlines()data = []max_len = 0for raw in tqdm(raw_iter, ncols=80):line = raw.rstrip("\n").split(self.split_sep)s1, s2, l = line[0], line[1], line[2]token1 = [self.vocab[token] for token in self.tokenizer(s1)]token2 = [self.vocab[token] for token in self.tokenizer(s2)]tmp = [self.CLS_IDX] + token1 + [self.SEP_IDX] + token2if len(tmp) > self.max_position_embeddings - 1:tmp = tmp[:self.max_position_embeddings - 1]  # BERT预训练模型只取前512个字符tmp += [self.SEP_IDX]seg1 = [0] * (len(token1) + 2)  # 2 表示[CLS]和中间的[SEP]这两个字符seg2 = [1] * (len(tmp) - len(seg1))segs = torch.tensor(seg1 + seg2, dtype=torch.long)tensor_ = torch.tensor(tmp, dtype=torch.long)l = torch.tensor(int(l), dtype=torch.long)max_len = max(max_len, tensor_.size(0))data.append((tensor_, segs, l))return data, max_lendef generate_batch(self, data_batch):batch_sentence, batch_seg, batch_label = [], [], []for (sen, seg, label) in data_batch:  # 开始对一个batch中的每一个样本进行处理。batch_sentence.append(sen)batch_seg.append((seg))batch_label.append(label)batch_sentence = pad_sequence(batch_sentence,  # [batch_size,max_len]padding_value=self.PAD_IDX,batch_first=False,max_len=self.max_sen_len)  # [max_len,batch_size]batch_seg = pad_sequence(batch_seg,  # [batch_size,max_len]padding_value=self.PAD_IDX,batch_first=False,max_len=self.max_sen_len)  # [max_len, batch_size]batch_label = torch.tensor(batch_label, dtype=torch.long)return batch_sentence, batch_seg, batch_label

模型训练

TaskForPairSentenceClassification的模块来完成分类模型的微调训练任务。

首先,我们需要定义一个ModelConfig类来对分类模型中的超参数进行管理,代码如下所示:

class BertConfig(object):"""Configuration for `BertModel`."""def __init__(self,vocab_size=21128,hidden_size=768,num_hidden_layers=12,num_attention_heads=12,intermediate_size=3072,pad_token_id=0,hidden_act="gelu",hidden_dropout_prob=0.1,attention_probs_dropout_prob=0.1,max_position_embeddings=512,type_vocab_size=2,initializer_range=0.02):"""Constructs BertConfig.Args:vocab_size: Vocabulary size of `inputs_ids` in `BertModel`.hidden_size: Size of the encoder layers and the pooler layer.num_hidden_layers: Number of hidden layers in the Transformer encoder.num_attention_heads: Number of attention heads for each attention layer inthe Transformer encoder.intermediate_size: The size of the "intermediate" (i.e., feed-forward)layer in the Transformer encoder.hidden_act: The non-linear activation function (function or string) in theencoder and pooler.hidden_dropout_prob: The dropout probability for all fully connectedlayers in the embeddings, encoder, and pooler.attention_probs_dropout_prob: The dropout ratio for the attentionprobabilities.max_position_embeddings: The maximum sequence length that this model mightever be used with. Typically set this to something large just in case(e.g., 512 or 1024 or 2048).type_vocab_size: The vocabulary size of the `token_type_ids` passed into`BertModel`.initializer_range: The stdev of the truncated_normal_initializer forinitializing all weight matrices."""self.vocab_size = vocab_sizeself.hidden_size = hidden_sizeself.num_hidden_layers = num_hidden_layersself.num_attention_heads = num_attention_headsself.hidden_act = hidden_actself.intermediate_size = intermediate_sizeself.pad_token_id = pad_token_idself.hidden_dropout_prob = hidden_dropout_probself.attention_probs_dropout_prob = attention_probs_dropout_probself.max_position_embeddings = max_position_embeddingsself.type_vocab_size = type_vocab_sizeself.initializer_range = initializer_range@classmethoddef from_dict(cls, json_object):"""Constructs a `BertConfig` from a Python dictionary of parameters."""config = BertConfig(vocab_size=None)for (key, value) in six.iteritems(json_object):config.__dict__[key] = valuereturn config@classmethoddef from_json_file(cls, json_file):"""Constructs a `BertConfig` from a json file of parameters.""""""从json配置文件读取配置信息"""with open(json_file, 'r') as reader:text = reader.read()logging.info(f"成功导入BERT配置文件 {json_file}")return cls.from_dict(json.loads(text))def to_dict(self):"""Serializes this instance to a Python dictionary."""output = copy.deepcopy(self.__dict__)return outputdef to_json_string(self):"""Serializes this instance to a JSON string."""return json.dumps(self.to_dict(), indent=2, sort_keys=True) + "\n"

最后,我们只需要再定义一个train()函数来完成模型的训练即可,代码如下:

def train(config):model = BertForSentenceClassification(config,config.pretrained_model_dir)model_save_path = os.path.join(config.model_save_dir, 'model.pt')if os.path.exists(model_save_path):loaded_paras = torch.load(model_save_path)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()bert_tokenize = BertTokenizer.from_pretrained(model_config.pretrained_model_dir).tokenizedata_loader = LoadPairSentenceClassificationDataset(vocab_path=config.vocab_path,tokenizer=bert_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)train_iter, test_iter, val_iter = \data_loader.load_train_val_test_data(config.train_file_path,config.val_file_path,config.test_file_path)lr_scheduler = get_scheduler(name='linear',optimizer=optimizer,num_warmup_steps=int(len(train_iter) * 0),num_training_steps=int(config.epochs * len(train_iter)))max_acc = 0for epoch in range(config.epochs):losses = 0start_time = time.time()for idx, (sample, seg, label) in enumerate(train_iter):sample = sample.to(config.device)  # [src_len, batch_size]label = label.to(config.device)seg = seg.to(config.device)padding_mask = (sample == data_loader.PAD_IDX).transpose(0, 1)loss, logits = model(input_ids=sample,attention_mask=padding_mask,token_type_ids=seg,position_ids=None,labels=label)optimizer.zero_grad()loss.backward()lr_scheduler.step()optimizer.step()losses += loss.item()acc = (logits.argmax(1) == label).float().mean()if idx % 10 == 0:logging.info(f"Epoch: {epoch}, Batch[{idx}/{len(train_iter)}], "f"Train loss :{loss.item():.3f}, Train acc: {acc:.3f}")end_time = time.time()train_loss = losses / len(train_iter)logging.info(f"Epoch: {epoch}, Train loss: "f"{train_loss:.3f}, Epoch time = {(end_time - start_time):.3f}s")if (epoch + 1) % config.model_val_per_epoch == 0:acc = evaluate(val_iter, model, config.device, data_loader.PAD_IDX)logging.info(f"Accuracy on val {acc:.3f}")if acc > max_acc:max_acc = acctorch.save(model.state_dict(), model_save_path)

结果

在这里插入图片描述

参考资料

基于BERT预训练模型的英文文本蕴含任务: https://www.ylkz.life/deeplearning/p10407402/

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

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

相关文章

Kyligence Copilot 登陆海外,斩获 Product Hunt 日榜 TOP 2

8月14日,AI 数智助理 Kyligence Copilot 在全球知名科技产品平台 Product Hunt 上线,其以出色的产品创新实力,在激烈的竞争中脱颖而出,仅仅在 24 小时内收获了超过 400 个投票和近 200 条支持评论,荣登当日产品榜排名第…

Git如何操作本地分支仓库?

基本使用TortoiseGit 操作本地仓库(分支) 分支的概念 几乎所有的版本控制系统都以某种形式支持分支。 使用分支意味着你可以把你的工作从开发主线上分离开来,避免影响开发主线。多线程开发,可以同时开启多个任务的开发,多个任务之间互不影响。 为何要…

YOLOv8教程系列:三、K折交叉验证——让你的每一份标注数据都物尽其用(yolov8目标检测+k折交叉验证法)

YOLOv8教程系列:三、K折交叉验证——让你的每一份标注数据都物尽其用(yolov8目标检测k折交叉验证法) 0.引言 k折交叉验证(K-Fold Cross-Validation)是一种在机器学习中常用的模型评估技术,用于估计模型的性…

Maven聚合项目(微服务项目)创建流程,以及pom详解

1、首先创建springboot项目作为父项目 只留下pom.xml 文件&#xff0c;删除src目录及其他无用文件 2、创建子项目 子项目可以是maven项目&#xff0c;也可以是springboot项目 3、父子项目关联 4、父项目中依赖管理 <?xml version"1.0" encoding"UTF-8&qu…

idea连接linux远程docker详细教程操作

1&#xff1a;修改docker配置文件docker.service vi /usr/lib/systemd/system/docker.service2&#xff1a;找到 ExecStart&#xff0c;在最后面添加 -H tcp://0.0.0.0:2375 # for containers run by docker ExecStart/usr/bin/dockerd -H fd:// --containerd/run/containerd/…

Echarts面积图2.0(范围绘制)

代码&#xff1a; // 以下代码可以直接粘贴在echarts官网的示例上 // 范围值 let normalValue {type: 内部绘制,minValue: 200,maxValue: 750 } // 原本的绘图数据 let seriesData [820, 932, 901, 934, 1290, 1330, 1320] let minData Array.from({length: seriesData.len…

【面试经典150题】移除元素·JavaScript版

题目来源 大致思路&#xff1a;遍历数组&#xff0c;如果遇到值为val的元素&#xff0c;使用数组最后一个元素替换它。详细过程&#xff1a; /*** param {number[]} nums* param {number} val* return {number}*/ var removeElement function(nums, val) {let i0,nnums.leng…

Android NDK JNI与Java的相互调用

一、Jni调用Java代码 jni可以调用java中的方法和java中的成员变量,因此JNIEnv定义了一系列的方法来帮助我们调用java的方法和成员变量。 以上就是jni调用java类的大部分方法,如果是静态的成员变量和静态方法,可以使用***GetStaticMethodID、CallStaticObjectMethod等***。就…

基于nginx禁用访问ip

一、背景 网络安全防护时&#xff0c;禁用部分访问ip,基于nginx可快速简单实现禁用。 二、操作 1、创建 conf.d文件夹 在nginx conf 目录下创建conf.d文件夹 Nginx 扩展配置文件一般在conf.d mkdir conf.d 2、新建blocksip.conf文件 在conf.d目录新建禁用ip的扩展配置文…

C++Qt堆叠窗体的使用案例

本博文源于笔者最近学习的Qt&#xff0c;内容讲解堆叠窗体QStackedWidget案例&#xff0c;效果是选择左侧列表框中不同的选项时&#xff0c;右侧显示所选的不同的窗体。 案例效果 案例书写过程 控件都是动态创建的&#xff0c;因此.h文件需要创建控件&#xff0c;.cpp书写业务…

网络:RIP协议

1. RIP协议原理介绍 RIP是一种比较简单的内部网关协议&#xff08;IGP协议&#xff09;&#xff0c;RIP基于距离矢量的贝尔曼-福特算法(Bellman - Ford)来计算到达目的网络的最佳路径。最初的RIP协议开发时间较早&#xff0c;所以在带宽、配置和管理方面的要求也较低。 路由器运…

HarmonyOS开发第一步,熟知开发工具DevEco Studio

俗话说的好&#xff0c;工欲善其事&#xff0c;必先利其器&#xff0c;走进HarmonyOS第一步&#xff0c;开发工具必须先行&#xff0c;当然了&#xff0c;关于开发工具的使用&#xff0c;官网和其他的博客也有很多的讲解&#xff0c;但是并没有按照常用的功能进行概述&#xff…

基于SpringBoot房产销售系统【附ppt|开题|万字文档(LW)和搭建文档】

主要功能 前台界面&#xff1a; ①首页、房源信息推荐、房源信息展示、查看更多等 ②房源信息、房源名称、房源户型、销售姓名等 ③购房、预约、点我收藏、评论等 ④个人中心、我的收藏、支付等 后台登录&#xff1a; ①首页、个人中心&#xff1a;修改密码、用户信息管理等 ②…

图像检索,目标检测map的实现

一、图像检索指标Rank1,map 参考&#xff1a;https://blog.csdn.net/weixin_41427758/article/details/81188164?spm1001.2014.3001.5506 1.Rank1: rank-k&#xff1a;算法返回的排序列表中&#xff0c;前k位为存在检索目标则称为rank-k命中。 常用的为rank1&#xff1a;首…

启动Vue项目踩坑记录

前言 在启动自己的Vue项目时&#xff0c;遇到一些报错&#xff0c;当时很懵&#xff0c;解决了以后豁然开朗&#xff0c;特写此博客记录一下。 一、<template>里多加了个div标签 [vite] Internal server error: At least one <template> or <script> is req…

LLMs训练的算力优化Computational challenges of training LLMs

当您尝试训练大型语言模型时&#xff0c;您仍然经常遇到的最常见问题之一是内存不足。如果您曾尝试在Nvidia GPU上训练或甚至只是加载模型&#xff0c;那么这个错误消息可能看起来很熟悉。 CUDA&#xff0c;即Compute Unified Device Architecture的缩写&#xff0c;是为Nvid…

IDEA项目实践——VUE介绍与案例分析

系列文章目录 IDEA项目实践——JavaWeb简介以及Servlet编程实战 IDEA项目实践——Spring集成mybatis、spring当中的事务 IDEA项目实践——Spring当中的切面AOP IDEWA项目实践——mybatis的一些基本原理以及案例 IDEA项目实践——Spring框架简介&#xff0c;以及IOC注解 I…

C++day2作业(2023.8.22)

1.定义一个学生的结构体&#xff0c;包含学生的姓名&#xff0c;年龄&#xff0c;成绩&#xff0c;性别&#xff0c;学生的成绩&#xff0c;姓名&#xff0c;定义为私有权限&#xff1b;定义一个学生类型的结构体变量&#xff0c;设置公有函数用于给学生的成绩和名字进行赋值&a…

17.2 【Linux】通过 systemctl 管理服务

systemd这个启动服务的机制&#xff0c;是通过一支名为systemctl的指令来处理的。跟以前 systemV 需要 service / chkconfig / setup / init 等指令来协助不同&#xff0c; systemd 就是仅有systemctl 这个指令来处理而已。 17.2.1 通过 systemctl 管理单一服务 &#xff08;s…

基于MATLAB开发AUTOSAR软件应用层Code mapping专题-part 5 Signal/States标签页介绍

这一篇我们说下signals和State这两个怎么搞做映射,那首先我们要知道什么是Signal和state,我们看下模型, 在原来的模型里我增加了标红的圆圈处delay模块,这个delay模块就是一个state模块,表示离散的一个状态,这个是个模型的基本概念,后续我有个专栏交接simulink建模,那…