使用bert模型进行命名实体识别任务

一、实验内容

         本实验使用预训练的 BERT 模型进行命名实体识别(NER)任务,并且使用 Hugging Face 的 Transformers 库完成模型的训练、验证和测试。最后,使用测试集评估模型性能,计算NER指标。

二、算法介绍 

         Bert是一种由Google于2018年提出的自然语言处理(NLP)模型。它基于Transformer架构。首先简单介绍transformer模型。2017年,Google翻译团队提出的论文《Attention is All You Need》。在论文中,作者提出了在序列转录领域,只依赖注意力结构的简单的网络架构——Transformer。Transformer是一种基于注意力的编码器-解码器模型。它由若干层编码器和解码器组成,每一层都包含了自注意力机制和前馈神经网络。

        在Transformer提出之前,RNN和CNN一直是人们处理序列问题的前沿方法,但是二者都存在局限性,Transformer的优势也正是对二者的补充。Transformer的提出有效解决了传统的模型在处理可变长序列时遇到的问题。其具有以下优点:

1、长程依赖处理

在CNN模型中,随着序列两个位置之间距离的增大,计算它们之间的依赖难度也随之增加。Transformer所引入的自注意力机制则允许其忽略序列距离的影响,使计算更简单。

2、支持并行计算

以往的RNN模型在t时刻的计算依赖于前t-1时刻的输出,无法并行计算。然而,Transformer仅基于自注意力机制,而完全摒弃了RNN,无需遵循该时序结构,令并行计算成为可能

Transformer结构:

54d2729fbc0b4b6b8e1040d3ee996e11.png

        左侧为编码器,右侧为解码器。编码器包含一个 多头注意力Multi-Head Attention机制,解码器是在编码器 基础上增加了一个有Masked的 Multi-Head Attention。Multi-Head Attention 上方还包括一个 Add & Norm 层,Add 表示残差连接用于防止网络退化,Norm表示层归一化处理,用于对每一层的激活值进行归一化。 

        并且Transformer通过引入位置编码来为attention加入时序信息。

3a2751752c094fc0ad6b30420a0a5345.png

        BERT 的主要创新在于通过预训练大规模语言模型来学习上下文相关的词嵌入。主要由三大部分构成:嵌入层、编码层和输出层。编码层是基于transformer编码层。

7822379a358c4b4bb22c0fe449bc5ffb.png

 

1.嵌入层:

输入向量是由三个向量相加得到,分别是标记嵌入、段嵌入和位置嵌入。

Token Embeddings(标记嵌入): 标识每个token的基本语义

Segment Embeddings(段嵌入):区分不同句子/段的嵌入,表明这个词属于哪个句子

Position Embeddings(位置嵌入):标记token在序列中的位置信息

38d98dd1223d4d14ae78059fcf27a20e.png

 

BERT的预训练任务主要由MLM和NSP两部分组成。

2.MLM

        为了同时利用上下文的信息,Bert将输入序列的部分 token 随机遮挡起来,通过预测这些被遮挡起来的 token,得到文本的双向特征。

        类似于完形填空:给定一句话,随机抹去这句话中的一个或几个词,要求根据剩余词汇预测被抹去的几个词分别是什么,若想正确地填上这些空,就一定需要对整个文本的信息进行学习。

        但由于预训练时存在mask操作但在下游微调任务中不会对文本mask,因此bert仅对15%的词进行mask,对于被选中的token,在80%的时间进行mask,10%的时间使用用随机token替代,10%的时间保持token不变,借此减小预训练与微调之间的差距。

dc084c0a637043fb84736d2f2abcefe8.png

 

        另外一个预训练任务NSP是:给定文本中的两句话,判断第二句话在文本中是否紧跟在第一句话之后,在训练时IsNext和NotNext标签各占50% 

905bed2e75b847c9a8ba096d2b84200a.png

 

         这就要求bert能够学习到文本的大意,NSP与 MLM 任务相结合,让模型能够更准确地刻画语句乃至篇章层面的语义信息。

