华为云征文|华为云Flexus X实例ultralytics模型yolov10深度学习AI部署与应用

news2024/11/13 9:42:31

目录

前言:

环境准备

购买服务器配置

连接服务器

安装Python

安装Pytorch

部署YOLOv10

拉取YOLOv10代码并安装相关依赖

数据集准备

Detect目标检测模型训练

训练数据集的配置文件

训练命令

识别命令


前言:

本实验演示从0到1部署YOLOv10深度学习AI大模型的环境搭建、模型训练、权重使用,以及各项指标解读。实验环境为Flexus云服务器X实例 服务器,配置:4vCPUs | 12GiB

环境准备

购买服务器配置

本次实验使用的是 Flexus云服务器X实例 服务器。

在性能设置中我选择了自定义模式,使用了4vCPUs | 12GiB,因为本次要实验的是yolov10的部署与应用,Windows操作系统具有更加直观的用户界面和强大的图形支持,我选择了公共镜像Windows Server 2022 数据中心版。以上配置仅供参考,并非硬性要求!

连接服务器

在华为云服务器控制台中找到我们刚刚购买的服务器,将弹性公网IP地址复制下来。

快捷键Windows + R 打开运行窗口,输入mstsc,回车!

输入计算机:弹性公网IP地址;用户名:MicrosoftAccount\Administrator,单击“确定”。

然后输入密码,就成功的连接到我们的服务器了。

如果忘记密码了,可以在操作列中点击重置密码,重新设置我们的服务器密码。

安装Python

我们先来安装python3,打开官网地址

Download Python | Python.org

在官网下一个大于大于3.8的python安装包(官方建议使用3.9的版本),选择amd64的exe版本

安装的时候勾选最底下的帮我们添加环境变量

等待片刻,出现下面这个界面就是安装成功了。

CMD打开控制台小黑窗,执行 python -V 和 pip -V 查看python版本与pip版本,看看我们的环境变量是否设置成功。

安装Pytorch

到官网安装Pytorch

Start Locally | PyTorch

在安装之前看看自己买的服务器是否有GPU,可以使用命令来查看

查看CPU型号:cat /proc/cpuinfo | grep "model name"

查看GPU型号(Nvidia GPU):nvidia-smi --query-gpu=gpu_name --format=csv

查看GPU型号(AMD Radeon GPU):sudo lshw -C display

因为我这台是只有CPU的,因此在官网中选择Stable(稳定版),系统Linux,用pip来安装吧,然后Compute Platform选择CPU,然后把Run this Command:中的命令👇cmd打开黑窗口执行。

我这里执行的是

pip3 install torch torchvision torchaudio
直接执行可能会很慢,我在后面加上指定镜像源,切换为国内镜像
pip3 install torch torchvision torchaudio -i https://pypi.mirrors.ustc.edu.cn/simple/

出现如下画面即是成功下载完成。

部署YOLOv10

YOLOv10是YOLO(You Only Look Once)系列的最新版本,由清华大学的研究人员开发,旨在进一步提高实时目标检测的效率和准确性。以下是对YOLOv10的详细介绍:

之前的YOLO版本在后处理和模型架构方面仍存在不足,特别是依赖于非最大抑制(NMS)进行后处理,这限制了模型的端到端部署并增加了推理延迟。YOLOv10通过消除NMS和优化模型组件,旨在解决这些问题,实现更高的性能和效率。

拉取YOLOv10代码并安装相关依赖

打开YOLOV0的GItHub代码库,将源码下载到本地,解压。

GitHub - THU-MIG/yolov10: YOLOv10: Real-Time End-to-End Object Detection

解压完成后,打开命令行窗口,cd到源码的工作目录,执行下面两个命令。

//升级pip
python -m pip install --upgrade pip
pip install -r requirements.txt
pip install ultralytics
pip install yolo
pip install -e .

