当前位置: 首页 > news >正文

7.卷积神经网络与计算机视觉

计算机视觉是一门研究如何使计算机识别图片的学科,也是深度学习的主要应用领域之一。

在众多深度模型中,卷积神经网络“独领风骚”,已经被称为计算机视觉的主要研究根据之一。

一、卷积神经网络的基本思想

卷积神经网络最初由 Yann LeCun(杨立昆)等人在1989年提出,是最初取得成功的深度神经网络之一。

1、局部连接

1、全局连接

传统的BP神经网络,例如多层感知器,前一层的某个节点与后一层的所有节点都有连接后一层的某一个节点与前一层的所有节点也有连接,这种连接方式成为全局连接

如果前一层有M个节点,后一层有N个节点,我们就会有 M×N 个链接权值,

每一轮反向传播更新权值的时候都要对这些权值进行重新计算,造成了 O(M×N)=O(n ²)的计算与内存开销。

2、局部连接

局部连接的思想就是使得两层之间只有相邻的结点才进行连接,即连接都是“局部”的。

以图像处理为例,直觉上,图像的某一个局部的像素点组合在一起共同呈现出一些特征,而图像中距离比较远的像素点组合起来则没有什么实际意义,因此这种局部连接的方式可以在图像处理的问题上有较好的表现。

如果把连接限制在空间中相邻 c 个节点,就把连接权值降低到了 c×N,计算与内存开销就降低到了 O(c×N)= O(n)

2、参数共享

既然在图像处理中,我们认为图像的特征具有局部性,那么对于每一个局部使用不同的特征抽取方式(即不同的连续权值)是否合理?

由于不同的图像在结构上相差甚远,同一个局部位置的特征并不具有共性,对于某一个局部使用特定的连续权值不能让我们得到更好的结果。

因此我们考虑让空间中不同位置的结点连续权值进行共享,例如在局部连接的图中,属于结点 s₂的连续权值

w = { w₁,w₂,w₃|w₁:x₁ → s₂;w₂:x₂ → s₂;w₃:x₃ →s₂}

可以被结点s₃

w = { w₁,w₂,w₃|w₁:x₂ → s₃;w₂:x₃ → s₃;w₃:x₄ →s₃}

的方式共享。其他结点的权值共享类似。

这样一来,两层之间的连续权值就减少到 c 个。虽然在前向传播和反向传播的过程中,计算开销仍为 O(n),但内存开销被减少到常数级别O(c)。

二、卷积操作

离散的卷积操作正是这样一种操作,它满足了以上局部连接、参数共享的性质。代表卷积操作的结点层称为卷积层

泛函分析中,卷积被 f * g 定义为:

一维离散的卷积操作可以被定义为:

现在,假设 f 和 g 分别代表一个从向量下标到向量元素值的映射,令 f 表示输入向量,g 表示的向量称为卷积核(kermel),则卷积核施加于输入向量上的操作类似于一个权值向量在输入向量上移动,每移动一步进行一次加权求和操作;每一步移动的距离被称为步长(stride)。

例如,我们取输入向量大小为5,卷积核大小为3,步长为1,则卷积操作过程如图:

卷积核从输入向量左边开始扫描,权值在第一个位置分别与对应输入值相乘求和,得到卷积特征值向量的第一个值,接下来,移动1个步长,到达第二个位置,进行相同操作,依此类推。

这样就实现了从前一层的输入向量提取特征到后一层的操作,这种操作具有局部连接(每个结点只与其相邻的3个结点有连接)以及参数共享(所用的卷积核为同一个向量)的特征。

类似地,我们可以拓展到二维(如图)以及更高维度的卷积操作。

1、多个卷积核

利用一个卷积核进行卷积抽取特征是不充分的,因此在实践中,通常使用多个卷积核来提升特征提取的效果,之后将不同卷积核卷积所得的特征张量沿第一维拼接形成更高一个维度的特征张量。

2、多通道卷积

在处理彩色图像时,输入的图像有R、G、B这3个通道的数值,这个时候分别使用不同的卷积核对每一个通道进行卷积,然后使用线性或非线性的激活函数将相同位置的卷积特征合并为一个。

3、边界填充

注意在图中,卷积核的中心 g(2) 并不是从边界 f (1) 上开始扫描的。以一维

卷积为例,大小为 m 的卷积核在大小为 n 的输入向量上进行操作后所得的卷积特征向量大小会缩

