使用pytorch搭建textCNN、BERT、transformer进行文本分类

首先展示数据处理后的类型:
在这里插入图片描述
第一列为文本,第二类为标注的标签,数据保存在xlsx的表格中,分为训练集和验证集。

textCNN

直接上整个工程代码:

import pandas as pd
import numpy as np
import torch
from torch.utils.data import Dataset, DataLoader
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from transformers import BertTokenizer, BertModel
import random
from sklearn.metrics import classification_report# 设置随机种子以确保结果可复现
def set_seed(seed):random.seed(seed)np.random.seed(seed)torch.manual_seed(seed)if torch.cuda.is_available():torch.cuda.manual_seed(seed)torch.cuda.manual_seed_all(seed)set_seed(42)# 使用预训练的 BERT 模型和分词器
tokenizer = BertTokenizer.from_pretrained('bert-base-chinese')
bert_model = BertModel.from_pretrained('bert-base-chinese')# 定义一个函数来处理文本数据
def preprocess(text):encoding = tokenizer.encode_plus(text,add_special_tokens=True,max_length=150,padding='max_length',return_attention_mask=True,return_tensors='pt',truncation=True)return encoding['input_ids'].squeeze(), encoding['attention_mask'].squeeze()# 读取训练和验证数据
train_df = pd.read_excel('../train.xlsx')
val_df = pd.read_excel('../val.xlsx')# 处理训练数据
train_texts = train_df['comment'].apply(preprocess)
train_labels = torch.tensor(train_df['label'].values)
train_input_ids = torch.stack([x[0] for x in train_texts])
train_attention_masks = torch.stack([x[1] for x in train_texts])# 处理验证数据
val_texts = val_df['comment'].apply(preprocess)
val_labels = torch.tensor(val_df['label'].values)
val_input_ids = torch.stack([x[0] for x in val_texts])
val_attention_masks = torch.stack([x[1] for x in val_texts])# 创建数据集和数据加载器
class TextDataset(Dataset):def __init__(self, input_ids, attention_masks, labels):self.input_ids = input_idsself.attention_masks = attention_masksself.labels = labelsdef __len__(self):return len(self.labels)def __getitem__(self, idx):return {'input_ids': self.input_ids[idx],'attention_mask': self.attention_masks[idx],'labels': self.labels[idx]}train_dataset = TextDataset(train_input_ids, train_attention_masks, train_labels)
val_dataset = TextDataset(val_input_ids, val_attention_masks, val_labels)train_dataloader = DataLoader(train_dataset, batch_size=32, shuffle=True)
val_dataloader = DataLoader(val_dataset, batch_size=32, shuffle=False)# 检查是否有可用的 GPU
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f'Using device: {device}')# 定义模型
class TextCNN(nn.Module):def __init__(self, bert_model, num_classes):super(TextCNN, self).__init__()self.bert_model = bert_modelself.conv1 = nn.Conv2d(1, 100, (3, 768))self.conv2 = nn.Conv2d(1, 100, (4, 768))self.conv3 = nn.Conv2d(1, 100, (5, 768))self.dropout = nn.Dropout(0.5)self.fc = nn.Linear(300, num_classes)def forward(self, input_ids, attention_mask):with torch.no_grad():embedded = self.bert_model(input_ids, attention_mask).last_hidden_stateembedded = embedded.unsqueeze(1)conv1 = F.relu(self.conv1(embedded)).squeeze(3)conv2 = F.relu(self.conv2(embedded)).squeeze(3)conv3 = F.relu(self.conv3(embedded)).squeeze(3)pooled1 = F.max_pool1d(conv1, conv1.size(2)).squeeze(2)pooled2 = F.max_pool1d(conv2, conv2.size(2)).squeeze(2)pooled3 = F.max_pool1d(conv3, conv3.size(2)).squeeze(2)out = torch.cat((pooled1, pooled2, pooled3), 1)out = self.dropout(out)return self.fc(out)# 初始化模型、损失函数和优化器
model = TextCNN(bert_model, num_classes=2).to(device)
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)# 训练和验证模型,并保存最好的模型和最后一轮的模型
def train_and_evaluate(model, train_dataloader, val_dataloader, criterion, optimizer, device, epochs=10):best_val_accuracy = 0.0best_model_path = "best_model.pth"last_model_path = "last_model.pth"for epoch in range(epochs):model.train()train_loss = 0for batch in train_dataloader:input_ids = batch['input_ids'].to(device)attention_mask = batch['attention_mask'].to(device)labels = batch['labels'].to(device)optimizer.zero_grad()outputs = model(input_ids, attention_mask)loss = criterion(outputs, labels)loss.backward()optimizer.step()train_loss += loss.item()train_loss /= len(train_dataloader)print(f"Epoch {epoch + 1}, Training Loss: {train_loss}")model.eval()val_loss = 0correct = 0total = 0all_preds = []all_labels = []with torch.no_grad():for batch in val_dataloader:input_ids = batch['input_ids'].to(device)attention_mask = batch['attention_mask'].to(device)labels = batch['labels'].to(device)outputs = model(input_ids, attention_mask)loss = criterion(outputs, labels)val_loss += loss.item()_, predicted = torch.max(outputs.data, 1)total += labels.size(0)correct += (predicted == labels).sum().item()all_preds.extend(predicted.cpu().numpy())all_labels.extend(labels.cpu().numpy())val_loss /= len(val_dataloader)accuracy = 100 * correct / totalprint(f"Validation Loss: {val_loss}, Validation Accuracy: {accuracy}%")# 打印分类报告print("Classification Report:")print(classification_report(all_labels, all_preds, digits=3))# 保存验证集上表现最好的模型if accuracy > best_val_accuracy:best_val_accuracy = accuracytorch.save(model.state_dict(), best_model_path)print(f"Best model saved with accuracy: {best_val_accuracy}%")# 保存最后一轮的模型torch.save(model.state_dict(), last_model_path)print(f"Last model saved.")train_and_evaluate(model, train_dataloader, val_dataloader, criterion, optimizer, device)