速度慢的话换国内镜像,在命令后面加上-i 镜像源
以下是常用的国内镜像源
清华大学:https://pypi.tuna.tsinghua.edu.cn/simpl
阿里云:https://mirrors.aliyun.com/pypi/simple/
豆瓣:https://pypi.douban.com/simple/
腾讯云:https://mirrors.cloud.tencent.com/pypi/simple/
华为云:https://mirrors.huaweicloud.com/repository/pypi/simple/
中国科学技术大学:https://pypi.mirrors.ustc.edu.cn/simple/
华中科技大学:http://pypi.hustunique.com/
山东理工大学:http://pypi.sdutlinux.org/
浙江大学:https://mirrors.zju.edu.cn/pypi/web/simple
北京外国语大学:https://mirrors.bfsu.edu.cn/pypi/web/simple
上海交通大学:https://mirrors.sjtug.sjtu.edu.cn/pypi/web/simple

当以上相关依赖都安装完毕后,执行以下训练命令测试我们的环境(此步骤可跳过)。

yolo detect train data=coco.yaml model=yolov10s.yaml epochs=5 batch=256 imgsz=640

第一次执行会自动下载官方提供的训练案例文件,需要等待较长时间。

数据集准备

YOLOv10作为实时目标检测模型,理论上支持多种类型的数据集,只要这些数据集符合YOLOv10的输入格式和标注要求。具体来说,YOLOv10可以支持的数据集包括但不限于以下几种类型:

  1. 通用目标检测数据集:如COCO(Common Objects in Context)数据集,这是一个大型、丰富的图像数据集,用于目标检测、分割、关键点检测等多种任务。YOLOv10在COCO数据集上取得了显著的性能提升,展现出优异的精度-效率平衡能力。
  2. 特定领域数据集:YOLOv10也可以应用于特定领域的数据集,如交通标志检测数据集、人脸检测数据集、车辆检测数据集等。这些数据集通常针对特定场景或任务进行收集和标注,以满足特定领域的需求。
  3. 自定义数据集:用户还可以根据自己的需求创建自定义数据集,并使用YOLOv10进行训练和测试。自定义数据集需要按照YOLOv10的输入格式进行标注和组织,包括图像文件、标签文件以及可能的数据集配置文件等。

通常来说,我们需要将标注结果与原图按比例分配到三个文件夹中

如你有100张标注了的图片,大约 70 张图片用于训练数据,约 20 张图片用于验证数据,约 10 张图片用于测试数据

train 路径用于训练模型,val 路径用于验证模型,test 路径用于测试模型。在训练和验证期间,模型将在不同的数据集上进行训练和验证,以便评估模型的性能。在测试期间,模型将使用整个数据集进行测试,以确定其性能指标

需要注意的是:训练过的图片通常不能用于验证数据。这是因为在训练期间,模型已经对这些图片进行了训练,并学会了识别这些图片中的对象和场景类别。

因为数据标注要花费大量的时间,这里直接拿出我最爱的皮卡丘标注数据

400多张“皮卡丘”原图与标注结果以及yolov8的训练结果best.pt权重和ONNX格式文件_yolov8权重转onnx资源-CSDN文库

在这个压缩包中有皮卡丘图片与标注信息,还有yolov8的训练好的权重文件,我们只留下images和labels用来训练yolov10版本的权重。

因为我比较懒,能用代码解决的事就用代码,下面我们使用python对数据集进行随机分配。

修改下面代码中66-67行中的

src_data_folder = '数据集路径' target_data_folder = '处理后的数据集'

# 工具类
import os
import random
from shutil import copy2