BERT模型的优越性主要体现在三个方面:

1.双向上下文建模

相较于传统的单向模型,Bert考虑到输入序列中所有位置的上下文信息,能够更好地理解句子中的语境和依赖关系。

2.预训练阶段的无监督学习

BERT在大规模无标签的语料库上进行预训练,通过两个预训练任务MLM和NSP对语料库进行学习,使模型能够学习到通用的语言表示。

3.适用于多种下游任务

由于BERT预训练阶段学到的通用表示,只需在预训练模型的基础上微调,就可以适应不同的任务,无需重新训练整个模型。

三、代码解读

1.数据集准备

使用 Hugging Face 的 datasets 从Hub中加载了一个名为 "lcampillos/ctebmsp" 的生物医学实体识别数据集

a27e5a4d52174a349a8531f22ef30c85.png

2.BERT模型配置

使用了 dccuchile/bert-base-spanish-wwm-cased 作为预训练的 BERT 模型。 

5d8a0a6f8b3b4bf5b9edb2467a2fa46f.png

配置AdamW优化器,设置了学习率和权重衰减

f8c2adf7146d487e95be4327100be200.png

配置一个学习率调度程序,在训练开始时有一个热身阶段并且在训练过程中进行线性调度

6eea4524b50f4358bd518a636196a2bd.png

 

3.数据预处理

        对训练集、验证集和测试集进行了数据预处理,包括分词、填充、创建注意力掩码等。

定义标签映射和BERT分词器

b2d97c67620a4180a68d5cf8c0410152.png

        定义处理数据集的函数 process_dataset:对每个句子进行分词、填充和创建注意力掩码,最终转换为PyTorch张量。目的是将原始文本数据转换为模型可以接受的格式 

8e6e8acebe38412fb5b3d2f957f96671.png

使用上述定义的 process_dataset 函数对训练、验证和测试数据集进行处理

a16a1c3a97f044c9b52af6fb1d6f6c2d.png 

 使用PyTorch的DataLoader将处理后的数据集转换为可用于训练的批次数据。

3770ec0a0fb044f6b79cf6d9bd8757b0.png

4.模型训练

在range()函数中进行多个训练轮次

 2570d9de7476412f80a70e08f3b2bdd1.png

将模型设置为训练模式,启用梯度计算和参数更新

cf40e07441654030a397b73247134440.png

循环遍历训练数据集

7c859c09841f4735bac753e3b31c1ec3.png

 将每个批次的输入数据、注意力掩码和标签转移到GPU设备上

0c2c174908ad4baf80cca84a8d5d03ec.png 

执行前向传播,计算损失

执行反向传播,然后使用优化器更新模型参数。

 6f90104a1e084bc9ac3dee436628daca.png

 

5.学习曲线绘制

使用 Matplotlib 和 Seaborn 绘制了模型的学习曲线,包括训练损失和验证损失的变化趋势。

20c1c803b6844cbb8175cc2790d70926.png

6.模型测试

        在测试集上评估训练后的模型性能。计算测试集的NER性能指标,包括准确性和分类报告。

将模型设置为评估模式,禁用梯度计算和参数更新。

9a98034bbb6547c3915fc9bfde217bb1.png

 执行前向传播并获取预测结果

4cdc5445bfaa4310bdff28b2efa59da8.png

计算评估损失,将模型的预测结果和真实标签保存在相应的列表中

 1c7fe757806f45ae86969cb0e4e56401.png

将模型的预测结果和真实标签转换为嵌套列表格式,并使用classification_report函数输出分类报告,包括准确率、召回率、F1分数等性能指标 

255740f7589c477489b96426628281e2.png 

四、运行结果 

实验环境

PyTorch、Hugging Face Transformers库、Hugging Face Datasets库、scikit-learn库、NumPy、Pandas、Matplotlib、Seaborn库

模型配置

预训练的BERT模型:dccuchile/bert-base-spanish-wwm-cased优化器:AdamW