可以根据自己爬取的文本的长度来自定义preprocess()函数里面的max_length值,若文本长度超过定义的最大值将进行截断,若不足则padding。最好包括大部分文本的长度,模型效果会比较好。

运行起来可能会报以下错误:

OSError: Can't load tokenizer for 'bert-base-chinese'. If you were trying to load it from 'https://huggingface.co/models', make sure you don't have a local directory with the same name. Otherwise, make sure 'bert-base-chinese' is the correct path to a directory containing all relevant files for a BertTokenizer tokenizer.

说明自动下载可能出现问题我们可以手动下载。
访问给出的网站https://huggingface.co/models,然后搜索bert-base-chinese,如图选择第一个。
在这里插入图片描述
点进去后下载config.json、pytorch_model.bin 和 vocab.txt三个文件,在工程的同一路径下创建“bert-base-chinese”的文件夹,将三个文件放入其中。
在这里插入图片描述
将使用预训练的 BERT 模型和分词器的两行代码该文调用本地:

tokenizer = BertTokenizer.from_pretrained('./bert-base-chinese')
bert_model = BertModel.from_pretrained('./bert-base-chinese')

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

BERT

跟textCNN一样用相同的BERT 模型和分词器:

import pandas as pd
import numpy as np
import torch
from torch.utils.data import Dataset, DataLoader
import torch.nn as nn
import torch.optim as optim
from transformers import BertTokenizer, BertModel, BertConfig
import random
from sklearn.metrics import classification_report# 设置随机种子以确保结果可复现
def set_seed(seed):random.seed(seed)np.random.seed(seed)torch.manual_seed(seed)if torch.cuda.is_available():torch.cuda.manual_seed(seed)torch.cuda.manual_seed_all(seed)set_seed(42)# 使用预训练的 BERT 模型和分词器
tokenizer = BertTokenizer.from_pretrained('./bert-base-chinese')
bert_model = BertModel.from_pretrained('./bert-base-chinese')# 定义一个函数来处理文本数据
def preprocess(text):encoding = tokenizer.encode_plus(text,add_special_tokens=True,max_length=150,padding='max_length',return_attention_mask=True,return_tensors='pt',truncation=True)return encoding['input_ids'].squeeze(), encoding['attention_mask'].squeeze()# 读取训练和验证数据
train_df = pd.read_excel('../train.xlsx')
val_df = pd.read_excel('../val.xlsx')# 处理训练数据
train_texts = train_df['comment'].apply(preprocess)
train_labels = torch.tensor(train_df['label'].values)
train_input_ids = torch.stack([x[0] for x in train_texts])
train_attention_masks = torch.stack([x[1] for x in train_texts])# 处理验证数据
val_texts = val_df['comment'].apply(preprocess)
val_labels = torch.tensor(val_df['label'].values)
val_input_ids = torch.stack([x[0] for x in val_texts])
val_attention_masks = torch.stack([x[1] for x in val_texts])# 创建数据集和数据加载器
class TextDataset(Dataset):def __init__(self, input_ids, attention_masks, labels):self.input_ids = input_idsself.attention_masks = attention_masksself.labels = labelsdef __len__(self):return len(self.labels)def __getitem__(self, idx):return {'input_ids': self.input_ids[idx],'attention_mask': self.attention_masks[idx],'labels': self.labels[idx]}train_dataset = TextDataset(train_input_ids, train_attention_masks, train_labels)
val_dataset = TextDataset(val_input_ids, val_attention_masks, val_labels)train_dataloader = DataLoader(train_dataset, batch_size=32, shuffle=True)
val_dataloader = DataLoader(val_dataset, batch_size=32, shuffle=False)# 检查是否有可用的 GPU
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f'Using device: {device}')# 定义模型
class BertForTextClassification(nn.Module):def __init__(self, bert_model, num_classes):super(BertForTextClassification, self).__init__()self.bert = bert_modelself.dropout = nn.Dropout(0.5)self.classifier = nn.Linear(bert_model.config.hidden_size, num_classes)def forward(self, input_ids, attention_mask):outputs = self.bert(input_ids=input_ids, attention_mask=attention_mask)pooled_output = outputs.pooler_outputpooled_output = self.dropout(pooled_output)logits = self.classifier(pooled_output)return logits# 初始化模型、损失函数和优化器
model = BertForTextClassification(bert_model, num_classes=2).to(device)
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.00001)# 训练和验证模型,并保存最好的模型和最后一轮的模型
def train_and_evaluate(model, train_dataloader, val_dataloader, criterion, optimizer, device, epochs=10):best_val_accuracy = 0.0best_model_path = "best_model.pth"last_model_path = "last_model.pth"for epoch in range(epochs):model.train()train_loss = 0for batch in train_dataloader:input_ids = batch['input_ids'].to(device)attention_mask = batch['attention_mask'].to(device)labels = batch['labels'].to(device)optimizer.zero_grad()outputs = model(input_ids, attention_mask)loss = criterion(outputs, labels)loss.backward()optimizer.step()train_loss += loss.item()train_loss /= len(train_dataloader)print(f"Epoch {epoch + 1}, Training Loss: {train_loss}")model.eval()val_loss = 0correct = 0total = 0all_preds = []all_labels = []with torch.no_grad():for batch in val_dataloader:input_ids = batch['input_ids'].to(device)attention_mask = batch['attention_mask'].to(device)labels = batch['labels'].to(device)outputs = model(input_ids, attention_mask)loss = criterion(outputs, labels)val_loss += loss.item()_, predicted = torch.max(outputs.data, 1)total += labels.size(0)correct += (predicted == labels).sum().item()all_preds.extend(predicted.cpu().numpy())all_labels.extend(labels.cpu().numpy())val_loss /= len(val_dataloader)accuracy = 100 * correct / totalprint(f"Validation Loss: {val_loss}, Validation Accuracy: {accuracy}%")# 打印分类报告print("Classification Report:")print(classification_report(all_labels, all_preds, digits=3))# 保存验证集上表现最好的模型if accuracy > best_val_accuracy:best_val_accuracy = accuracytorch.save(model.state_dict(), best_model_path)print(f"Best model saved with accuracy: {best_val_accuracy}%")# 保存最后一轮的模型torch.save(model.state_dict(), last_model_path)print(f"Last model saved.")train_and_evaluate(model, train_dataloader, val_dataloader, criterion, optimizer, device)

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

