自然语言处理入门级项目——文本分类(预处理)

文章目录

  • 前言
  • 1.数据预处理
    • 1.1数据集介绍
    • 1.2数据集抽取
    • 1.3划分数据集
    • 1.4数据清洗
    • 1.5数据保存
  • 2.样本的向量化表征
    • 2.1词汇表
    • 2.2向量化
    • 2.3自定义数据集
    • 2.4备注
  • 结语

前言

本篇博客主要介绍自然语言处理领域中一个项目案例——文本分类,具体而言就是判断评价属于积极还是消极的模型,选用的模型属于最简单的单层感知机模型。

1.数据预处理

1.1数据集介绍

本项目数据集来源:2015年,Yelp 举办了一场竞赛,要求参与者根据点评预测一家餐厅的评级。该数据集分为 56 万个训练样本和3.8万个测试样本。共计两个类别,分别代表该评价属于积极还是消极。这里以训练集为例,进行介绍展示:

import pandas as pdtrain_reviews=pd.read_csv('data/yelp/raw_train.csv',header=None,names=['rating','review'])
train_reviews,train_reviews.rating.value_counts()

运行结果:
在这里插入图片描述
在这里插入图片描述
共计两个类别,同时类别数量相等,因此不需要进行类平衡操作。因为当前数据集过大,因此这里对数据集进行抽取。

1.2数据集抽取

首先,将两个类别的数据分别使用两个列表进行保存。代码如下:

import collectionsby_rating = collections.defaultdict(list)
for _, row in train_reviews.iterrows():by_rating[row.rating].append(row.to_dict())

运行查看:
在这里插入图片描述
共计两个类别,分别存储在by_rating[1]by_rating[2]对于的列表中。
接着选择合适的比例将数据从相应的类别中抽取出来,这里选择的比例为0.01,具体代码如下:

review_subset = []
for _, item_list in sorted(by_rating.items()):n_total = len(item_list)n_subset = int(0.01 * n_total)review_subset.extend(item_list[:n_subset])

为了可视化方便,这里将抽取后的子集转化为DataFrame数据格式,具体代码如下:

review_subset = pd.DataFrame(review_subset)
review_subset.head(),review_subset.shape

运行结果:
在这里插入图片描述
在这里插入图片描述
共计两个类别,每个类别均有2800条数据。

1.3划分数据集

首先,将两个类别的数据分别使用两个列表进行保存。代码如下:

by_rating = collections.defaultdict(list)
for _, row in review_subset.iterrows():by_rating[row.rating].append(row.to_dict())

因为该过程包括了打乱顺序,为了保证结果的可重复性,因此设置了随机种子。这里划分的训练集:验证集:测试集=0.70:0.15:0.15,同时为了区分数据,增加了一个属性split,该属性共有三种取值,分别代表训练集、验证集、测试集。

import numpy as npfinal_list = []
np.random.seed(1000)for _, item_list in sorted(by_rating.items()):np.random.shuffle(item_list)n_total = len(item_list)n_train = int(0.7 * n_total)n_val = int(0.15 * n_total)n_test = int(0.15 * n_total)for item in item_list[:n_train]:item['split'] = 'train'for item in item_list[n_train:n_train+n_val]:item['split'] = 'val'for item in item_list[n_train+n_val:n_train+n_val+n_test]:item['split'] = 'test'final_list.extend(item_list)

同理为了可视化方便,将其转化为DataFrame类型,代码如下:

final_reviews = pd.DataFrame(final_list)
final_reviews.head()

运行结果:
在这里插入图片描述
从上述结果可以看到,每条数据中还是有很多无意义的字符,如\,因此希望将其过滤掉,这就需要对数据进行清洗。

1.4数据清洗

这里为了将无意义的字符去除掉,自然就会想到正则表达式,用于匹配指定格式的字符串。具体操作代码如下:

import redef preprocess_text(text):text = text.lower()text = re.sub(r"([.,!?])", r" \1 ", text)text = re.sub(r"[^a-zA-Z.,!?]+", r" ", text)return textfinal_reviews.review = final_reviews.review.apply(preprocess_text)

这里对上述代码进行解释:

  • \1:指的是被匹配的字符,该段代码的功能是将匹配到的标点符号前后均加一个空格。
  • 第二个正则表达式:将除表示的字母及标点符号,其他符号均使用空格替代。