学习率:3e-5  训练轮数:4 批量大小:8

成功下载,导入数据集

dc5918c0c64049f488fae5da933a810e.png

完成数据预处理

d8e92bb6eb64434aa07a84d9fda3abcd.png

输出模型在训练过程中的性能指标以及在开发集(validation set)上的分类报告

第一轮:

平均训练损失: 0.0306

开发集损失: 0.0155

总体性能:F1-score 为 0.6279

各类别性能差异明显,ANAT 类别的 Precision 和 Recall 较低。

第二轮:

平均训练损失: 0.0127

开发集损失: 0.0143

总体性能提升,F1-score 为 0.6648

ANAT 类别的性能有所改善,但仍然较低。

第三轮:

平均训练损失: 0.0083

开发集损失: 0.0152

总体性能进一步提升,F1-score 为 0.6781

各类别的性能相对均衡。

第四轮:

平均训练损失: 0.0056

开发集损失: 0.0163

总体性能保持稳定,F1-score 为 0.6808

各类别的性能相对稳定,CHEM 和 DISO 类别性能较好。

随着训练轮次的增加,平均训练损失逐渐减小,表明模型在训练数据上逐步学到了特征。开发集损失逐渐减小,说明模型在验证数据上的性能逐渐提升,但在第四轮有轻微上升。模型整体性能在四轮中逐渐提升,最终在开发集上达到了相对稳定的水平。

319fbcf505a347588e1243bc334deeb8.png

76f9d16c22f74fd0bdec21b9df97a1b1.png 

绘制训练过程中的学习曲线,其中包括训练损失(training loss)和验证损失(validation loss)随着训练轮次的变化趋势。图像中的横轴表示训练轮次(Epoch),纵轴表示损失值(Loss)。每个点表示模型在相应训练轮次结束时的损失值。 

d6a91c582ed74f5eaefe3311a4168831.png

随着训练轮次的增加,训练损失逐渐减小。这表明模型在训练数据上逐步学到了特征,取得了收敛。后续训练损失下降但验证损失上升,则可能存在过拟合问题,模型在训练数据上表现好,但在新数据上表现较差。

测试集性能评估:

Accuracy(准确性): 91.78%,表示整体分类的准确性很高。

Macro Avg 和 Weighted Avg: 这两个指标是对所有类别性能的综合评价,显示模型在多类别任务上的整体表现。

模型在大多数类别上都表现良好,尤其是在 B-PROC、I-PROC、B-CHEM、I-CHEM、I-ANAT 等类别上具有较高的精确度和召回率。

55df687250b94c4d8861e6989b0a3856.png

五、参考文献 

  1. Vaswani, A., Shazeer, N., Parmar, N., Uszkoreit, J., Jones, L., Gomez, A. N., ... & Polosukhin, I. (2017). Attention is All You Need. In Advances in Neural Information Processing Systems (NeurIPS), 5998-6008.
  2. Devlin, J., Chang, M. W., Lee, K., & Toutanova, K. (2018). BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding. arXiv preprint arXiv:1810.04805.

六、总结 

        本次实验通过搭建基于BERT的命名实体识别系统,深入了解了模型的训练、验证和测试过程。通过使用Hugging Face的数据集库加载了一个西班牙语生物医学文本的命名实体识别数据集,并对数据集进行了预处理,包括分词、标签转索引等。选择了预训练的西班牙语BERT模型(dccuchile/bert-base-spanish-wwm-cased)作为基础模型,并根据任务配置了模型的输入参数、标签集、优化器等。利用训练集对BERT模型进行了训练,并通过设定的损失函数和学习率调度程序进行了模型参数的优化。在训练过程中,使用了GPU加速,并在多个轮次中迭代训练。通过在验证集上进行性能评估,监测模型的训练效果。利用分类报告、损失值等指标来评估模型对各个实体类别的识别性能。最终,利用测试集对训练好的BERT模型进行了测试,评估模型的泛化性能。实验结果表明,BERT模型在生物医学文本命名实体识别任务上具有良好的性能,但也需要对一些特定类别进行进一步的改进。