transformer

transformer使用的是自己的预训练模型和分词器,如果需要提前手动下载的话访问Hugging Face的官网还是下载config.json、pytorch_model.bin 和 vocab.txt三个文件,保存在hfl/chinese-roberta-wwm-ext目录中。

import pandas as pd
import numpy as np
import torch
from torch.utils.data import Dataset, DataLoader
import torch.nn as nn
import torch.optim as optim
from transformers import AutoTokenizer, AutoModel
import random
from sklearn.metrics import classification_report# 设置随机种子以确保结果可复现
def set_seed(seed):random.seed(seed)np.random.seed(seed)torch.manual_seed(seed)if torch.cuda.is_available():torch.cuda.manual_seed(seed)torch.cuda.manual_seed_all(seed)set_seed(42)# 使用预训练的 Transformer 模型和分词器
model_name = './hfl/chinese-roberta-wwm-ext'
tokenizer = AutoTokenizer.from_pretrained(model_name)
transformer_model = AutoModel.from_pretrained(model_name)# 定义一个函数来处理文本数据
def preprocess(text):encoding = tokenizer.encode_plus(text,add_special_tokens=True,max_length=150,padding='max_length',return_attention_mask=True,return_tensors='pt',truncation=True)return encoding['input_ids'].squeeze(), encoding['attention_mask'].squeeze()# 读取训练和验证数据
train_df = pd.read_excel('../train.xlsx')
val_df = pd.read_excel('../val.xlsx')# 处理训练数据
train_texts = train_df['comment'].apply(preprocess)
train_labels = torch.tensor(train_df['label'].values)
train_input_ids = torch.stack([x[0] for x in train_texts])
train_attention_masks = torch.stack([x[1] for x in train_texts])# 处理验证数据
val_texts = val_df['comment'].apply(preprocess)
val_labels = torch.tensor(val_df['label'].values)
val_input_ids = torch.stack([x[0] for x in val_texts])
val_attention_masks = torch.stack([x[1] for x in val_texts])# 创建数据集和数据加载器
class TextDataset(Dataset):def __init__(self, input_ids, attention_masks, labels):self.input_ids = input_idsself.attention_masks = attention_masksself.labels = labelsdef __len__(self):return len(self.labels)def __getitem__(self, idx):return {'input_ids': self.input_ids[idx],'attention_mask': self.attention_masks[idx],'labels': self.labels[idx]}train_dataset = TextDataset(train_input_ids, train_attention_masks, train_labels)
val_dataset = TextDataset(val_input_ids, val_attention_masks, val_labels)train_dataloader = DataLoader(train_dataset, batch_size=32, shuffle=True)
val_dataloader = DataLoader(val_dataset, batch_size=32, shuffle=False)# 检查是否有可用的 GPU
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f'Using device: {device}')# 定义模型
class TransformerForTextClassification(nn.Module):def __init__(self, transformer_model, num_classes):super(TransformerForTextClassification, self).__init__()self.transformer = transformer_modelself.dropout = nn.Dropout(0.5)self.classifier = nn.Linear(transformer_model.config.hidden_size, num_classes)def forward(self, input_ids, attention_mask):outputs = self.transformer(input_ids=input_ids, attention_mask=attention_mask)pooled_output = outputs.pooler_output if 'pooler_output' in outputs else outputs.last_hidden_state[:, 0]pooled_output = self.dropout(pooled_output)logits = self.classifier(pooled_output)return logits# 初始化模型、损失函数和优化器
model = TransformerForTextClassification(transformer_model, num_classes=2).to(device)
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.00001)# 训练和验证模型,并保存最好的模型和最后一轮的模型
def train_and_evaluate(model, train_dataloader, val_dataloader, criterion, optimizer, device, epochs=10):best_val_accuracy = 0.0best_model_path = "best_model.pth"last_model_path = "last_model.pth"for epoch in range(epochs):model.train()train_loss = 0for batch in train_dataloader:input_ids = batch['input_ids'].to(device)attention_mask = batch['attention_mask'].to(device)labels = batch['labels'].to(device)optimizer.zero_grad()outputs = model(input_ids, attention_mask)loss = criterion(outputs, labels)loss.backward()optimizer.step()train_loss += loss.item()train_loss /= len(train_dataloader)print(f"Epoch {epoch + 1}, Training Loss: {train_loss}")model.eval()val_loss = 0correct = 0total = 0all_preds = []all_labels = []with torch.no_grad():for batch in val_dataloader:input_ids = batch['input_ids'].to(device)attention_mask = batch['attention_mask'].to(device)labels = batch['labels'].to(device)outputs = model(input_ids, attention_mask)loss = criterion(outputs, labels)val_loss += loss.item()_, predicted = torch.max(outputs.data, 1)total += labels.size(0)correct += (predicted == labels).sum().item()all_preds.extend(predicted.cpu().numpy())all_labels.extend(labels.cpu().numpy())val_loss /= len(val_dataloader)accuracy = 100 * correct / totalprint(f"Validation Loss: {val_loss}, Validation Accuracy: {accuracy}%")# 打印分类报告print("Classification Report:")print(classification_report(all_labels, all_preds, digits=3))# 保存验证集上表现最好的模型if accuracy > best_val_accuracy:best_val_accuracy = accuracytorch.save(model.state_dict(), best_model_path)print(f"Best model saved with accuracy: {best_val_accuracy}%")# 保存最后一轮的模型torch.save(model.state_dict(), last_model_path)print(f"Last model saved.")train_and_evaluate(model, train_dataloader, val_dataloader, criterion, optimizer, device)

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

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

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