小为 n-m+1。当卷积层数增加的时候,特征向量大小就会以 m-1的速度“坍缩”,这使得更深的神经网络变得不可能,因为在叠加到第个卷积层之后,卷积特征不足 m-1 维。

为了解决这一问题,人们通常采用在输入张量的边界上填充0的方式使得卷积核的中心可以从边界上开始扫描,从而保持卷积操作输入张量和输出张量的大小不变

三、池化层

池化(pooling,如下图)的目的是降低特征空间的维度,只抽取局部最显著的特征同时这些特征出现的具体位置也被忽略。

这样做是符合直觉的:以图像处理维例,我们通常关注的是一个特征是否出现,而不太关心它们出现在哪里;这被称为图像的静态性

通过池化降低空间维度的做法不但减少了计算开销,还使得卷积神经网络对于噪声具有健壮性。

常见的池化类型有最大池化、平均池化等

最大池化是指在池化区域中取卷积特征值最大的作为所得池化特征值

平均池化层是指在池化区域中,取所有卷积特征值的平均作为池化特征值

如上图所示,在二维的卷积操作之后得到一个20×20的卷积特征矩阵,池化区域大小为10×10,这样得到的就是一个4×4的池化特征矩阵。

需要注意的是,与卷积核在重叠的区域进行卷积操作不同,池化区域是互不重叠的

四、卷积神经网络

一般来说,卷积神经网络卷积层池化层非线性激活函数层组成。如左下图:

在图像分类中表现良好的深度往往由许多“卷积层+池化层”的组合堆叠而成,通常多达数十乃至上百层。如右下图:

五、经典网络结构

VGG、InceptionNet、ResNet等是从大规模图像数据集训练的用于图像分类的网络。ImageNet从2010年起每年都举办图像分类的竞赛,为了公平起见,它为每位参赛者提供来自1000个类别的120万张图像。

从如此巨大的数据集后训练出的深度学习模型特征具有非常良好的泛化能力,在迁移学习后,它可以被用于除图像分类之外的其他任务,比如目标检测、图像分割等。

PyTorch 的 torchvision.models 为我们提供了大量的模型实现以及模型的预训练权重文件,其中就包括本节介绍的VGG、ResNet、InceptionNet。

1、VGG网络

VGG网络的特点用 3×3 的卷积核代替先前网络(如AlexNet)的大卷积核

比如,3个步长为1的 3×3 的卷积核和一个 7×7 的卷积核的感受野(receptive field)是一致的,2个步长为1的 3×3 的卷积核和一个 5×5 的卷积核的感受野是一致的。

这样,感受野没有改变,但是却加深了网络的深度,提升了网络的拟合能力

VGG网络的网络结构如图所示:

除此之外,VGG的全 3×3 的卷积核结构减少了参数量:

比如一个 7×7 的卷积核,其参数量为 7×7×C_{in}×C_{out}而具有相同感受野的全 3×3 的卷积核的参数量为 3×3×3×C_{in}×C_{out}

VGG网络和AlexNet的整体结构一致,都是先用5层卷积层提取图像特征,再用3层全连接层作为分类器。

【不过VGG网络的 “层” (在VGG中称为Stage)是由几个 3×3 的卷积层叠加起来的,

而AlexNet是1个大卷积层为一层。】

所以 AlexNet 只有8层,而VGG网络则可多达19层,VGG网络在 ImageNet 的 Top5 准确率达到了92.3%。VGG网络的主要问题是最后的3层全连接层的参数量过于庞大。

2、InceptionNet

InceptionNet(GoodLeNet)主要是由多个Inception模块实现的,Inception模块的基本结构如图所示:

它是一个分支结构,一共有4个分支

第1个分支是进行 1×1 卷积;

第2个分支是先进行 1×1 卷积,然后再进行 3×3 卷积;

第3个分支同样先进行 1×1 卷积,然后再进行 5×5 卷积;

第4个分支先进行 3×3 的最大池化,然后再进行 1×1 卷积。

最后,4个分支计算过的特征映射用沿通道维度拼接的方式组合到一起。

图中的中间层可以分为4列来看,其中第1列的 1×1 的卷积核和中间两列的 3×3、5×5的卷积核主要用于提取特征。

不同大小的卷积核拼接到一起,使得这一结构具有多尺度的表达能力。

右侧3列的1×1的卷积核用于特征降维,可以减少计算量。

第4列最大池化层的使用是因为实验表明池化层往往有比较好的效果。