七、代码附录

# 安装必需的包
!pip install datasets
!pip install seqeval# 导入必要的库
import torch
import numpy as np
import pandas as pd
from datasets import load_dataset
from torch.utils.data import TensorDataset, DataLoader, RandomSampler, SequentialSampler
import transformers
from transformers import BertTokenizer, BertConfig
from keras.preprocessing.sequence import pad_sequences
from transformers import BertForTokenClassification, AdamW
import seqeval
from seqeval.metrics import f1_score, precision_score, recall_score, accuracy_score, classification_report# 设置Hugging Face API令牌以访问数据集
access_token = "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"# 从Hugging Face Hub加载一个命名数据集
dataset = load_dataset("lcampillos/ctebmsp", token=access_token)# 显示数据集信息
print(dataset)# 定义与BERT相关的参数
MAX_LEN = 270  # 最大句子长度
bs = 8         # 批量大小
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")  # 选择设备(如果可用,则为GPU)# 为令牌分类定义所有可能的标签
all_tags = ["O", "B-PROC", "I-PROC", "B-CHEM", "I-CHEM", "B-DISO", "I-DISO", "B-ANAT", "I-ANAT", "PAD"]# 创建标签到索引的映射字典
tag2idx = {tag: idx for idx, tag in enumerate(all_tags)}
tag_values = {idx: tag for idx, tag in enumerate(all_tags)}# 加载用于西班牙语的BERT分词器
tokenizer = BertTokenizer.from_pretrained("dccuchile/bert-base-spanish-wwm-cased", token=access_token)# 定义处理数据集的函数
def process_dataset(dataset):tokenized_texts = dataset["tokens"]labels = dataset["ner_tags"]# 对输入句子和标签进行填充input_ids = pad_sequences([tokenizer.convert_tokens_to_ids(txt) for txt in tokenized_texts],maxlen=MAX_LEN, dtype="long", value=0.0,truncating="post", padding="post")tags = pad_sequences([[tag2idx.get(l) for l in lab] for lab in labels],maxlen=MAX_LEN, value=tag2idx["PAD"], padding="post",dtype="long", truncating="post")# 创建注意力掩码以在测试期间忽略填充的元素attention_masks = [[float(i != 0.0) for i in ii] for ii in input_ids]# 转换为torch张量inputs = torch.tensor(input_ids)tags = torch.tensor(tags)masks = torch.tensor(attention_masks)return TensorDataset(inputs, masks, tags)# 处理训练、验证和测试数据集
train_data_processed = process_dataset(dataset["train"])
dev_data_processed = process_dataset(dataset["validation"])
test_data_processed = process_dataset(dataset["test"])# 为每个数据集定义DataLoader
train_dataloader = DataLoader(train_data_processed, batch_size=bs, shuffle=True)
dev_dataloader = DataLoader(dev_data_processed, batch_size=bs)
test_dataloader = DataLoader(test_data_processed, batch_size=bs)# 实例化用于令牌分类的BERT模型
model = BertForTokenClassification.from_pretrained("dccuchile/bert-base-spanish-wwm-cased",num_labels=len(tag2idx),output_attentions=False,output_hidden_states=False,token=access_token
)# 将模型移到GPU
model.cuda()# 配置优化器和学习率调度程序
FULL_FINETUNING = True
if FULL_FINETUNING:param_optimizer = list(model.named_parameters())no_decay = ['bias', 'gamma', 'beta']optimizer_grouped_parameters = [{'params': [p for n, p in param_optimizer if not any(nd in n for nd in no_decay)],'weight_decay_rate': 0.01},{'params': [p for n, p in param_optimizer if any(nd in n for nd in no_decay)],'weight_decay_rate': 0.0}]
else:param_optimizer = list(model.classifier.named_parameters())optimizer_grouped_parameters = [{"params": [p for n, p in param_optimizer]}]# Adam优化器
optimizer = AdamW(optimizer_grouped_parameters,lr=3e-5,eps=1e-8
)# 导入调度程序以减小学习率
from transformers import get_linear_schedule_with_warmup# 训练轮数
epochs = 4
max_grad_norm = 1.0# 总训练步骤数
total_steps = len(train_dataloader) * epochs# 创建学习率调度程序
scheduler = get_linear_schedule_with_warmup(optimizer,num_warmup_steps=0,num_training_steps=total_steps
)# 用于存储训练和验证损失值的列表
loss_values, development_loss_values = [], []# 训练循环
for _ in range(epochs):# 训练model.train()total_loss = 0for step, batch in enumerate(train_dataloader):# 将批次转移到GPUbatch = tuple(t.to(device) for t in batch)b_input_ids, b_input_mask, b_labels = batch# 移除之前的梯度model.zero_grad()# 前向传播outputs = model(b_input_ids, token_type_ids=None,attention_mask=b_input_mask, labels=b_labels)# 获取损失loss = outputs[0]# 反向传播loss.backward()# 训练损失total_loss += loss.item()# 限制梯度范数以防止梯度爆炸torch.nn.utils.clip_grad_norm_(parameters=model.parameters(), max_norm=max_grad_norm)# 更新参数optimizer.step()# 更新学习率scheduler.step()# 计算平均训练损失avg_train_loss = total_loss / len(train_dataloader)print("平均训练损失: {}".format(avg_train_loss))# 存储损失值以绘制学习曲线loss_values.append(avg_train_loss)# 开发集评估model.eval()eval_loss = 0predictions, true_labels = [], []for batch in dev_dataloader:batch = tuple(t.to(device) for t in batch)b_input_ids, b_input_mask, b_labels = batchwith torch.no_grad():outputs = model(b_input_ids, token_type_ids=None,attention_mask=b_input_mask, labels=b_labels)logits = outputs[1].detach().cpu().numpy()label_ids = b_labels.to('cpu').numpy()eval_loss += outputs[0].mean().item()predictions.extend([list(p) for p in np.argmax(logits, axis=2)])true_labels.extend(label_ids)eval_loss = eval_loss / len(dev_dataloader)development_loss_values.append(eval_loss)print("开发集损失: {}".format(eval_loss))# 将预测和真实标签转换为嵌套列表格式pred_tags = [tag_values[p_i] for p, l in zip(predictions, true_labels)for p_i, l_i in zip(p, l) if tag_values[l_i] != "PAD"]dev_tags = [tag_values[l_i] for l in true_labelsfor l_i in l if tag_values[l_i] != "PAD"]# 打印分类报告print("开发集分类报告:\n{}".format(classification_report(dev_tags, pred_tags, digits=4)))print()# 绘制训练损失
import matplotlib.pyplot as plt
import seaborn as sns
sns.set(style='darkgrid')
sns.set(font_scale=1.5)
plt.rcParams["figure.figsize"] = (12, 6)
plt.plot(loss_values, 'b-o', label="训练损失")
plt.plot(development_loss_values, 'r-o', label="验证损失")
plt.title("学习曲线")
plt.xlabel("Epoch")
plt.ylabel("Loss")
plt.legend()
plt.show()# 将模型应用于测试集
# 再次将模型设置为评估模式
from sklearn.metrics import classification_reportmodel.eval()
nb_eval_steps, nb_eval_examples = 0, 0
predictions, true_labels = [], []input_ids_list = []for batch in test_dataloader:batch = tuple(t.to(device) for t in batch)b_input_ids, b_input_mask, b_labels = batch# 模型不能计算或存储梯度with torch.no_grad():outputs = model(b_input_ids, token_type_ids=None,attention_mask=b_input_mask, labels=b_labels)# 将logits和标签传输到CPUlogits = outputs[1].detach().cpu().numpy()label_ids = b_labels.to('cpu').numpy()input_ids_list.extend(b_input_ids)# 计算这批测试句子的准确性eval_loss += outputs[0].mean().item()predictions.extend([list(p) for p in np.argmax(logits, axis=2)])true_labels.extend(label_ids)pred_tags = [tag_values[p_i] for p, l in zip(predictions, true_labels)for p_i, l_i in zip(p, l) if tag_values[l_i] != "PAD"]
test_tags = [tag_values[l_i] for l in true_labelsfor l_i in l if tag_values[l_i] != "PAD"]
print("测试准确性: {:.4f}".format(accuracy_score(pred_tags, test_tags)))
print("测试分类报告:\n{}".format(classification_report(pred_tags, test_tags, target_names=tag_values)))

 

 

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

