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

DERT目标检测—End-to-End Object Detection with Transformers

DERT:使用Transformer的端到端目标检测

论文题目:End-to-End Object Detection with Transformers
官方代码:https://github.com/facebookresearch/detr

论文题目中包括的一个创新点End to End(端到端的方法)简单的理解就是没有使用到NMS等后处理操作来处理生成的多个重复的框

简单的端到端的目标检测系统

引言与概述

We present a new method that views object detection as a
direct set prediction problem.

将目标检测任务直接看成是集合预测的问题。

  1. 提出了一个全局的二分图匹配的损失函数:a set-based global loss that forces unique predictions via bipartite matching
  2. 结合了Transformer结构,在解码器的部分进行并行的出框。

在引言的部分论文中简单概括了之前的目标检测所用到的一些方法。

  • 双阶段目标检测的算法: FasterRcnn
  • 单阶段目标检测的算法:Yolo
  • 基于中心点进行生成的算法:CenterNet

在这里插入图片描述

在没有深入的学习目标检测网络具体的细节之前。对这一个过程进行一.个直观的信息描述,

  1. 首先经过一个CNN网络提取一部分的特征得到对应的特征图,并将得到的特征进行拉直处理。准备送入之后的Transformer结构中去。

  2. 将拉直之后的token送入编码器的结构部分,(endcode去进一步学习全局的特征信息。为我们decode出预测框的部分做铺垫。)使用endcode可以认为是将图片中的每一个点和其他的点之间就有交互信息了。就可以知道大概那一块是那个物体。

  3. 对同一个物体就出一个检测框的结果。通过query和我们的特征就可以确定要出多少检测框(论文中固定出框数为100)

  4. 最后一步就是我得出的这100个框,如何和我的Ground Truth框之间做一个关联匹配问题呢 计算loss 没有匹配的框则会标记为没有物体。

目标检测相关工作

Most modern object detection methods make predictions relative to some ini-tial guesses. Two-stage detectors [37,5] predict boxes w.r.t. proposals, whereas single-stage methods make predictions w.r.t. anchors [23] or a grid of possible object centers [53,46]. Recent work [52] demonstrate that the final performance of these systems heavily depends on the exact way these initial guesses are set.

在之前的目标检测的相关工作中作者就提到了,之前相关的目标检测的工作,取决于我们的先验猜测,双阶段的候选框proposals,单阶段的anchors于 centernet的中心点检测取决于,中心点选取的位置。

从而提出了一种新的方法,基于集合的方式来做这个目标检测的任务。

目标函数

DETR infers a fixed-size set of N predictions, in a single pass through the decoder, where N is set to be significantly larger than the typical number of objects in an image N=100