相关文章

c++函数基础总结

在给出的代码片段中,我们看到两部分内容:一个类定义和一个全局函数声明。让我们逐一分析它们: 类定义: cpp复制代码 class { public: void a(); }; 这个类定义是不完整的,因为它没有类名。但为了说明,我…

Linux开发工具(个人使用)

Linux开发工具 1.Linux yum软件包管理器1.1Linux安装程序有三种方式1.2注意事项1.3如何查看,安装,卸载软件包1.3.1查看软件包1.3.2安装软件包1.3.3卸载软件 2.Linux vim编辑器2.1vim的基本操作2.2vim正常模式命令集2.3vim底行模式命令集2.4vim配置 3.Lin…

如何设置eclipse中web.xml 文件的地址

新学了一个项目 ,项目结构与平常自己构建的web项目不同 ,用eclipse打开之后,eclipse竟然自己创建了一个web.xml 而项目里面原本的web.xml 文件eclipse没有识别出来,导致后来浏览器访问任何路径都报错404 一、修改项目中web.xml的…

Centos7.9环境下安装Keepalived(亲测版)

目录 一、在线安装 二、离线安装 (1)、 下载 (2)、安装依赖包 (3)、解压文件 (4)、编译 (4.1)、进入 keepalived-2.2.8 目录中 (4.2)、安装Keepalived (5)、配置文件修改 (6)、启动 (7)、检查启动状态 (8)、 设置开机自启 (9)、配置从节点 (10)、启动从节点keepalived…