Observability:使用 OpenTelemetry 自动检测 Go 应用程序

作者:来自 Elastic Damien Mathieu 使用 OpenTelemetry 检测 Go 应用程序可以深入了解应用程序的性能、依赖项和错误。我们将向你展示如何使用 Docker 自动检测 Go 应用程序,而无需更改应用程序代码。 在快节奏的软件开发领域,尤其是在云原生…

分治算法(3)_快速选择_数组中的第K个最大元素

个人主页:C忠实粉丝 欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 C忠实粉丝 原创 分治算法(3)_快速排序_数组中的第K个最大元素 收录于专栏【经典算法练习】 本专栏旨在分享学习算法的一点学习笔记,欢迎大家在评论区交流讨论&#…

【原创】Anaconda+VScode+PySide6 完美配置Python开发环境,亲测!

准备工作 下载安装 Anaconda 下载安装Visual Studio Code 配置系统环境变量 配置Anaconda环境变量 将Anaconda安装目录及Scripts 、Library\bin 两个子目录添加到用户变量或系统变量的Path变量中。 Anaconda自带最新版Python,如果已经安装Python,建议…

Mybatis测试案例

1.创建springboot工程 创建实体类user和接口 user类 注意:java和mysql的对象的属性数据类型要一致 mapper接口 2.配置mybatis(连接数据库信息) # spring.datasource.driver-class-namecom.mysql.cj.jdbc.Driver #地址url spring.datasource.urljdbc:mysql://localho…