def data_set_split(src_data_folder, target_data_folder, train_scale=0.8, val_scale=0.2):
    '''
    读取源数据文件夹,生成划分好的文件夹,分为train、val两个文件夹进行
    :param src_data_folder: 源文件夹
    :param target_data_folder: 目标文件夹
    :param train_scale: 训练集比例
    :param val_scale: 验证集比例
    :return:
    '''
    print("开始数据集划分")
    class_names = os.listdir(src_data_folder)
    # 在目标目录下创建文件夹
    split_names = ['train', 'val']
    for split_name in split_names:
        split_path = os.path.join(target_data_folder, split_name)
        if os.path.isdir(split_path):
            pass
        else:
            os.makedirs(split_path)
        # 然后在split_path的目录下创建类别文件夹
        for class_name in class_names:
            class_split_path = os.path.join(split_path, class_name)
            if os.path.isdir(class_split_path):
                pass
            else:
                os.makedirs(class_split_path)

    # 按照比例划分数据集,并进行数据图片的复制
    # 首先进行分类遍历
    for class_name in class_names:
        current_class_data_path = os.path.join(src_data_folder, class_name)
        current_all_data = os.listdir(current_class_data_path)
        current_data_length = len(current_all_data)
        current_data_index_list = list(range(current_data_length))
        random.shuffle(current_data_index_list)

        train_folder = os.path.join(os.path.join(target_data_folder, 'train'), class_name)
        val_folder = os.path.join(os.path.join(target_data_folder, 'val'), class_name)
        train_stop_flag = current_data_length * train_scale
        current_idx = 0
        train_num = 0
        val_num = 0
        for i in current_data_index_list:
            src_img_path = os.path.join(current_class_data_path, current_all_data[i])
            if current_idx <= train_stop_flag:
                copy2(src_img_path, train_folder)
                train_num = train_num + 1
            else:
                copy2(src_img_path, val_folder)
                val_num = val_num + 1

            current_idx = current_idx + 1

        print("*********************************{}*************************************".format(class_name))
        print("{}类按照{}:{}的比例划分完成,一共{}张图片".format(class_name, train_scale, val_scale, current_data_length))
        print("训练集{}:{}张".format(train_folder, train_num))
        print("验证集{}:{}张".format(val_folder, val_num))


if __name__ == '__main__':
    src_data_folder = 'datasets/dwsb'
    target_data_folder = 'datasets/dwsb2'
    data_set_split(src_data_folder, target_data_folder, 0.8, 0.2)

要注意的是,不管是train还是val都需要检查其labels文件中是否包含这么一个classes.txt文件,如果没有的话需要自己手动补上,因为我这里的素材只有一个皮卡丘目标,并且标注为1了,所以只写了一个1。

Detect目标检测模型训练

训练数据集的配置文件

参考路径C:\yolov10-main\ultralytics\cfg\datasets 找到voc.yaml,复制一份,自定义一个名字

对里面的代码进行调整,path 是我们的刚刚准备好的数据集目录路径(就是刚刚的data,我改了个名字),train和val就是训练集和验证集的文件夹名称。

names: 标注时的数值和他的别名(这里需要根据照数据集的标注类别来定义,如果用的是我的数据集,直接按照我的设置就好了)

# Ultralytics YOLO 🚀, AGPL-3.0 license
# PASCAL VOC dataset http://host.robots.ox.ac.uk/pascal/VOC by University of Oxford
# Documentation: # Documentation: https://docs.ultralytics.com/datasets/detect/voc/
# Example usage: yolo train data=VOC.yaml
# parent
# ├── ultralytics
# └── datasets
#     └── VOC  ← downloads here (2.8 GB)

# Train/val/test sets as 1) dir: path/to/imgs, 2) file: path/to/imgs.txt, or 3) list: [path/to/imgs1, path/to/imgs2, ..]
path: C:/yolov10-main/datasets/pkqdata

train: train
val: val

test: # test images (optional)
  - images/test2007

# Classes
names:
  0: pkq