运行结果:
在这里插入图片描述
这里为了更好的展示数据,将rating属性做了更改,替换为negativepositive
代码如下:

final_reviews['rating'] = final_reviews.rating.apply({1: 'negative', 2: 'positive'}.get)
final_reviews.head()

运行结果:
在这里插入图片描述

1.5数据保存

至此数据预处理基本完成,这里将处理好的数据进行保存。

final_reviews.to_csv('data/yelp/reviews_with_splits_lite_new.csv', index=False)

在输入模型前,总不能是一个句子吧,因此需要将每个样本中的review表示为向量化。

2.样本的向量化表征

2.1词汇表

这里定义了一个 Vocabulary 类,用于处理文本并提取词汇表,以实现单词和索引之间的映射。具体代码如下:

class Vocabulary(object):"""处理文本并提取词汇表,以实现单词和索引之间的映射"""def __init__(self, token_to_idx=None, add_unk=True, unk_token="<UNK>"):"""参数:token_to_idx (dict): 一个已有的单词到索引的映射字典add_unk (bool): 指示是否添加未知词(UNK)标记unk_token (str): 要添加到词汇表中的未知词标记"""if token_to_idx is None:token_to_idx = {}self._token_to_idx = token_to_idxself._idx_to_token = {idx: token for token, idx in self._token_to_idx.items()}self._add_unk = add_unkself._unk_token = unk_tokenself.unk_index = -1if add_unk:self.unk_index = self.add_token(unk_token) def to_serializable(self):"""返回一个可序列化的字典"""return {'token_to_idx': self._token_to_idx, 'add_unk': self._add_unk, 'unk_token': self._unk_token}@classmethoddef from_serializable(cls, contents):"""从一个序列化的字典实例化 Vocabulary 类"""return cls(**contents)def add_token(self, token):"""根据传入的单词更新映射字典。参数:token (str): 要添加到词汇表中的单词返回:index (int): 该单词对应的整数索引"""if token in self._token_to_idx:index = self._token_to_idx[token]else:index = len(self._token_to_idx)self._token_to_idx[token] = indexself._idx_to_token[index] = tokenreturn indexdef add_many(self, tokens):"""向词汇表中添加一组单词参数:tokens (list): 一个字符串单词列表返回:indices (list): 一个与这些单词对应的索引列表"""return [self.add_token(token) for token in tokens]def lookup_token(self, token):"""查找与单词关联的索引,若单词不存在则返回未知词索引。参数:token (str): 要查找的单词返回:index (int): 该单词对应的索引注意:`unk_index` 需要 >=0(即已添加到词汇表中)才能启用未知词功能"""if self.unk_index >= 0:return self._token_to_idx.get(token, self.unk_index)else:return self._token_to_idx[token]def lookup_index(self, index):"""返回与索引关联的单词参数: index (int): 要查找的索引返回:token (str): 该索引对应的单词异常:KeyError: 若索引不在词汇表中"""if index not in self._idx_to_token:raise KeyError("索引 (%d) 不在词汇表中" % index)return self._idx_to_token[index]def __str__(self):"""返回表示词汇表大小的字符串"""return "<Vocabulary(size=%d)>" % len(self)def __len__(self):"""返回词汇表中单词的数量"""return len(self._token_to_idx)

这里对该类中方法体做以下解释:

  • __init__构造方法:若token_to_idx为 None,则初始化为空字典。_idx_to_token 是索引到单词的映射字典,通过_token_to_idx反转得到。若 add_unk 为 True,则调用 add_token 方法添加未知词标记,并记录其索引。
  • to_serializable 方法:返回一个字典,包含 _token_to_idx_add_unk _unk_token,可用于序列化存储。
  • from_serializable: 是类方法,接收一个序列化的字典,通过解包字典参数创建 Vocabulary 类的实例。
  • add_token 方法:用于向词汇表中添加单个单词。若单词已存在,返回其索引;否则,分配一个新索引并更新两个映射字典。
  • add_many 方法:用于批量添加单词列表,返回每个单词对应的索引列表。
  • lookup_token 方法:根据单词查找对应的索引。若单词不存在且unk_index 大于等于 0,则返回 unk_index;否则,返回单词的索引。
  • lookup_index 方法:根据索引查找对应的单词。若索引不存在,抛出 KeyError 异常。
  • __str__ 方法返回一个字符串,显示词汇表的大小。
  • __len__ 方法:返回词汇表中单词的数量。

2.2向量化