这样设计的Inception模块具有相当大的宽度,计算量却更低。前面提到了VGG的主要问题是最后3层全连接层参数量过于庞大,在InceptionNet中弃用了这一结构,取而代之的是一层全局平均池化层和单层的全连接层。

这样减少了参数量并且加快了模型的推断速度。

最后,InceptionNet达到了22层,为了让深度如此大的网络能够稳定地训练,Inception在网络中间添加了额外的两个分类损失函数,在训练中这些损失函数相加得到一个最终的损失函数,在验证过程中这两个额外的损失函数不再使用。InceptionNet 在 ImageNet 的 Top5准确率为93.3%,不仅准确率高于VGG网络,推断速度还更甚一筹。

3、ResNet

神经网络越深,对复杂特征的表示能力就越强。但是单纯地增大网络的深度会导致当反向传播算法在传递梯度时,发生梯度消失现象,从而导致网络的训练无效。通过一些权重初始化方法和 Batch Normalization可以解决这一问题。

但是,即使使用了这些方法,网络在达到一定深度之后,模型训练的准确率不会再提升,甚至会开始下降,这种现象称为训练准确率的退化(degradation)问题

退化问题表明,深层模型的训练是非常困难的。

ResNet提出了残差学习的方法,用于解决深度学习模型的退化问题。

假设输入数据是 x ,常规的神经网络是通过几个堆叠的层去学习映射 H(x),而ResNet学习的是映射和输入的残差 F(x)= H(x)- x

相应地,原有的表示就变成 H(x)= F(x)+ x

尽管两种表示是等价的,但实验表明,残差学习更容易训练。ResNet是由几个堆叠的残差模块表示的,可以将残差结构形式化为:

y = F(x,{W_{i}} )+ x

其中 F(x,{W_{i}} )表示要学习的残差映射,ResNet的基本结构如图所示:

图中,残差映射一共有两层,可表示为 y = W₂δ(W₁x + b₁)+ b₂ 

其中 δ 表示 ReLU激活函数。

图中例子一共有两层,ResNet的实现中大量采用了两层或三层的残差结构,而实际这个数量并没有限制,当它仅为一层时,残差结构就相当于一个线性层,所以就没有必要采用单层的残差结构了。

F(x)+ x 在ResNet中通过 shortcut 连接和逐元素相加实现相加后的结果会作为下一个ReLU激活函数的输入。

shortcut 连接相当于对输入x进行恒等映射(indentity map)。在非常极端的情况下,残差F(x)会等于0,而使得整个残差模块仅进行一次恒等映射,这完全是由网络自主决定的,只要它自身认为这是更好的选择。

如果 F(x)和 x 的维度并不相同,那么可以采用如下结构使得其维度相同:

y = F(x,{W_{i}})+ {W_{s}} x 

但是,ResNet的实验表明,使用恒等映射就能够很好地解决退化问题,并且足够简单,计算量足够小。

ResNet的残差结构解决了深度学习模型的退化问题,在ImageNet的数据集上,最深的ResNet模型达到了152层,其Top5准确率达到了95.51%。

六、用PyTorch进行手写数字识别  

torch.utils.data.Datasets 是PyTorch用来表示数据集的类,在本节我们使用 torchvision.datasets.MNIST 构建手写数字数据集。

实例化 datasets对象:

datasets.MNIST能够自动下载数据并保存到本地磁盘,参数train默认为True,用于控制加载的数据集是训练集函数测试集。

使用 len(mnnist),这里调用__len__方法。

使用mnist [ j ] ,调用的是__getitem__。

绘制MNIST手写数字数据集

当我们自己建立数据集时,需要继承Dataset,并且覆写__item__和__len__两个方法。

数据预处理是非常重要的步骤,PyTorch提供了 torchvision.transforms,可用于处理数据及实现数据增强。

在这里我们使用了transforms.ToTensor,它将 PIL Image 或者 numpy.ndarray 类型的数据转换为 Tensor ,并且它会将数据从 [0,255] 映射到 [0,1]。

transforms.Normalize会将数据标准化,将训练数据标准化会加速模型在训练中的收敛。

在使用中,可以利用torchvision.transforms.Compose将多个transforms组合到一起,被包含的transforms会顺序执行。

准备好处理数据的流程后,就可以读取用于训练的数据了,torch.utils.data.DataLoader提供了迭代数据、随机抽取数据、批处理数据、使用multiprocrssing并行化读取数据的功能。

下面定义了函数 imshow ;将数据从标准化的数据中恢复出来;将数据从Tensor类型转换为 ndarray,这样才可以用Matplotlib绘制出来。