# Download script/URL (optional) ---------------------------------------------------------------------------------------
download: |
  import xml.etree.ElementTree as ET

  from tqdm import tqdm
  from ultralytics.utils.downloads import download
  from pathlib import Path

  def convert_label(path, lb_path, year, image_id):
      def convert_box(size, box):
          dw, dh = 1. / size[0], 1. / size[1]
          x, y, w, h = (box[0] + box[1]) / 2.0 - 1, (box[2] + box[3]) / 2.0 - 1, box[1] - box[0], box[3] - box[2]
          return x * dw, y * dh, w * dw, h * dh

      in_file = open(path / f'VOC{year}/Annotations/{image_id}.xml')
      out_file = open(lb_path, 'w')
      tree = ET.parse(in_file)
      root = tree.getroot()
      size = root.find('size')
      w = int(size.find('width').text)
      h = int(size.find('height').text)

      names = list(yaml['names'].values())  # names list
      for obj in root.iter('object'):
          cls = obj.find('name').text
          if cls in names and int(obj.find('difficult').text) != 1:
              xmlbox = obj.find('bndbox')
              bb = convert_box((w, h), [float(xmlbox.find(x).text) for x in ('xmin', 'xmax', 'ymin', 'ymax')])
              cls_id = names.index(cls)  # class id
              out_file.write(" ".join(str(a) for a in (cls_id, *bb)) + '\n')


  # Download
  dir = Path(yaml['path'])  # dataset root dir
  url = 'https://github.com/ultralytics/yolov5/releases/download/v1.0/'
  urls = [f'{url}VOCtrainval_06-Nov-2007.zip',  # 446MB, 5012 images
          f'{url}VOCtest_06-Nov-2007.zip',  # 438MB, 4953 images
          f'{url}VOCtrainval_11-May-2012.zip']  # 1.95GB, 17126 images
  download(urls, dir=dir / 'images', curl=True, threads=3, exist_ok=True)  # download and unzip over existing paths (required)

  # Convert
  path = dir / 'images/VOCdevkit'
  for year, image_set in ('2012', 'train'), ('2012', 'val'), ('2007', 'train'), ('2007', 'val'), ('2007', 'test'):
      imgs_path = dir / 'images' / f'{image_set}{year}'
      lbs_path = dir / 'labels' / f'{image_set}{year}'
      imgs_path.mkdir(exist_ok=True, parents=True)
      lbs_path.mkdir(exist_ok=True, parents=True)

      with open(path / f'VOC{year}/ImageSets/Main/{image_set}.txt') as f:
          image_ids = f.read().strip().split()
      for id in tqdm(image_ids, desc=f'{image_set}{year}'):
          f = path / f'VOC{year}/JPEGImages/{id}.jpg'  # old img path
          lb_path = (lbs_path / f.name).with_suffix('.txt')  # new label path
          f.rename(imgs_path / f.name)  # move image
          convert_label(path, lb_path, year, id)  # convert labels to YOLO format

训练命令

执行下面命令开始训练我们的模型

yolo detect train data=coco.yaml model=yolov10n/s/m/b/l/x.yaml epochs=500 batch=256 imgsz=640 device=0,1,2,3,4,5,6,7

关于命令的内容,我们来进行解读:

  1. data=coco.yaml: 指定了训练数据集的配置文件,coco.yaml是一个YAML格式的文件,它包含了训练YOLO模型所需的数据集信息,如图片路径、标注文件路径、类别名称等。数据集遵循COCO(Common Objects in Context)的格式
  2. model=yolov10n/s/m/b/l/x.yaml: 指定了模型的配置文件。这里使用了yolov10n/s/m/b/l/x.yaml作为占位符,实际上应该选择一个具体的模型配置,如yolov10n.yamlyolov10s.yaml
    1. YOLOv10-N:适用于资源极其有限的环境
    2. YOLOv10-S:兼顾速度与精度
    3. YOLOv10-M:一般用途
    4. YOLOv10-B:宽度增加,精度更高
    5. YOLOv10-L:以计算资源为代价实现高精度
    6. YOLOv10-X:最高精度和性能
  3. epochs=500: 指定了训练过程中的迭代次数(epoch)。一个epoch意味着整个训练数据集被遍历了一次。这里设置为500,意味着整个数据集将被用于训练500次。
  4. batch=256: 设置了每个batch中的图片数量。Batch size是一个重要的超参数,它影响模型的训练速度和稳定性。较大的batch size可以加速训练,但也可能需要更多的内存。
  5. imgsz=640: 指定了输入图片的大小。在这个例子中,所有输入图片都将被调整(或裁剪)到640x640像素。调整输入图片大小是YOLO等目标检测模型训练前的常见步骤。
  6. device=0,1,2,3,4,5,6,7: 指定了用于训练的GPU设备ID。在这个例子中,它使用了8个GPU(从0到7编号)来加速训练过程。这通常是在具有多个GPU的服务器上进行的,可以显著减少训练时间。

执行完命令后出现以下窗口意味着正在训练中,接下来就是漫长的等待~~~