vue3中实现鼠标点击后出现点击特效

一、效果展示 图片下方为效果体验地址 缓若江海凝清光 二、代码 js中&#xff1a; <script setup lang"ts"> window.addEventListener("click", (e: MouseEvent) > {const pointer document.createElement("div");pointer.classLi…

数模混合芯片之可靠性设计

一、可靠性设计目的 数模混合芯片设计之所以需要可靠性设计&#xff0c;主要原因有以下几点&#xff1a; 工艺与环境影响&#xff1a; 半导体制造工艺存在着不可避免的随机和系统性偏差&#xff0c;这可能导致芯片内部的模拟电路和数字电路参数发生变化&#xff0c;影响性能…

CobaltStrike基本渗透

目录 CobaltStrike简介 主要功能&#xff1a; 使用注意&#xff1a; 在使用CobaltStrike进行渗透测试时&#xff0c;务必遵守法律法规&#xff0c;并获得合法授权。 CobaltStrike安装 前提 安装 服务端安装 windows安装 CS基本使用 监听器配置 一些基本的攻击…

算法(十四)动态规划

算法概念 动态规划&#xff08;Dynamic Programming&#xff09;是一种分阶段求解的算法思想&#xff0c;通过拆分问题&#xff0c;定义问题状态和状态之间的关系&#xff0c;使得问题能够以递推&#xff08;分治&#xff09;的方式去解决。动态规划中有三个重点概念&#xff…

【监控】prometheus自定义指标 exporter

一、【写在前面】 prometheus自定义指标本质是用代码自己写一个网络访问的采集器&#xff0c;你可以在官网看到&#xff0c;Client libraries | Prometheus官方支持的语言有GO JAVA PYTHON RUBY RUST, 第三方的库就支持的更多了&#xff0c;有BASH C CPP LUA C# JS PHP R PER…

智慧医院物联网建设-统一管理物联网终端及应用