将矩阵的维度从 (C,W,H)转化为(W,H,C)。注:C、W、H属于通用符,分别表示 channel、weight、height。

前面展示了使用PyTorch加载数据,处理数据的方法。

下面我们构建用于识别手写数字的神经网络模型。

我们可以直接通过输出nn.Module的对象看到其网络结构

在准备好数据和模型后,我们就可以训练模型了。

下面我们分别定义数据处理和加载流程、模型、优化器、损失函数,以及用准确率评估模型能力。

from torch import optim
from tqdm import tqdm
#数据处理和加载
trans = transforms.Compose([transforms.ToTensor(),transforms.Normalize((0.1307,),(0.3081,))])
mnist_train = datasets.MNIST(root="~",train=True,download=True,transform=trans)
mnist_val = datasets.MNIST(root="~",train=False,download=True,transform=trans)trainloader = DataLoader(mnist_train, batch_size=16, shuffle=True,num_workers=4)
valloader   = DataLoader(mnist_val, batch_size=16, shuffle=True,num_workers=4)#模型
model = MLP()#优化器
optimizer = optim.SGD(model.parameters(),lr=0.01,momentum=0.9)#损失函数
celoss = nn.CrossEntropyLoss()
best_acc = 0#计算准确率
def accuracy(pred,target):pred_label = torch.argmax(pred,1)correct = sum(pred_label == target).to(torch.float)#acc = correct/float(len(pred))return correct,len(pred)acc = {"train":[],"val":[]}
loss_all = {"train":[],"val":[]}for epoch in tqdm(range(10)):#设置为验证模式model.eval()numer_val,denumer_val,loss_tr = 0.,0.,0.with torch.no_grad():for data,target in valloader:output = model(data)loss = celoss(output,target)loss_tr +=loss.datanum,denum = accuracy(output,target)numer_val += numdenumer_val += denum#设置为训练模式model.train()numer_tr,denumer_tr,loss_val = 0.,0.,0.for data,target in trainloader:optimizer.zero_grad()output = model(data)loss = celoss(output,target)loss_val += loss.dataloss.backward()optimizer.step()num,denum = accuracy(output,target)numer_tr +=numdenumer_tr += denumloss_all["train"].append(loss_tr/len(trainloader))loss_all["val"].append(loss_val/len(trainloader))acc["train"].append(numer_tr/denumer_tr)acc["val"].append(numer_val/denumer_val)

将训练数据迭代10个轮次(epoch),并将训练和验证的准确率和损失记录下来。

模型训练迭代后,训练集和验证集的损失迭代图像如图:

模型训练迭代后,训练集和验证集的准确率迭代图如图:

相关文章:

7.卷积神经网络与计算机视觉

计算机视觉是一门研究如何使计算机识别图片的学科,也是深度学习的主要应用领域之一。 在众多深度模型中,卷积神经网络“独领风骚”,已经被称为计算机视觉的主要研究根据之一。 一、卷积神经网络的基本思想 卷积神经网络最初由 Yann LeCun&a…...

Linux|如何管理多个Git身份

摘要 关于如何管理不同项目和多个Git身份。 作为一名通用软件开发者,我经常发现自己在处理各种各样的项目,每个项目都有自己的要求和期望。这包括为个人、工作和客户项目管理不同的Git身份。以下是我组织Git仓库以简化这一过程的方法。 目录组织 我将我的…...

力扣---最长回文子串---二维动态规划

二维动态规划思路: 首先,刚做完这道题:力扣---最长有效括号---动态规划,栈-CSDN博客,所以会有一种冲动,设立g[i],表示以第i位为结尾的最长回文子串长度,然后再遍历一遍取最大长度即可…...

(一)kafka实战——kafka源码编译启动

前言 本节内容是关于kafka消息中间键的源码编译,并通过idea工具实现kafka服务器的启动,使用的kafka源码版本是3.6.1,由于kafka源码是通过gradle编译的,以及服务器是通过scala语言实现,我们要预先安装好gradle编译工具…...

Spring Boot 使用 Redis

1&#xff0c;Spring 是如何集成Redis的&#xff1f; 首先我们要使用jar包 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><dependency><gro…...

火车头通过关键词采集文章的原理

随着互联网信息的爆炸式增长&#xff0c;网站管理员和内容创作者需要不断更新和发布新的文章&#xff0c;以吸引更多的用户和提升网站的排名。而火车头作为一款智能文章采集工具&#xff0c;在这一过程中发挥着重要作用。本文将探讨火车头如何通过关键词采集文章&#xff0c;以…...