此处定义了 ReviewVectorizer 类,其作用是协调词汇表(Vocabulary)并将其投入使用,主要负责把文本评论转换为可用于模型训练的向量表示。具体代码如下:

class ReviewVectorizer(object):""" 协调词汇表并将其投入使用的向量化器 """def __init__(self, review_vocab, rating_vocab):"""参数:review_vocab (Vocabulary): 将单词映射为整数的词汇表rating_vocab (Vocabulary): 将类别标签映射为整数的词汇表"""self.review_vocab = review_vocabself.rating_vocab = rating_vocabdef vectorize(self, review):"""为评论创建一个压缩的独热编码向量参数:review (str): 评论文本返回:one_hot (np.ndarray): 压缩后的独热编码向量"""# 初始化一个长度为词汇表大小的全零向量one_hot = np.zeros(len(self.review_vocab), dtype=np.float32)# 遍历评论中的每个单词for token in review.split(" "):# 若单词不是标点符号if token not in string.punctuation:# 将向量中对应单词索引的位置置为 1one_hot[self.review_vocab.lookup_token(token)] = 1return one_hot@classmethoddef from_dataframe(cls, review_df, cutoff=25):"""从数据集的 DataFrame 实例化向量化器参数:review_df (pandas.DataFrame): 评论数据集cutoff (int): 基于词频过滤的阈值参数返回:ReviewVectorizer 类的一个实例"""# 创建评论词汇表,添加未知词标记review_vocab = Vocabulary(add_unk=True)# 创建评分词汇表,不添加未知词标记rating_vocab = Vocabulary(add_unk=False)# 添加评分标签到评分词汇表for rating in sorted(set(review_df.rating)):rating_vocab.add_token(rating)# 统计词频,若词频超过阈值则添加到评论词汇表word_counts = Counter()for review in review_df.review:for word in review.split(" "):if word not in string.punctuation:word_counts[word] += 1for word, count in word_counts.items():if count > cutoff:review_vocab.add_token(word)return cls(review_vocab, rating_vocab)@classmethoddef from_serializable(cls, contents):"""从可序列化的字典实例化 ReviewVectorizer参数:contents (dict): 可序列化的字典返回:ReviewVectorizer 类的一个实例"""# 从可序列化字典中恢复评论词汇表review_vocab = Vocabulary.from_serializable(contents['review_vocab'])# 从可序列化字典中恢复评分词汇表rating_vocab =  Vocabulary.from_serializable(contents['rating_vocab'])return cls(review_vocab=review_vocab, rating_vocab=rating_vocab)def to_serializable(self):"""创建用于缓存的可序列化字典返回:contents (dict): 可序列化的字典"""return {'review_vocab': self.review_vocab.to_serializable(),'rating_vocab': self.rating_vocab.to_serializable()}

这里对该类中方法体做以下解释:

  • __init__方法:类的构造方法,接收两个 Vocabulary 类的实例:
    review_vocab:将评论中的单词映射为整数。
    rating_vocab:将评论的评分标签映射为整数。
  • vectorize 方法:将输入的评论文本转换为压缩的独热编码向量。具体操作为:
    首先创建一个长度为词汇表大小的全零向量 one_hot。
    遍历评论中的每个单词,若该单词不是标点符号,则将向量中对应单词索引的位置置为 1。
    最后返回处理好的独热编码向量。
  • from_dataframe类方法:用于从包含评论数据的 DataFrame 中实例化 ReviewVectorizer。具体操作为:
    创建两个 Vocabulary 实例,review_vocab 添加未知词标记,rating_vocab 不添加。
    遍历数据框中的评分列,将所有唯一评分添加到 rating_vocab 中。
    统计评论中每个非标点单词的出现频率,将出现次数超过 cutoff 的单词添加到 review_vocab 中。
    最后返回 ReviewVectorizer 类的实例。
  • from_serializable 方法:从一个可序列化的字典中实例化 ReviewVectorizer
    从字典中提取review_vocabrating_vocab 对应的序列化数据,分别创建 Vocabulary 实例。
    最后返回 ReviewVectorizer 类的实例。
  • to_serializable 方法:创建一个可序列化的字典,用于缓存 ReviewVectorizer 的状态。调用 review_vocab 和 rating_vocab 的 to_serializable 方法,将结果存储在字典中并返回。

2.3自定义数据集

该数据集继承Dataset,具体代码如下:

class ReviewDataset(Dataset):def __init__(self, review_df, vectorizer):"""参数:review_df (pandas.DataFrame): 数据集vectorizer (ReviewVectorizer): 从数据集中实例化的向量化器"""self.review_df = review_dfself._vectorizer = vectorizer# 从数据集中筛选出训练集数据self.train_df = self.review_df[self.review_df.split=='train']# 训练集数据的数量self.train_size = len(self.train_df)# 从数据集中筛选出验证集数据self.val_df = self.review_df[self.review_df.split=='val']# 验证集数据的数量self.validation_size = len(self.val_df)# 从数据集中筛选出测试集数据self.test_df = self.review_df[self.review_df.split=='test']# 测试集数据的数量self.test_size = len(self.test_df)# 用于根据数据集划分名称查找对应数据和数据数量的字典self._lookup_dict = {'train': (self.train_df, self.train_size),'val': (self.val_df, self.validation_size),'test': (self.test_df, self.test_size)}# 默认设置当前使用的数据集为训练集self.set_split('train')@classmethoddef load_dataset_and_make_vectorizer(cls, review_csv):"""从文件加载数据集并从头创建一个新的向量化器参数:review_csv (str): 数据集文件的路径返回:ReviewDataset 类的一个实例"""review_df = pd.read_csv(review_csv)# 从数据集中筛选出训练集数据train_review_df = review_df[review_df.split=='train']return cls(review_df, ReviewVectorizer.from_dataframe(train_review_df))@classmethoddef load_dataset_and_load_vectorizer(cls, review_csv, vectorizer_filepath):"""加载数据集和对应的向量化器。用于向量化器已被缓存以便重复使用的情况参数:review_csv (str): 数据集文件的路径vectorizer_filepath (str): 保存的向量化器文件的路径返回:ReviewDataset 类的一个实例"""review_df = pd.read_csv(review_csv)vectorizer = cls.load_vectorizer_only(vectorizer_filepath)return cls(review_df, vectorizer)@staticmethoddef load_vectorizer_only(vectorizer_filepath):"""一个静态方法,用于从文件加载向量化器参数:vectorizer_filepath (str): 序列化的向量化器文件的路径返回:ReviewVectorizer 类的一个实例"""with open(vectorizer_filepath) as fp:return ReviewVectorizer.from_serializable(json.load(fp))def save_vectorizer(self, vectorizer_filepath):"""使用 JSON 将向量化器保存到磁盘参数:vectorizer_filepath (str): 保存向量化器的文件路径"""with open(vectorizer_filepath, "w") as fp:json.dump(self._vectorizer.to_serializable(), fp)def get_vectorizer(self):"""返回向量化器"""return self._vectorizerdef set_split(self, split="train"):"""根据数据框中的一列选择数据集中的划分参数:split (str): "train", "val", 或 "test" 之一"""self._target_split = splitself._target_df, self._target_size = self._lookup_dict[split]def __len__(self):"""返回当前所选数据集划分的数据数量"""return self._target_sizedef __getitem__(self, index):"""PyTorch 数据集的主要入口方法参数:index (int): 数据点的索引返回:一个字典,包含数据点的特征 (x_data) 和标签 (y_target)"""row = self._target_df.iloc[index]# 将评论文本转换为向量review_vector = \self._vectorizer.vectorize(row.review)# 获取评分对应的索引rating_index = \self._vectorizer.rating_vocab.lookup_token(row.rating)return {'x_data': review_vector,'y_target': rating_index}def get_num_batches(self, batch_size):"""根据给定的批次大小,返回数据集中的批次数量参数:batch_size (int): 批次大小返回:数据集中的批次数量"""return len(self) // batch_sizedef generate_batches(dataset, batch_size, shuffle=True,drop_last=True, device="cpu"):"""一个生成器函数,封装了 PyTorch 的 DataLoader。它将确保每个张量都位于正确的设备上。"""dataloader = DataLoader(dataset=dataset, batch_size=batch_size,shuffle=shuffle, drop_last=drop_last)for data_dict in dataloader:out_data_dict = {}for name, tensor in data_dict.items():out_data_dict[name] = data_dict[name].to(device)yield out_data_dict

这里不对代码进行解释了,关键部分已添加注释。

2.4备注

