使用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.rhkb.cn/news/337052.html

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

相关文章

SAPUI5基础知识3 - 引导过程(Bootstrap)

1. 背景 在上一篇博客中,我们已经建立出了第一个SAPUI5项目,接下来,我们将为这个项目添加引导过程。 在动手练习之前,让我们先解释一下什么引导过程。 1.1 什么是引导过程? 在计算机科学中,引导过程也称…

Presto 从提交SQL到获取结果 源码详解(3)

物理执行计划 回到SqlQueryExecution.startExecution() ,执行计划划分以后, // 初始化连接,获取Connect 元数据,添加会话,初始ConnectId metadata.beginQuery(getSession(), plan.getConnectors()); // 构建物理执行…

你真的会用收藏夹吗?可道云teamOS收藏夹,竟能缩短多层级文件夹的路径,实现快速访问

在日常工作中,我们时常会面临一个让人头疼的问题:如何在海量的文件和资料中快速找到我们需要的那一份? 尤其是在团队协作中,每个人都在不断地上传、更新文件……导致文件目录层级复杂,搜索也变得繁琐。 这时候&#x…

编程学习 (C规划) 6 {24_4_18} 七 ( 简单扫雷游戏)

首先我们要清楚扫雷大概是如何实现的: 1.布置雷 2.扫雷(排查雷) (1)如果这个位置是雷就炸了,游戏结束 (2)如果不是雷,就告诉周围有几个雷 3.把所有不是雷的位置都找…

一周学会Django5 Python Web开发 - Django5内置Admin系统二次开发

锋哥原创的Python Web开发 Django5视频教程: 2024版 Django5 Python web开发 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili2024版 Django5 Python web开发 视频教程(无废话版) 玩命更新中~共计56条视频,包括:2024版 Django5 Python we…

【C++】Vector的简易模拟与探索

💞💞 前言 hello hello~ ,这里是大耳朵土土垚~💖💖 ,欢迎大家点赞🥳🥳关注💥💥收藏🌹🌹🌹 💥个人主页&#x…

模型 FABE(特性 优势 好处 证据)法则

说明:系列文章 分享 模型,了解更多👉 模型_思维模型目录。特性、优势、好处、证据,一气呵成。 1 FABE法则的应用 1.1 FABE法则营销商用跑步机 一家高端健身器材公司的销售代表正在向一家新开的健身房推销他们的商用跑步机。以下…

Microsoft Dynamics 365 Business Central 讲解VAT RATE CHANGE TOOL(增值税税率更改工具)

学习目标: 如果使用VAT RATE CHANGE TOOL(增值税税率更改工具) 过程演示: 1.创建新的VAT产品过账组 2.创建新的总账科目以过账采购、销售和逆向征收增值税。 3.给新的VAT产品过账设置过账设置 4.创建一个新的一般产品过账组 5…

CUDA学习(2)

什么是CUDA CUDA(Compute Unified Device Architecture),统一计算设备架构,英伟达推出的基于其GPU的通用高性能计算平台和编程模型。 借助CUDA,开发者可以充分利用英伟达GPU的强大计算能力加速各种计算任务。 软件生…

手写HTML字符串解析成对应的 AST语法树

先看效果 展示如下: HTML模版 转成ast语法树后 在学习之前,我们需要了解这么一个问题,为什么要将HTML字符串解析成对应的 AST语法树。 为什么? 语法分析:HTML字符串是一种标记语言,其中包含了大量的标签…

chap5 CNN

卷积神经网络(CNN) 问题描述: 利用卷积神经网络,实现对MNIST数据集的分类问题 数据集: MNIST数据集包括60000张训练图片和10000张测试图片。图片样本的数量已经足够训练一个很复杂的模型(例如 CNN的深层…

gcc 内建函数示例 __builtin_return_address

1,理论未动&#xff0c;示例先行 hello_gcc_callstack.c #include <stdio.h>void do_backtrace() {void *pc0 __builtin_return_address(0);void *pc1 __builtin_return_address(1);void *pc2 __builtin_return_address(2);void *pc3 __builtin_return_address(3);…

低边驱动与高边驱动

一.高边驱动和低边驱动 低边驱动(LSD): 在电路的接地端加了一个可控开关&#xff0c;低边驱动就是通过闭合地线来控制这个开关的开关。容易实现&#xff08;电路也比较简单&#xff0c;一般由MOS管加几个电阻、电容&#xff09;、适用电路简化和成本控制的情况。 高边驱动&am…

JVM哪些区域可能出现内存溢出,哪些地方需要GC?

GC顾名思义也就是垃圾回收&#xff0c;有人的地方就有江湖&#xff0c;那有数据的地方也理应有垃圾回收&#xff0c;所以思考一下&#xff0c;沿着之前提到过的JVM内存分区&#xff0c;堆&#xff0c;栈&#xff0c;程序计数器&#xff0c;方法区 堆、栈、方法区…

一键安装 HaloDB 之 Ansible for Halo

↑ 关注“少安事务所”公众号&#xff0c;欢迎⭐收藏&#xff0c;不错过精彩内容~ 前倾回顾 前面介绍了“光环”数据库的基本情况和安装办法。 哈喽&#xff0c;国产数据库&#xff01;Halo DB! 三步走&#xff0c;Halo DB 安装指引 以及 HaloDB 的 Oracle 和 MySQL 兼容模式: …

ChatGPT-4o 有何特别之处?

文章目录 多模态输入&#xff0c;多模态输出之前的模型和现在模型对比 大家已经知道&#xff0c;OpenAI 在 GPT-4 发布一年多后终于推出了一个新模型。它仍然是 GPT-4 的一个变体&#xff0c;但具有前所未见的多模态功能。 有趣的是&#xff0c;它包括实时视频处理等强大功能&…

Mac安装第三方软件的命令安装方式

场景&#xff1a; 打开终端命令行&#xff0c;sudo xattr -rd com.apple.quarantine&#xff0c;注意最后quarantine 后面加一个空格&#xff01;然后打开Finder&#xff08;访达&#xff09;&#xff0c;点击左侧的 应用程序&#xff0c;找到相关应用&#xff0c;拖进终端qua…

六一见!|Post Microsoft Build and AI Day 上海开发者日

编辑/排版&#xff1a;Alan Wang 大小朋友明天见&#xff01; 6月1日&#xff0c;Microsoft Azure & Microsoft Reactor 面向大小朋友特别推出六一特辑&#xff0c;「Post Microsoft Build and AI Day 上海开发者日」 探讨 Microsoft Build 2024 带来的最新发布&#xff0…

KT6368A双模蓝牙芯片上电到正常发送AT指令或指令复位需要多久

一、简介 KT6368A芯片上电到正常发送AT指令&#xff0c;或者开启蓝牙广播被搜索到&#xff0c;或者指令复位需要多久等等系列问题总结 详细描述 其实这些问题归结到一起&#xff0c;就还是一个问题&#xff0c;芯片上电需要多久的时间 在另外一份文档里面&#xff0c;是有描…

热门新游 2024 植物大战僵尸杂交版 Mac 版本下载安装详细教程

最近植物大战僵尸杂交版可谓是非常的火&#xff0c;好多主播都在播这款游戏&#xff0c;我一个 Mac 党也想玩&#xff0c;可奈何该游戏目前只有 PC 版本&#xff0c;经过一番折腾终于在我的 Mac 上安装上了该游戏&#xff0c;分享给大家 其实安装过程也很简单&#xff0c;只需…