近年来&#xff0c;国家卫健委相继出台的政策和评估标准体系中&#xff0c;都涵盖了强化物联网建设的内容。物联网建设已成为智慧医院建设的核心议题之一。 作为医院高质量发展的关键驱动力&#xff0c;物联网的顶层设计与网络架构设计规划&#xff0c;既需要结合现代信息技术的…

Python3位运算符

前言 本文介绍的是位运算符&#xff0c;位运算可以理解成对二进制数字上的每一个位进行操作的运算&#xff0c;位运算分为 布尔位运算符 和 移位位运算符。 文章目录 前言一、位运算概览1、布尔位运算符1&#xff09;按位与运算符 ( & )2&#xff09;按位或运算符 ( | )3…

一款C#开源、简单、免费的屏幕录制和GIF动画制作神器

前言 今天要给大家推荐一款由C#语言开发且开源的操作简单、免费的屏幕录制和GIF动画制作神器&#xff1a;ScreenToGif 。 工具介绍 ScreenToGif 是一款免费的开源屏幕录制和GIF 制作工具。它可以帮助用户捕捉计算机屏幕上的实时动画&#xff0c;并将其保存为高质量的 GIF 图像…

开发者工具-sources(源代码选项)

一、概要说明 源代码面板从视觉效果上分为三个区域&#xff1a;菜单区、内容区、监听区。 菜单区里面有5个子分类&#xff1a; 网页(Page)&#xff1a;指页面源&#xff0c;包含了该页面中所有的文件&#xff0c;即使多个域名下的文件也都会展示出来&#xff0c;包括iframe…

手机耳机哪个品牌音质好

在寻找音质出色的手机耳机时&#xff0c;品牌选择显得尤为重要。市场上众多知名品牌提供了各式各样的耳机产品&#xff0c;它们在音质、降噪功能、设计等方面各有千秋。以下是一些在音质上表现优异的手机耳机品牌的分析&#xff1a; 索尼&#xff1a;索尼的耳机以其卓越的降噪技…

开利网络参加广州数据交易所学习活动

开利网络做为南沙广州数据交易所的会员参加了由“广东三会”组织的“数据资产”相关学习活动。&#xff08;下图为开利董事长付立军先生在签到&#xff09; 学习内容提现了数字时代企业数字化转型的核之心“发掘数据价值&#xff0c;驱动高速发展”&#xff0c;交易中心组织大家…

5G NR TAE TEST

环境配置&#xff1a; 测试TAE时&#xff0c;需要比对不同的Antenna Port之间的差异来测试 配置DL 2 layer MU的case layer1&#xff1a;通过设置weight&#xff0c;只有一个物理天线上有weight&#xff0c;其他天线上的weight为0&#xff0c;该天线的DMRS DMRS Port设置为1…

学习Java的日子 Day51 数据库,DDL

Day51 MySQL 1.数据库 数据库&#xff08;database&#xff09;就是一个存储数据的仓库。为了方便数据的存储和管理&#xff0c;它将数据按照特定的规律存储在磁盘上。通过数据库管理系统&#xff0c;可以有效地组织和管理存储在数据库中的数据 MySQL就是数据库管理系统&#…

PLC无线通讯模块

在工业自动化日益深入的今天&#xff0c;PLC&#xff08;可编程逻辑控制器&#xff09;作为工业控制的核心大脑&#xff0c;其功能的扩展和智能化水平直接影响着整个生产线的效率和安全性。而PLC无线通讯模块&#xff0c;作为连接PLC与外界信息世界的桥梁&#xff0c;其重要性不…

Centos给普通用户添加sudo命令权限

打开sudoers文件 sudo visudo 修改sudoers文件 找到root ALL(ALL) ALL这一行&#xff0c;即如下图标出红线的一行 在此行下新增如下内容: lbs为用给予sudo执行权限的用户名 # 执行sudo命令&#xff0c;需要输入命令 lbs ALL(ALL) ALL 或 # 执行sudo命令&#xff0c;…

HQChart使用教程100-uniapp如何在vue3运行微信小程序

HQChart使用教程100-uniapp如何在vue3运行微信小程序 症状原因分析解决思路解决步骤1. 修改vender.js2. 修改HQChartControl.js 完整实例HQChart代码地址 症状 HQChart插件在uniappvue3的项目编译成小程序以后&#xff0c; 运行会报错&#xff0c;见下图。 原因分析 查了下…