打开任务管理器看一下性能,CPU的利用率还是很可观的,4vCPUs | 12GiB的配置训练yolov10s的模型绰绰有余!

训练完成后

weights下有两个.pt文件,这是我们的训练结果权重文件

  1. best.pt文件保存的是在验证集上表现最好的模型权重。在训练过程中,每个epoch结束后都会对验证集进行一次评估,并记录下表现最好的模型的权重。这个文件通常用于推理和部署阶段,因为它包含了在验证集上表现最好的模型的权重,可以获得最佳的性能。
  2. last.pt文件则保存的是最后一次训练迭代结束后的模型权重。这个文件通常用于继续训练模型,因为它包含了最后一次训练迭代结束时的模型权重,可以继续从上一次训练结束的地方继续训练模型。

因此部署的话使用best,下次继续追加训练就用last

除了权重文件,我们发现还有一些训练结果可视化分析图,下面我们对其中几张进行查看!

为了能够评价不同算法的优劣,在Precision和Recall的基础上提出了F1值的概念,来对Precision和Recall进行整体评价。F1的定义如下:

F1值的取值范围是0到1,其中1表示最佳性能(即精确率和召回率都为1),而0表示最差性能(即精确率和召回率都为0)由上图可见模型在平衡精确率和召回率方面的表现都比较理想。

在目标检测中,损失函数扮演着至关重要的角色。它的主要作用是衡量模型预测结果与真实标签之间的差异或误差,并通过最小化这个差异来优化模型的参数,从而提高模型的预测准确性。

IoU系列损失函数简介

  • IoU(Intersection over Union):最基本的目标检测损失函数之一,计算预测框与真实框的交集与并集之比。然而,当预测框与真实框不相交时,IoU值为0,导致损失函数没有梯度。
  • GIoU(Generalized Intersection over Union):针对IoU的缺点进行改进,引入了最小封闭形状C(可以包含预测框和真实框)的概念,并计算C中未覆盖预测框和真实框的面积占C总面积的比值,最后用IoU减去这个比值得到GIoU。GIoU能够在预测框与真实框不重叠时提供梯度信息。
  • DIoU(Distance-IoU):进一步考虑了预测框与真实框中心点之间的距离信息,使损失函数在重叠时仍能为边界框提供移动方向。
  • CIOU(Complete IoU):在DIoU的基础上增加了长宽比的一致性项,使损失函数更加全面和鲁棒。

识别命令

使用yolo predict来进行识别,model就是我们刚刚训练好的模型,source是你要拿来识别的图片文件夹路径。同时后面可以设置一些参数来调整你想要的识别结果。

yolo predict model=模型路径 source= 图片路径 conf=0.5 识别阈值

更多其他参数可参考下表 :

Key

Value

Description

source

'ultralytics/assets'

source directory for images or videos

conf

0.25

object confidence threshold for detection

iou

0.7

intersection over union (IoU) threshold for NMS

imgsz

640

image size as scalar or (h, w) list, i.e. (640, 480)

half

False

use half precision (FP16)

device

None

device to run on, i.e. cuda device=0/1/2/3 or device=cpu

show

False

show results if possible

save

False

save images with results

save_txt

False

save results as .txt file

save_conf

False

save results with confidence scores

save_crop

False

save cropped images with results

hide_labels

False

hide labels

hide_conf

False

hide confidence scores

max_det

300

maximum number of detections per image

vid_stride

False

video frame-rate stride

line_width

None

The line width of the bounding boxes. If None, it is scaled to the image size.

visualize

False

visualize model features

augment

False

apply image augmentation to prediction sources

agnostic_nms

False

class-agnostic NMS

retina_masks

False

use high-resolution segmentation masks

classes

None

filter results by class, i.e. class=0, or class=[0,2,3]

boxes

True

Show boxes in segmentation predictions

执行完识别命令后,可在输出信息中看到识别结果文件所在位置,detect\predict(数字会自动叠加)

任意打开一张图片,找出识别前的图片对比一下,皮卡丘已经被框出来了,并打上我们设置的pkq标签。