上述代码可能过长,导致难以理解,其实就是一个向量化表征的思想。上述采用的思想就是基于词频统计的,将整个训练集上的每条评论数据使用split(" ")分开形成若干个token,统计这些token出现的次数,将频次大于cutoff=25的token加入到词汇表中,并分配一个编码,其实就是索引。样本中的每条评论数据应该怎么表征呢,其实就是一个基于上述创建的词汇表的独热编码,因此是一个向量。

至此样本的向量化表征到此结束。接着就到定义模型,进行训练了。

结语

为了避免博客内容过长,这里就先到此结束,后续将接着上述内容进行阐述!后续直达链接,同时本项目也是博主接触的第一个NLP领域的项目,如有不足,请批评指正!!!
备注:本案例代码参考本校《自然语言处理》课程实验中老师提供的参考代码

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

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

相关文章

C++面试2——C与C++的关系

C与C++的关系及核心区别的解析 一、哲学与编程范式:代码组织的革命 过程式 vs 多范式混合 C语言是过程式编程的典范,以算法流程为中心,强调“怎么做”(How)。例如,实现链表操作需手动管理节点指针和内存。 C++则是多范式语言,支持面向对象(OOP)、泛型编程(模板)、函…

HTTP与HTTPS协议的核心区别

HTTP与HTTPS协议的核心区别 数据传输安全性 HTTP采用明文传输&#xff0c;数据易被窃听或篡改&#xff08;如登录密码、支付信息&#xff09;&#xff0c;而HTTPS通过SSL/TLS协议对传输内容加密&#xff0c;确保数据完整性并防止中间人攻击。例如&#xff0c;HTTPS会生成对称加…

PotPlayer 安装 madVR、LAV Filters 以提升解码能力和视频音频效果

PotPlayer自带的解码器并不是最好&#xff0c;如下两张截图都是出自 TOP GUN: Maverick 较暗、灰蒙蒙的一张&#xff0c;是安装插件之前明亮的一张&#xff0c;是安装插件之后 详细安装参考 https://www.bilibili.com/video/BV1UV5qzuE74?spm_id_from333.788.videopod.sectio…

深入理解 OpenCV 的 DNN 模块:从基础到实践

在计算机视觉领域蓬勃发展的当下&#xff0c;深度学习模型的广泛应用推动着技术的不断革新。OpenCV 作为一款强大且开源的计算机视觉库&#xff0c;其 DNN&#xff08;Deep Neural Network&#xff09;模块为深度学习模型的落地应用提供了高效便捷的解决方案。本文将以理论为核…

Spring MVC 中请求处理流程及核心组件解析

在 Spring MVC 中&#xff0c;请求从客户端发送到服务器后&#xff0c;需要经过一系列组件的处理才能最终到达具体的 Controller 方法。这个过程涉及多个核心组件和复杂的映射机制&#xff0c;下面详细解析其工作流程&#xff1a; 1. 核心组件与请求流程 Spring MVC 的请求处…

RISC-V 开发板 MUSE Pi Pro V2D图像加速器测试,踩坑介绍

视频讲解&#xff1a; RISC-V 开发板 MUSE Pi Pro V2D图像加速器测试&#xff0c;踩坑介绍 今天测试下V2D&#xff0c;这是K1特有的硬件级别的2D图像加速器&#xff0c;参考如下文档&#xff0c;但文档中描述的部分有不少问题&#xff0c;后面会讲下 https://bianbu-linux.spa…

hbase shell的常用命令

一、hbase shell的基础命令 # 版本号查看 [rootTest-Hadoop-NN-01 hbase]$ ./bin/hbase version HBase 2.4.0 Source code repository git://apurtell-ltm.internal.salesforce.com/Users/apurtell/src/hbase revision282ab70012ae843af54a6779543ff20acbcbb629# 客户端登录 […

深入解析Python中的Vector2d类:从基础实现到特殊方法的应用

引言 在Python面向对象编程中&#xff0c;特殊方法&#xff08;或称魔术方法&#xff09;是实现对象丰富行为的关键。本文将以Vector2d类为例&#xff0c;详细讲解如何通过特殊方法为自定义类添加多种表示形式和操作能力。 Vector2d类的基本行为 Vector2d类是一个二维向量类…

Zookeeper入门(三)

Zookeeper Java 客户端 项目构建 ookeeper 官方的客户端没有和服务端代码分离&#xff0c;他们为同一个jar 文件&#xff0c;所以我们直接引入 zookeeper的maven即可&#xff0c; 这里版本请保持与服务端版本一致&#xff0c;不然会有很多兼容性的问题 1 <dependency>…