二分图匹配问题+匈牙利算法。找到一个唯一解使得最后可以完成最后的一个分配。(代价矩阵的构建就可以看成是,将100个预测框和Ground Truth框之间进行二分图匹配

σ ^ = arg ⁡ min ⁡ σ ∈ S N ∑ i N L match  ( y i , y ^ σ ( i ) ) \hat{\sigma}=\underset{\sigma \in \mathfrak{S}_{N}}{\arg \min } \sum_{i}^{N} \mathcal{L}_{\text {match }}\left(y_{i}, \hat{y}_{\sigma(i)}\right) σ^=σSNargminiNLmatch (yi,y^σ(i))

最后匹配完成之后就可以和之后的目标检测差不多的损失函数。

L Hungarian  ( y , y ^ ) = ∑ i = 1 N [ − log ⁡ p ^ σ ^ ( i ) ( c i ) + 1 { c i ≠ ∅ } L box  ( b i , b ^ σ ^ ( i ) ) ] \mathcal{L}_{\text {Hungarian }}(y, \hat{y})=\sum_{i=1}^{N}\left[-\log \hat{p}_{\hat{\sigma}(i)}\left(c_{i}\right)+\mathbb{1}_{\left\{c_{i} \neq \varnothing\right\}} \mathcal{L}_{\text {box }}\left(b_{i}, \hat{b}_{\hat{\sigma}}(i)\right)\right] LHungarian (y,y^)=i=1N[logp^σ^(i)(ci)+1{ci=}Lbox (bi,b^σ^(i))]

简单的看也就是分类损失加上回归损失的表达形式。

在这里插入图片描述
这一个更为详细的图里面就引出了另外的一个十分重要的概念object Queries(是一个可学习的参数在经过学习之后就可以确定出哪些查询会对应哪些目标,从而避免重复的操作。

连接一个分类头完成最终的结果的一个预测。论文中给出的简化的版本代码编写。

import torch
from torch import nn
from torchvision.models import resnet50
class DETR(nn.Module):
def __init__(self, num_classes, hidden_dim, nheads,
num_encoder_layers, num_decoder_layers):
super().__init__()
# We take only convolutional layers from ResNet-50 model
self.backbone=nn.Sequential(*list(resnet50(pretrained=True).children())[:-2])
self.conv = nn.Conv2d(2048, hidden_dim, 1)self.transformer = nn.Transformer(hidden_dim, nheads,num_encoder_layers, num_decoder_layers)self.linear_class = nn.Linear(hidden_dim, num_classes + 1)self.linear_bbox = nn.Linear(hidden_dim, 4)self.query_pos = nn.Parameter(torch.rand(100, hidden_dim))self.row_embed = nn.Parameter(torch.rand(50, hidden_dim // 2))self.col_embed = nn.Parameter(torch.rand(50, hidden_dim // 2))def forward(self, inputs):x = self.backbone(inputs)h = self.conv(x)H, W = h.shape[-2:]
pos = torch.cat([self.col_embed[:W].unsqueeze(0).repeat(H, 1, 1),self.row_embed[:H].unsqueeze(1).repeat(1, W, 1),], dim=-1).flatten(0, 1).unsqueeze(1)h = self.transformer(pos + h.flatten(2).permute(2, 0, 1),self.query_pos.unsqueeze(1))return self.linear_class(h), self.linear_bbox(h).sigmoid()detr = DETR(num_classes=91, hidden_dim=256, nheads=8, num_encoder_layers=6, num_decoder_layers=6)detr.eval()inputs = torch.randn(1, 3, 800, 1200)logits, bboxes = detr(inputs)

网络模型结构

在这里插入图片描述

主干网络与预处理的部分

根据论文官方的代码对模型的结构进行说明:

  1. 输入时一个800 x 1066的三通道图片,将其输入到主干网络提取器ResNet50中进行特征的提取 得到的特征图大小是 25x34(下采样了32倍) 将通道数拓展为2048。

  2. 将得到的特征图经过一个1x1的卷积层输入的通道数是2048 输出的通道数是 256得到了**[ 25 34 256]的结构**

  3. 将最后的两个维度进行一个展平的操作步骤得到了 [850 ,256]的结构

在这里插入图片描述

其中的850就是我们后面使用的Transformer中token的个数,256即为特征向量的长度。

Transformer结构部分

论文中也给出了一个改进之后的Transformer结构。结构之前的Transfomer结构给出类比的结果。

在这里插入图片描述
在标准的Transformer中位置编码只作用在输入的位置处,并且只作用一次。而在DERT的Transformer中位置编码是在每一个编码器,和解码器的部分都需要操作一次的。

学习这个网络模型的难点就在需要注意,模型之间的连线来确定好各个Q K V是通过哪些变量的计算来生成的(结合源码)

在这里插入图片描述

解读细节

Encoder完成的任务得到各个目标的注意力结果,准备好特征,等解码器来选

一组参考点的编码器自注意力。 编码器能够分离各个实例。 使用基线 DETR 模型对验证集图像进行预测。

在这里插入图片描述

在论文的结构图中解码器的部分也需要注意一些实现的细节步骤。

在这里插入图片描述

解码器部分虽然用到了两个自注意力机制,但是第一部分用到的是多头自注意力机制,而第二部分用到的则是,多头注意力机制 原因第二部分的Q来自下面一层的一个输出,而K和V的部分则来自编码器的输出,因此不能称为自注意力机制。

解码器的第一部分:个人感觉可以简单的理解为通过我们初始化的Object Queries查询向量 这一个可以学习的参数来整合查询的过程,告诉第二部分,每一个查询向量应该对应那一部分的区域信息。

将它作为一个查询向量Q输入到下一层和编码器中包括的信息(如上图所示)进行整合 最后进行分类和回归得到最后的结果。得到的长度为100

损失函数

  1. 从100个预测框中,找出和真实标注框所匹配的N个框(图中对应的是两个框),也就是说我们在训练集样本中标注了几个框,就需要在那100个得到的预测框中筛选出几个框(N)来进行匹配

在这里插入图片描述

我们需要做的任务就是向代价矩阵中进行填值使得匹配的结果最为合适

− 1 { c i ≠ ∅ } p ^ σ ( i ) ( c i ) + 1 { c i ≠ ∅ } L box  ( b i , b ^ σ ( i ) ) . -\mathbb{1}_{\left\{c_{i} \neq \varnothing\right\}} \hat{p}_{\sigma(i)}\left(c_{i}\right)+\mathbb{1}_{\left\{c_{i} \neq \varnothing\right\}} \mathcal{L}_{\text {box }}\left(b_{i}, \hat{b}_{\sigma(i)}\right) . 1{ci=}p^σ(i)(ci)+1{ci=}Lbox (bi,b^σ(i)).
在这里插入图片描述
我们首先看公式的前半部分:即为对应的类别损失:Class Cost

− 1 { c i ≠ ∅ } p ^ σ ( i ) ( c i ) -\mathbb{1}_{\left\{c_{i} \neq \varnothing\right\}} \hat{p}_{\sigma(i)}\left(c_{i}\right) 1{ci=}p^σ(i)(ci)

在这里插入图片描述

  • 首先要提取出GT中的坐标框对应的类别信息(第一张图有两个框,第二张图中有四个框。值为类别编号

  • 对应两个图片给出的200个预测框的值(2N)我们将其进行拼接,计算出包含真实类别的概率值。

在这里插入图片描述
在计算的时候Cost class这个张量需要加符号用来计算损失函数的值

  • 第二部分我们对应的是边界框回归的一个损失。

1 { c i ≠ ∅ } L box  ( b i , b ^ σ ( i ) ) \mathbb{1}_{\left\{c_{i} \neq \varnothing\right\}} \mathcal{L}_{\text {box }}\left(b_{i}, \hat{b}_{\sigma(i)}\right) 1{ci=}Lbox (bi,b^σ(i))

论文中关于回归损失函数的描述信息为:
Bounding box loss. The second part of the matching cost and the Hungarian
loss is Lbox(·) that scores the bounding boxes. Unlike many detectors that do box
predictions as a ∆ w.r.t. some initial guesses, we make box predictions directly.
While such approach simplify the implementation it poses an issue with relative
scaling of the loss. The most commonly-used 1 loss will have different scales for
small and large boxes even if their relative errors are similar. To mitigate this
issue we use a linear combination of the 1 loss and the generalized IoU loss [38]
Liou(·, ·) that is scale-invariant. Overall, our box loss is Lbox(bi, ˆbσ(i)) defined as
λiouLiou(bi, ˆbσ(i)) + λL1||bi − ˆbσ(i)||1 where λiou, λL1 ∈ R are hyperparameters.
These two losses are normalized by the number of objects inside the batch.

总结一下:也就如果和之前一样使用常规的L1损失来作为回归损失,可能会导致,大小检测框的相对计算一致。因此在这个基础上引出了GIOU损失与L1损失相结合的最终回归损失部分。

λ iou  L iou  ( b i , b ^ σ ( i ) ) + λ L 1 ∥ b i − b ^ σ ( i ) ∥ 1 \lambda_{\text {iou }} \mathcal{L}_{\text {iou }}\left(b_{i}, \hat{b}_{\sigma(i)}\right)+\lambda_{\mathrm{L} 1}\left\|b_{i}-\hat{b}_{\sigma(i)}\right\|_{1} λiou Liou (bi,b^σ(i))+λL1 bib^σ(i) 1

在这里插入图片描述

match操作

− 1 { c i ≠ ∅ } p ^ σ ( i ) ( c i ) + 1 { c i ≠ ∅ } L box  ( b i , b ^ σ ( i ) ) -\mathbb{1}_{\left\{c_{i} \neq \varnothing\right\}} \hat{p}_{\sigma(i)}\left(c_{i}\right)+\mathbb{1}_{\left\{c_{i} \neq \varnothing\right\}} \mathcal{L}_{\text {box }}\left(b_{i}, \hat{b}_{\sigma(i)}\right) 1{ci=}p^σ(i)(ci)+1{ci=}Lbox (bi,b^σ(i))

L box  ( ⋅ ) = λ iou  L iou  ( b i , b ^ σ ( i ) ) + λ L1  ∥ b i − b ^ σ ( i ) ∥ 1 \mathcal{L}_{\text {box }}(\cdot)=\lambda_{\text {iou }} \mathcal{L}_{\text {iou }}\left(b_{i}, \hat{b}_{\sigma(i)}\right)+\lambda_{\text {L1 }}\left\|b_{i}-\hat{b}_{\sigma(i)}\right\|_{1} Lbox ()=λiou Liou (bi,b^σ(i))+λL1  bib^σ(i) 1

  • 我们对应代码部分实际的计算步骤就是:cost = -cost_class + 5 × cost_bbor - 2 × cost_GIoUs

  • 把计算得到的结果填写入矩阵之中,就可以得到两个图片总的代价矩阵,我们在使用split操作将其分开得到两个代价矩阵的结果。

(分别进行匈牙利匹配)

在这里插入图片描述

计算损失并反向传播

在这个地方论文中提出了一个新的损失函数。—匈牙利损失函数。使用筛选出的预测框与真实标注框计算损失。

L Hungarian  ( y , y ^ ) = ∑ i = 1 N [ − log ⁡ p ^ σ ^ ( i ) ( c i ) + 1 { c i ≠ ∅ } L box  ( b i , b ^ σ ^ ( i ) ) ] \mathcal{L}_{\text {Hungarian }}(y, \hat{y})=\sum_{i=1}^{N}\left[-\log \hat{p}_{\hat{\sigma}(i)}\left(c_{i}\right)+\mathbb{1}_{\left\{c_{i} \neq \varnothing\right\}} \mathcal{L}_{\text {box }}\left(b_{i}, \hat{b}_{\hat{\sigma}}(i)\right)\right] LHungarian (y,y^)=i=1N[logp^σ^(i)(ci)+1{ci=}Lbox (bi,b^σ^(i))]

和之前代价矩阵计算所用的那个函数其实差不多(类别损失+坐标损失)。区别主要在于一下几点。

  1. 这里在计算类别损失的时候我们是使用N也就是100个预测框来参与运算。而不是只计算标注类别的损失。
  2. 加了 log也就是使用交叉熵损失函数(计算平均值)
  3. 中间层的输出也是参与了损失计算的。(主网络损失+网络中间层的损失)

在这里插入图片描述

用预测结果与真实的结果计算交叉熵损失(所有的框 92代表背景)

在回归损失中,公式也给出了只使用真实的标注框不含背景。

1 { c i ≠ ∅ } L box  ( b i , b ^ σ ^ ( i ) ) \mathbb{1}_{\left\{c_{i} \neq \varnothing\right\}} \mathcal{L}_{\text {box }}\left(b_{i}, \hat{b}_{\hat{\sigma}}(i)\right) 1{ci=}Lbox (bi,b^σ^(i))

最后就可以得到最终的结果了:结合反向传播对整个网络进行训练和优化

L Hungarian  ( y , y ^ ) = ∑ i = 1 N [ − log ⁡ p ^ σ ^ ( i ) ( c i ) + 1 { c i ≠ ∅ } L box  ( b i , b ^ σ ^ ( i ) ) ] \mathcal{L}_{\text {Hungarian }}(y, \hat{y})=\sum_{i=1}^{N}\left[-\log \hat{p}_{\hat{\sigma}(i)}\left(c_{i}\right)+\mathbb{1}_{\left\{c_{i} \neq \varnothing\right\}} \mathcal{L}_{\text {box }}\left(b_{i}, \hat{b}_{\hat{\sigma}}(i)\right)\right] LHungarian (y,y^)=i=1N[logp^σ^(i)(ci)+1{ci=}Lbox (bi,b^σ^(i))]

相关文章:

DERT目标检测—End-to-End Object Detection with Transformers

DERT:使用Transformer的端到端目标检测 论文题目:End-to-End Object Detection with Transformers 官方代码:https://github.com/facebookresearch/detr 论文题目中包括的一个创新点End to End(端到端的方法)简单的理解就是没有使…...

软件后端开发速度慢的科技公司老板有没有思考如何破局

最近接到两个科技公司咨询,说是他们公司后端开发速度太慢,前端程序员老等着,后端程序员拖了项目进度。 这种问题不只他们公司,在软件外包公司中,有一部分项目甲方客户要得急,以至于要求软件开发要快&#…...

开放原子超级链内核XuperCore可搭建区块链

区块链是一种分布式数据库技术,它以块的形式存储数据,并使用密码学方法保证数据的安全性和完整性。 每个块包含一定数量的交易信息,并通过加密链接到前一个块,形成一个不断增长的链条。 这种设计使得数据在网络中无法被篡改,因为任何尝试修改一个块的数据都会破坏整个链的…...

【Qualcomm】高通SNPE框架的使用 | 原始模型转换为量化的DLC文件 | 在Android的CPU端运行模型

目录 ① 激活snpe环境 ② 设置环境变量 ③ 模型转换 ④ run on Android 首先,默认SNPE工具已经下载并且Setup相关工作均已完成。同时,拥有原始模型文件,本文使用的模型文件为SNPE 框架示例的inception_v3_2016_08_28_frozen.pb文件。imag…...

C++map与set

文章目录 前言一、map和set基础知识二、set与map使用示例1.set去重操作2.map字典统计 总结 前言 本章主要介绍map和set的基本知识与用法。 一、map和set基础知识 map与set属于STL的一部分,他们底层都是是同红黑树来实现的。 ①set常见用途是去重 ,set不…...

随手记:前端一些定位bug的方法

有时候接到bug很烦躁,不管是任何环境的bug,看到都影响心情,随后记总结一下查看bug的思路,在摸不着头脑的时候或者焦虑的时候,可以静下心来顺着思路思考和排查bug可能产生的原因 1.接到bug,最重要的是&am…...

【深度学习】03-神经网络2-1损失函数

在神经网络中,不同任务类型(如多分类、二分类、回归)需要使用不同的损失函数来衡量模型预测和真实值之间的差异。选择合适的损失函数对于模型的性能至关重要。 这里的是API 的注意⚠️,但是在真实的公式中,目标值一定是…...

Python爬虫APP程序:构建智能化数据抓取工具

在信息爆炸的时代,数据的价值日益凸显。Python作为一种强大的编程语言,与其丰富的库一起,为爬虫程序的开发提供了得天独厚的优势。本文将探讨如何使用Python构建一个爬虫APP程序,以及其背后的思维逻辑。 什么是Python爬虫APP程序&…...

第五部分:2---中断与信号

目录 操作系统如何得知哪个外部资源就绪? 什么是中断机制? CPU引脚和中断号的关系: 中断向量表: 信号和中断的关系: 操作系统如何得知哪个外部资源就绪? 操作系统并不会主动轮询所有外设来查看哪些资源…...

梧桐数据库(WuTongDB):SQL Server Query Optimizer 简介

SQL Server Query Optimizer 是 SQL Server 数据库引擎的核心组件之一,负责生成查询执行计划,以优化 SQL 查询的执行性能。它的目标是根据查询的逻辑结构和底层数据的统计信息,选择出最优的查询执行方案。SQL Server Query Optimizer 采用基于…...

Scrapy框架介绍

一、什么是Scrapy 是一款快速而强大的web爬虫框架,基于Twusted的异步处理框架 Twisted是事件驱动的 Scrapy是由Python实现的爬虫框架 ① 架构清晰 ②可扩展性强 ③可以灵活完成需求 二、核心组件 Scrapy Engine(引擎):Scrapy框架…...

Facebook对现代社交互动的影响

自2004年成立以来,Facebook已经成为全球最大的社交媒体平台之一,改变了人们的交流方式和社交互动模式。作为一个数字平台,Facebook不仅为用户提供了分享生活点滴的空间,也深刻影响了现代社交互动的各个方面。本文将探讨Facebook如…...

Java项目运维有哪些内容?

Java项目运维的内容主要包括环境准备、部署Java应用、配置和优化、安全配置、以及数据安全保护措施,服务的运行和资源动态监控管理。‌ ‌1,环境准备‌:这包括选择适合运行Java和Tomcat的操作系统,如Ubuntu、CentOS等Linux发行版…...

【学习笔记】MIPI

MIPI介绍 MIPI是由ARM、Nokia、ST、IT等公司成立的一个联盟,旨在把手机内部的接口如存储接口,显示接口,射频/基带接口等标准化,减少兼容性问题并简化设计。 MIPI联盟通过不同的工作组,分别定义一系列手机内部的接口标…...

QMake 脚本知识点记录

1. 简单工程配置 QT core guigreaterThan(QT_MAJOR_VERSION, 4): QT widgetsCONFIG c11CONFIG debug # debug/release HEADERS demo.h # 头文件 列表 SOURCES main.cpp demo.cpp # 源文件 列表 FORMS mainwin.ui # 窗体 列表…...

Kubernetes配置管理(kubernetes)

实验环境: 在所有节点上拉取镜像;然后把资源清单拉取到第一个master节点上; 同步会话,导入镜像: configmap/secret 配置文件的映射 变量: 基于valuefrom的方式 cm--》pod 特点:变量的名称可…...

macOS与Ubuntu虚拟机使用SSH文件互传

1.ubuntu配置: 安装openssh服务: sudo apt-get install openssh-server -y 查看服务启动状态: systemctl status ssh 2.macOS使用scp连接ubuntu并发送文件 查看ubuntu IP : ifconfigmacOS终端连接ubuntu : sc...

defineExpose 显式导出子组件方法

当父组件调用子组件的script setup中的方法时&#xff0c;必须显式导出该方法。因为 script setup 中定义的变量和方法默认是局部的&#xff0c;只有显式导出后&#xff0c;父组件才能访问这些方法。 //父组件-Parent <template><el-button type"primary" …...

vue 解决列表界面进入明细返回查询条件不变

在Vue中&#xff0c;如果你遇到了列表界面进入详情页面后返回查询条件不变的问题&#xff0c;可能是因为你没有正确地管理状态或者是使用了不合适的组件间通信方式。 解决方案通常涉及到以下几点&#xff1a; 使用Vuex来管理状态&#xff0c;确保查询条件保存在全局状态树中&…...

华为NAT ALG技术的实现

双向NAT技术&#xff1a;经过防火墙的2报文源IP地址和目的IP地址都同时被转换&#xff0c;外网发送报文给内网服务器&#xff0c;先转换目的IP地址&#xff0c;然后符合安全策略后&#xff0c;在替换源IP地址&#xff0c;然后将记录写入防火墙会话表&#xff0c;并发送出报文&a…...

基于距离变化能量开销动态调整的WSN低功耗拓扑控制开销算法matlab仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.算法仿真参数 5.算法理论概述 6.参考文献 7.完整程序 1.程序功能描述 通过动态调整节点通信的能量开销&#xff0c;平衡网络负载&#xff0c;延长WSN生命周期。具体通过建立基于距离的能量消耗模型&am…...

【Oracle APEX开发小技巧12】

有如下需求&#xff1a; 有一个问题反馈页面&#xff0c;要实现在apex页面展示能直观看到反馈时间超过7天未处理的数据&#xff0c;方便管理员及时处理反馈。 我的方法&#xff1a;直接将逻辑写在SQL中&#xff0c;这样可以直接在页面展示 完整代码&#xff1a; SELECTSF.FE…...

通过Wrangler CLI在worker中创建数据库和表

官方使用文档&#xff1a;Getting started Cloudflare D1 docs 创建数据库 在命令行中执行完成之后&#xff0c;会在本地和远程创建数据库&#xff1a; npx wranglerlatest d1 create prod-d1-tutorial 在cf中就可以看到数据库&#xff1a; 现在&#xff0c;您的Cloudfla…...

【Linux】C语言执行shell指令

在C语言中执行Shell指令 在C语言中&#xff0c;有几种方法可以执行Shell指令&#xff1a; 1. 使用system()函数 这是最简单的方法&#xff0c;包含在stdlib.h头文件中&#xff1a; #include <stdlib.h>int main() {system("ls -l"); // 执行ls -l命令retu…...

大型活动交通拥堵治理的视觉算法应用

大型活动下智慧交通的视觉分析应用 一、背景与挑战 大型活动&#xff08;如演唱会、马拉松赛事、高考中考等&#xff09;期间&#xff0c;城市交通面临瞬时人流车流激增、传统摄像头模糊、交通拥堵识别滞后等问题。以演唱会为例&#xff0c;暖城商圈曾因观众集中离场导致周边…...

Java如何权衡是使用无序的数组还是有序的数组

在 Java 中,选择有序数组还是无序数组取决于具体场景的性能需求与操作特点。以下是关键权衡因素及决策指南: ⚖️ 核心权衡维度 维度有序数组无序数组查询性能二分查找 O(log n) ✅线性扫描 O(n) ❌插入/删除需移位维护顺序 O(n) ❌直接操作尾部 O(1) ✅内存开销与无序数组相…...

如何在看板中体现优先级变化

在看板中有效体现优先级变化的关键措施包括&#xff1a;采用颜色或标签标识优先级、设置任务排序规则、使用独立的优先级列或泳道、结合自动化规则同步优先级变化、建立定期的优先级审查流程。其中&#xff0c;设置任务排序规则尤其重要&#xff0c;因为它让看板视觉上直观地体…...

CMake 从 GitHub 下载第三方库并使用

有时我们希望直接使用 GitHub 上的开源库,而不想手动下载、编译和安装。 可以利用 CMake 提供的 FetchContent 模块来实现自动下载、构建和链接第三方库。 FetchContent 命令官方文档✅ 示例代码 我们将以 fmt 这个流行的格式化库为例,演示如何: 使用 FetchContent 从 GitH…...

Hive 存储格式深度解析:从 TextFile 到 ORC,如何选对数据存储方案?

在大数据处理领域&#xff0c;Hive 作为 Hadoop 生态中重要的数据仓库工具&#xff0c;其存储格式的选择直接影响数据存储成本、查询效率和计算资源消耗。面对 TextFile、SequenceFile、Parquet、RCFile、ORC 等多种存储格式&#xff0c;很多开发者常常陷入选择困境。本文将从底…...

【无标题】路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论

路径问题的革命性重构&#xff1a;基于二维拓扑收缩色动力学模型的零点隧穿理论 一、传统路径模型的根本缺陷 在经典正方形路径问题中&#xff08;图1&#xff09;&#xff1a; mermaid graph LR A((A)) --- B((B)) B --- C((C)) C --- D((D)) D --- A A -.- C[无直接路径] B -…...