至此~我们就完成了YOLOv10目标检测模型的训练与识别工作了!整个实验操作下来,Flexus云服务器X实例的表现都是非常出色的!

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

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

相关文章

tecplot宏批量导入数据

Tecplot新手进阶——使用tecplot宏操作批量处理数据输出图片&#xff08;详细步骤&#xff09; tecplot 宏的使用方法及代码改写 第一步&#xff1a;首先点击Scripting–>Record Macro&#xff0c;生成一个脚本文件&#xff0c;即.mcr文件 点击保存&#xff0c;会出现这个…

Activity的优雅跳转

需求1&#xff1a;跳转到下一个界面&#xff1a;NextActivity startActivity(Intent(this,NextActivity::class.java))需求2&#xff1a;跳转到下一个界面(并传参数)&#xff1a;NextActivity startActivity(Intent(this,NextActivity::class.java).apply { putExtra("pa…

Vulnhub靶场 | DC系列 - DC9

文章目录 DC-9环境搭建渗透测试端口敲门服务 DC-9 环境搭建 靶机镜像下载地址&#xff1a;https://vulnhub.com/entry/dc-6,315/需要将靶机和 kali 攻击机放在同一个局域网里&#xff1b;本实验kali 的 IP 地址&#xff1a;192.168.10.146。 渗透测试 使用 nmap 扫描 192.1…

【Linux】Ubuntu 安装 NFS 步骤详解

Ubuntu 安装 NFS 步骤详解 1.安装 NFS 服务2.配置 NFS 服务3.启用 NFS 服务4.客户端挂载 NFS 共享目录5.验证挂载是否成功6.持久化挂载&#xff08;可选&#xff09;7.其他客户端节点安装 NFS&#xff08;Network File System&#xff09;是一种允许不同主机之间通过网络共享文…

快速了解Git 文件的四种状态及其操作指令、如何忽略文件

&#x1f600;前言 在软件开发过程中&#xff0c;版本控制是团队协作的基石之一。Git 作为分布式版本控制系统&#xff0c;被广泛应用于各类项目的管理中。在使用 Git 进行文件管理时&#xff0c;理解文件的不同状态以及如何有效操作这些文件是非常重要的。本文将介绍 Git 文件…

BaseCTF之web(week2)