Redis的主从架构

主从模式 全量同步 首先主从同步过程第一步 会先比较replication id 判断是否是第一次同步假设为第一次同步 那么就会 启动bgsave异步生成RDB 同时fork子进程记录生成期间的新数据发送RDB给从节点 清空本地数据写入RDB 增量同步 对比ReplicationID不同因此选择增量同步在Rep…

新电脑软件配置二:安装python,git, pycharm

安装python 地址 https://www.python.org/downloads/ 不是很懂为什么这么多版本 安装windows64位的 这里我是凭自己感觉装的了 然后cmd输入命令没有生效&#xff0c;先重启下&#xff1f; 重启之后再次验证 环境是成功的 之前是输入的python -version 命令输入错误 安装pyc…

docker 学习记录

docker pull nginx docker 将本地nginx快照保存到当前文件夹下 docker save -o nginx.tar nginx:latestdocker 将本地nginx 加载 docker load -i nginx.tar docker运行nginx在80端口 docker run --name dnginx -p 80:80 -d nginxredis启动 docker run --name mr -p 6379:6379 -…

什么是私有IP地址?如何判断是不是私有ip地址

在互联网的世界中&#xff0c;IP地址是设备之间通信的基础标识。无论是浏览网页、发送邮件还是在线游戏&#xff0c;IP地址都扮演着至关重要的角色。然而&#xff0c;并非所有的IP地址都是公开的&#xff0c;有些IP地址被保留用于内部网络&#xff0c;这就是我们所说的私有IP地…

功能安全管理

一、功能安全整体管理 1、功能安全文化&#xff0c;良好的功能安全文化包括&#xff1a; 1&#xff09; 在公司层面&#xff0c;有清晰的组织架构支撑功能安全开展 2&#xff09; 确保有足够的资源投入到功能安全开发中 3&#xff09; 有完整的功能安全培训 4&#xff09; 流程…

异常日志规范

目录 一、错误码 二、异常处理 三、日志规约 一、错误码 强制&#xff1a; 1、错误码的制订原则&#xff1a;快速溯源、沟通标准化。 1&#xff09;错误码必须能够快速知晓错误来源&#xff0c;可快速判断是谁的问题。 2&#xff09;错误码必须能够清晰地比对&#xff08;…

SOLID 面对象设计的五大基本原则

SOLID 原则的价值 原则核心价值解决的问题SRP职责分离&#xff0c;提高内聚性代码臃肿、牵一发而动全身OCP通过扩展而非修改实现变化频繁修改现有代码导致的风险LSP确保子类行为的一致性继承滥用导致的系统不稳定ISP定制化接口&#xff0c;避免依赖冗余接口过大导致的实现负担…

Python 装饰器详解

装饰器是 Python 中一种强大的语法特性&#xff0c;它允许在不修改原函数代码的情况下动态地扩展函数的功能。装饰器本质上是一个高阶函数&#xff0c;它接受一个函数作为参数并返回一个新的函数。 基本装饰器 1. 简单装饰器示例 def my_decorator(func):def wrapper():prin…

无损耗协议:PROFINET和EtherNet IP网关的高效安装指南

作为风力发电机组监控系统的重要组成部分&#xff0c;PROFINET和EtherNet/IP协议转换网关倍讯BX-606-EIP的安装至关重要。作为安装工,我们要确保网关安装的高效顺利,保证风力发电机组的稳定运行。 首先,我们需要仔细检查网关的硬件接口,确保所有连接线缆与设备端口相匹配。网关…

Axure元件动作四:设置选中

亲爱的小伙伴,在您浏览之前,烦请关注一下,在此深表感谢!如有帮助请订阅专栏! Axure产品经理精品视频课已登录CSDN可点击学习https://edu.csdn.net/course/detail/40420 课程主题:设置选中 主要内容:选中效果全面解析 应用场景:元件、元件组合需要被选中场景 案例展…

大模型为什么学新忘旧(大模型为什么会有灾难性遗忘)?

字数&#xff1a;2500字 一、前言&#xff1a;当学霸变成“金鱼” 假设你班上有个学霸&#xff0c;数学考满分&#xff0c;英语拿第一&#xff0c;物理称霸全校。某天&#xff0c;他突然宣布&#xff1a;“我要全面发展&#xff01;从今天起学打篮球&#xff01;” 一周后&am…