【Python】Mistune:高效的 Python Markdown 解析器

Mistune 是一个轻量且强大的 Python Markdown 解析器。它的设计目标是兼顾速度和扩展性,同时兼容 CommonMark 标准。Mistune 支持多种渲染器(Renderers)和插件,能够根据需求将 Markdown 转换为 HTML、LaTeX 或自定义格式。此外&am…

Java中数组的应用

Java中数组的应用 数组数组的使用使用方式1-动态初始化数组的定义:数组的引用(使用/访问/获取数组元素):快速入门案例 使用方式2-动态初始化**先声明**数组**再创建**数组使用方式1和2的比较 使用方式3-静态初始化初始化数组快速入…

[嵌入式Linux]—STM32MP1启动流程

STM32MP1启动流程 1.启动模式 STM32MP1等SOC支持从多种设备中启动,如EMMC、SD、NAND、NOR、USB、UART等。其中USB、UART是作为烧录进行启动的。 STM32MP1内部ROM中存储有一段出厂代码来进行判断从哪种设备中启动,上电后这段代码会被执行,这…

CPU中的寄存器是什么以及它的工作原理是什么?

在计算机科学中,寄存器是数字设备中的一个重要组成部分,它用于存储数据和指令以快速处理。寄存器充当临时存储区,信息可以在这里被快速访问和操作,以执行复杂任务。寄存器是计算机中最基础的存储类型,它们在帮助机器高…

【Unity】版本不一致且未升级资产,导致 Unity Sprite 2D 动画播放错误

自己的 Unity版本是 2022.3.45f1。目前折腾的这插件 2D Action RPG Engine: Mythril2D ,推荐使用的 Unity 版本是 2021.3.18。 倒腾了这个 unity animation 动画半天,发现这个 animation sprite resolver 在导入动画帧的时候,一直都导入的是…