Kafka 面试题及参考答案

目录 1. Kafka 的核心特性是什么? 2. Kafka 为什么能够实现高吞吐量? 3. Kafka 的消息丢失是...

【Qt 学习笔记】Day1 | Qt 背景介绍

博客主页&#xff1a;Duck Bro 博客主页系列专栏&#xff1a;Qt 专栏关注博主&#xff0c;后期持续更新系列文章如果有错误感谢请大家批评指出&#xff0c;及时修改感谢大家点赞&#x1f44d;收藏⭐评论✍ Day1 | Qt 背景介绍 文章编号&#xff1a;Qt 学习笔记 / 01 文章目录…...

springboot3.2.4+Mybatis-plus在graalvm21环境下打包exe

springboot3.2.4Mybatis-plus在graalvm21环境下打包exe 前提条件为之前已经能直接打包springboot3.2.4项目了然后在此基础上接入Mybatis-plus&#xff0c;然后能够正常进行打包exe并且执行&#xff0c;参考之前的文章进行打包 核心配置如下 package com.example.demo.config…...

Kubernetes(K8S)学习(二):K8S常用组件

K8S常用组件 一、 Controllers1、ReplicationController(RC)2、ReplicaSet(RS)3、Deployment 二、Labels and Selectors三、Namespace&#xff08;命名空间&#xff09;1、简介2、测试2.1、创建namespace2.2、创建pod 四、Network1、集群内&#xff1a;同一个Pod中的容器通信2、…...

如何使用群晖WebDAV实现固定公网地址同步Zotero文献管理器

文章目录 前言1. Docker 部署 Trfɪk2. 本地访问traefik测试3. Linux 安装cpolar4. 配置Traefik公网访问地址5. 公网远程访问Traefik6. 固定Traefik公网地址 前言 Trfɪk 是一个云原生的新型的 HTTP 反向代理、负载均衡软件&#xff0c;能轻易的部署微服务。它支持多种后端 (D…...

【JavaSE】初识线程,线程与进程的区别

文章目录 ✍线程是什么&#xff1f;✍线程和进程的区别✍线程的创建1.继承 Thread 类2.实现Runnable接口3.匿名内部类4.匿名内部类创建 Runnable ⼦类对象5.lambda 表达式创建 Runnable ⼦类对象 ✍线程是什么&#xff1f; ⼀个线程就是⼀个 “执行流”. 每个线程之间都可以按…...

全国青少年软件编程(Python)等级考试三级考试真题2023年9月——持续更新.....

青少年软件编程&#xff08;Python&#xff09;等级考试试卷&#xff08;三级&#xff09; 分数&#xff1a;100 题数&#xff1a;38 一、单选题(共25题&#xff0c;共50分) 1.有一组数据存在列表中,things[“桌子”,“椅子”,“茶几”,“沙发”,“西瓜”,“苹果”,“草莓”,“…...

react-navigation:

我的仓库地址&#xff1a;https://gitee.com/ruanjianbianjing/bj-hybrid react-navigation&#xff1a; 学习文档&#xff1a;https://reactnavigation.org 安装核心包: npm install react-navigation/native 安装react-navigation/native本身依赖的相关包: react-nativ…...

nginx负载均衡模式

轮询 (Round Robin) 用法&#xff1a;这是Nginx默认的负载均衡策略。每个请求会按顺序分配给upstream中的后端服务器&#xff0c;即按照配置的服务器列表顺序依次分配。 upstream backend {server backend1.example.com;server backend2.example.com;server backend3.example.…...

手写简易操作系统(十七)--编写键盘驱动

前情提要 上一节我们实现了锁与信号量&#xff0c;这一节我们就可以实现键盘驱动了&#xff0c;访问键盘输入的数据也属于临界区资源&#xff0c;所以需要锁的存在。 一、键盘简介 之前的 ps/2 键盘使用的是中断驱动的&#xff0c;在当时&#xff0c;按下键盘就会触发中断&a…...

springboot中基于RestTemplate 类 实现调用第三方API接口【POST版本】

https://blog.csdn.net/Drug_/article/details/135111675 这一篇的升级版 还是先配置文件 package com.init.config;import org.apache.http.conn.ssl.NoopHostnameVerifier; import org.apache.http.conn.ssl.SSLConnectionSocketFactory; import org.apache.http.impl.clie…...

编程器固件修改教程