目录 ez_ser 一起吃豆豆 你听不到我的声音 Really EZ POP RCEisamazingwithspace 所以你说你懂 MD5? 数学大师 ez_ser <?php highlight_file(__FILE__); error_reporting(0);class re{public $chu0;public function __toString(){if(!isset($this->chu0)){return…

Docker 容器编排之 Docker Compose

目录 1 Docker Compose 概述 1.1 主要功能 1.2 工作原理 1.3 Docker Compose 中的管理层 2 Docker Compose 的常用命令参数 2.1 服务管理 2.1.1 docker-compose up &#xff1a; 2.1.2 docker-compose down &#xff1a; 2.1.3 docker-compose start &#xff1a; 2.1.4 docker…

数据结构:(LeetCode101)对称二叉树

给你一个二叉树的根节点 root &#xff0c; 检查它是否轴对称。 示例 1&#xff1a; 输入&#xff1a;root [1,2,2,3,4,4,3] 输出&#xff1a;true示例 2&#xff1a; 输入&#xff1a;root [1,2,2,null,3,null,3] 输出&#xff1a;false提示&#xff1a; 树中节点数目在范围…

World of Warcraft [CLASSIC][80][Shushia] [Obsidian Sanctum][Sartharion]

黑曜石圣殿 [Obsidian Sanctum] 萨塔里奥[Sartharion] 号旗披风、龙魂图典、五色巨龙之怒、黑曜石巨盔等装备&#xff0c;都是非常极品的BIS装备 召唤顺序&#xff1a;&#xff08;中&#xff09;塔尼布隆、&#xff08;右&#xff09;沙德隆、&#xff08;左&#xff09;维斯…

SAP OBYC配置方案

在SAP OBYC配置中&#xff0c;确保评估级别与会计科目匹配的关键在于正确设置评估级别、评估分组代码以及相关的会计科目。以下是确保匹配的步骤和注意事项&#xff1a; 定义评估控制&#xff1a;在SAP中&#xff0c;首先需要定义评估控制&#xff0c;这通常与工厂或公司代码相…

switch语句和while循环

switch语句和while循环 switch语句break的用法default的用法switch语句中的case和default的顺序问题 while语句while语句的执行流程while语句的具体例子 switch语句 switch 语句是⼀种特殊形式的 if…else 结构&#xff0c;用于判断条件有多个结果的情况。它把多重 的 else if…

13 隔离性

数据库并发的场景 读-读&#xff1a;不存在任何问题&#xff0c;也不需要并发控制 读-写&#xff1a;有线程安全问题&#xff0c;可能会造成事务隔离性问题&#xff0c;可能遇到脏读&#xff0c;幻读&#xff0c;不可重复读 写-写&#xff1a;有线程安全问题&#xff0c;可能存…

低代码开发与数据库:数字化转型的新引擎

低代码开发与数据库&#xff1a;数字化转型的新引擎 前言低代码开发的革命性优势数据库在低代码开发中的关键角色实践案例分析未来展望结语 前言 在当今这个快速变化的时代&#xff0c;技术的革新不断推动着企业向数字化转型迈进。随着云计算、大数据、人工智能等技术的飞速发展…

VastBase——执行计划

一、SQL的执行过程 1.词法分析 从查询语句中识别出系统支持的关键字、标识符、运算符、终结符等&#xff0c;确定每个词固有的特性。 以如下这个查询为例&#xff1a; select name from test_0717 where id > 1; 该SQL语句可以划分的关键字、标识符、运算符、常量等…

机器视觉-3 光学成像之明场与暗场

一. 原理介绍 在机器视觉中&#xff0c;光学成像的明场&#xff08;Bright Field&#xff09;和暗场&#xff08;Dark Field&#xff09;是两种常见的成像技术&#xff0c;分别用于不同的检测和分析场景。它们通过不同的光照方式来突出对象的特征&#xff0c;从而帮助识…

基于单片机的多功能数字闹钟设计

本设计是基于单片机来设计的多功能数字闹钟。主要功能包括显示年、月、日、星期、时、分、秒和温湿度等信息&#xff0c;并提示当前环境温湿度是否处于人体舒适区间内&#xff0c;并且设置了4个闹钟用于日常生活中使用&#xff0c;同时设计有秒表计时、整点报时功能等等。在控制…

PCIe Gen4 ltssm协商过程

本章节我们以gen4 Endpoint为例介绍PCIe ltssm(链路状态机)协商过程。 正常PCIe设备链路状态跳变为 detect-->polling-->configuration-->L0(gen1)-->recovery-->L0(gen3)-->recovery-->L0(gen4)。 需要注意的是在进入configuration状态之前&#xff…

视频化时代,用好AIGC产品赋能企业培训打造增效降本“最佳实践”

根据IBM的数据&#xff0c;85%的中国企业正在加速投资AI领域&#xff0c;其中超过63%的企业已积极采用生成式AI。德勤的调研进一步显示&#xff0c;近80%的全球受访企业高管认为&#xff0c;生成式AI的兴起与发展将在3年内推动组织和行业发生实质性变革&#xff0c;这也就意味着…

若依nodejs全栈(五:导出Excel与用户列表填坑)

回顾 上一章节中&#xff0c;我们学会了ruoyi用户列表简单的增删改查功能&#xff0c;但是上一节还存在一些问题&#xff1a; 查询的列表是全部数据&#xff0c;没加查询条件&#xff1b;没有导出功能&#xff1b;新增或修改时&#xff0c;用户关联的角色、岗位、菜单等没做关…

【R语言速通】1.数据类型

文章目录 0. 变量名1.基本数据类型1.1 数值型1.2 整型1.3 复数型1.4 逻辑型1.5 字符型 2.复合数据类型2.1 向量向量操作向量的常用函数 2.2 矩阵矩阵操作矩阵的常用函数 2.3 数组数组的操作数据的运算数组的访问数组的维度操作 数组的常用函数 2.4 数据框数据框操作数据框的常用…