allegro 替换过孔

操作步骤如下 1.选择操作对象(需要替换的过孔),右键–>Repace……–>Selected…… 2.在弹出的窗口中选择最终需要的过孔既可以

【Matlab学习日记】② 常用滤波以及噪声分析方法(上)

关注星标公众号,不错过精彩内容 作者 | 量子君 微信公众号 | 极客工作室 【Matlab学习日记】专栏目录 第一章 ① Sinmulink自动代码生成教程 第二章 ② 常用滤波以及噪声分析方法(上) 文章目录 前言一、使用滤波的目的二、常见的几种噪声和表…

算法闭关修炼百题计划(四)

仅供个人复习 1.两数相加2.寻找峰值3.寻找旋转排序数组中的最小值4.寻找旋转排序数组中的最小值II5.搜索旋转排序数组6.岛屿的最大面积7.最大数8.会议室9.最长连续序列 1.两数相加 给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储…

STM32 通用同步/异步通信

一、串行通信简介 CPU与外围设备之间的信息交换称为通信。基本的通信方式有并行通信和串行通信两种。STM32单片机提供了功能强大的串行通信模块,即通用同步/异步收发器(USART)。 1.串行通信 串行通信是数据字节一位一位地依次传送的通信方式。…

毕业设计 深度学习水果识别

文章目录 1 前言2 开发简介3 识别原理3.1 传统图像识别原理3.2 深度学习水果识别 4 数据集5 部分关键代码5.1 处理训练集的数据结构5.2 模型网络结构5.3 训练模型 6 识别效果 1 前言 Hi,大家好,这里是丹成学长,今天做一个 基于深度学习的水果…

毕业设计——医院信息化系统原型设计

作品详情 主要功能: 信息化系统是以患者为中心,服务于重症科室医务人员,提高工作效率及医疗服务质量。软件主要包含了重症医学临床管理系统和中央监控站,重症医学临床管理系统主要实现患者床位总览、患者护理、医嘱管理、数据字典…

JS 介绍/书写位置/输入输出语法

目录 1. JS 介绍 1.1 JS 是什么 1.2 JS 的作用 1.3 JS 的组成 2. JS 书写位置 2.1 内部 JS 2.2 外部 JS 2.3 内联 JS 3. JS 注释和结束符 4. JS 输入输出语法 4.1 输入语法 4.2 输入语句 4.3 执行顺序 5. 字面量 1. JS 介绍 1.1 JS 是什么 1.2 JS 的作用 1.3 JS …

GOM引擎启动后M2提示Invalid filename报错的解决办法

在架设一个GOM引擎版本的时候,启动M2就提示Invalid filename,之后的网关就没有办法再启动了,研究了半天也终于是弄好了,其实也简单,就是路径设置的不对,所以无法完成启动,很多人以为在控制台设置…

国庆节刷题

10.1 C语言 10.1 C 10.2 C语言 10.2 C 10.3 C语言 10.3 C 10.4 C语言 10.4 C 10.5 C语言 10.5 C 10.6 C语言 10.6 C

如何写出Pythonic的代码?

f-string、三元操作、各种解析式、生成器装饰器的熟练运用,“内库”引用和函数封装再加持PEP8,撰写的脚本不pythonic都难。😎 (笔记模板由python脚本于2024年10月07日 18:03:27创建,本篇笔记适合特别喜欢python的coder翻阅) 【学习…

手机号归属地查询-手机号归属地-手机号归属地-运营商归属地查询-手机号码归属地查询手机号归属地-运营商归属地

手机号归属地查询API接口是一种网络服务接口,允许开发者通过编程方式查询手机号码的注册地信息。关于快证签API接口提供的手机号归属地查询服务,以下是一些关键信息: 一、快证签API接口简介 快证签API接口可能是一个提供多种验证和查询服务…