首发csdn&#xff0c;转载请说明出处&#xff0c;保留一切权益。 关于编程器固件 所谓编程器固件是用编程器读取嵌入式设备的FLASH存储数据生成的文件&#xff0c;类似于直接用工具复制整个硬盘 编程器固件与普通固件的差异 编程器固件是用特定的结构(按顺序、大小)将一些文件系…...

Python从原Excel表中抽出数据存入同一文件的新的Sheet(附源码)

python读取excel数据。Python在从原Excel表中抽出数据并存储到同一文件的新的Sheet中的功能&#xff0c;充分展示了其在数据处理和自动化操作方面的强大能力。这一功能不仅简化了数据迁移的过程&#xff0c;还提高了数据处理的效率&#xff0c;为数据分析和管理工作带来了极大的…...

计算机网络实验六:路由信息协议RIP

目录 6 实验六:路由信息协议RIP 6.1 实验目的 6.2 实验步骤 6.2.1 构建网络拓扑、配置各网络设备 6.2.2 网络功能验证测试 6.3 实验总结 6 实验六:路由信息协议RIP 6.1 实验目的 (1)学习RIP协议的工作原理和特点 (2)学习如何选择最短路径路由。 (3)进一步掌握…...

.Net框架,除了EF还有很多很多......

文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...

线程与协程

1. 线程与协程 1.1. “函数调用级别”的切换、上下文切换 1. 函数调用级别的切换 “函数调用级别的切换”是指&#xff1a;像函数调用/返回一样轻量地完成任务切换。 举例说明&#xff1a; 当你在程序中写一个函数调用&#xff1a; funcA() 然后 funcA 执行完后返回&…...

pam_env.so模块配置解析

在PAM&#xff08;Pluggable Authentication Modules&#xff09;配置中&#xff0c; /etc/pam.d/su 文件相关配置含义如下&#xff1a; 配置解析 auth required pam_env.so1. 字段分解 字段值说明模块类型auth认证类模块&#xff0c;负责验证用户身份&am…...

STM32F4基本定时器使用和原理详解

STM32F4基本定时器使用和原理详解 前言如何确定定时器挂载在哪条时钟线上配置及使用方法参数配置PrescalerCounter ModeCounter Periodauto-reload preloadTrigger Event Selection 中断配置生成的代码及使用方法初始化代码基本定时器触发DCA或者ADC的代码讲解中断代码定时启动…...

Module Federation 和 Native Federation 的比较

前言 Module Federation 是 Webpack 5 引入的微前端架构方案&#xff0c;允许不同独立构建的应用在运行时动态共享模块。 Native Federation 是 Angular 官方基于 Module Federation 理念实现的专为 Angular 优化的微前端方案。 概念解析 Module Federation (模块联邦) Modul…...

DBAPI如何优雅的获取单条数据

API如何优雅的获取单条数据 案例一 对于查询类API&#xff0c;查询的是单条数据&#xff0c;比如根据主键ID查询用户信息&#xff0c;sql如下&#xff1a; select id, name, age from user where id #{id}API默认返回的数据格式是多条的&#xff0c;如下&#xff1a; {&qu…...

ardupilot 开发环境eclipse 中import 缺少C++

目录 文章目录 目录摘要1.修复过程摘要 本节主要解决ardupilot 开发环境eclipse 中import 缺少C++,无法导入ardupilot代码,会引起查看不方便的问题。如下图所示 1.修复过程 0.安装ubuntu 软件中自带的eclipse 1.打开eclipse—Help—install new software 2.在 Work with中…...

微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据

微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据 Power Query 具有大量专门帮助您清理和准备数据以供分析的功能。 您将了解如何简化复杂模型、更改数据类型、重命名对象和透视数据。 您还将了解如何分析列&#xff0c;以便知晓哪些列包含有价值的数据&#xff0c;…...

Java线上CPU飙高问题排查全指南

一、引言 在Java应用的线上运行环境中&#xff0c;CPU飙高是一个常见且棘手的性能问题。当系统出现CPU飙高时&#xff0c;通常会导致应用响应缓慢&#xff0c;甚至服务不可用&#xff0c;严重影响用户体验和业务运行。因此&#xff0c;掌握一套科学有效的CPU飙高问题排查方法&…...

Netty从入门到进阶(二)

二、Netty入门 1. 概述 1.1 Netty是什么 Netty is an asynchronous event-driven network application framework for rapid development of maintainable high performance protocol servers & clients. Netty是一个异步的、基于事件驱动的网络应用框架&#xff0c;用于…...