YOLOv10 超详细解析 | 网络结构、训练策略、论文解读

网络结构

1. Backbone

在这里插入图片描述

2. Head

在这里插入图片描述

3. 说明

  • 网络结构按 YOLOv10m 绘制,不同 scale 的模型在结构上略有不同,而不是像 YOLOv8 一样仅调整 depth 和 width。
  • Head 有部分后续计算与 YOLOv8 完全相同,上图省略,具体请看此文。
  • YOLOv10 整体的网络结构与 YOLOv8 相同,在一些细节模块上有所改进,查看具体的模块计算方式、优化策略跳转模型优化部分。

4. Predict Postprocess

  首先需要说明的是,网络实际包含两个 Head(结构相同、参数不同),分别对应了 One-to-many Head 和 One-to-one Head,在训练时两个 Head 同时参与,而推理预测时只需要 One-to-one Head。

class v10Detect(Detect):def __init__(self, nc=80, ch=()):super().__init__(nc, ch)c3 = max(ch[0], min(self.nc, 100))  # channelsself.cv3 = ...self.one2one_cv2 = copy.deepcopy(self.cv2)self.one2one_cv3 = copy.deepcopy(self.cv3)

后处理具体流程:

  1. one2one [1, 84, 6300] → \to boxes [1, 6300, 4] + scores [1, 6300, 80]
  2. 根据每个 Anchor 最高的分类得分 max_scores [1,6300] 排序,取前 max_det=300 个 Anchor
  3. 将这 300 个 Anchor 的 80 类分类得分再做一次排序,取前 max_det=300

  此过程可以看作直接将所有 scores 中得分较高的 300 个结果作为检测结果,代码中使用两次 topk 可能是效率更高。 由于 scores 计算使用的是 Sigmoid 而非 Softmax,这个后处理过程就可能会得到两个 Anchor 相同的框(即框的位置大小也都相同),但类别不同的结果。

  由于后处理的不同,作者建议在预测中可以自由调节置信度阈值,或者设较小的阈值来提升对小目标、远处目标的检测效果,并且可以看出调节阈值对于后处理速度并无影响,只是从这 300 个结果中用不同的阈值筛选出最终结果而已。

# step 1
preds = preds["one2one"][0]  	# [1,84,6300]
preds.transpose(-1, -2)  		# [1,6300,84]
boxes, scores = preds.split([4, nc], dim=-1)  # [1,6300,4], [1,6300,80]
# step 2
max_scores = scores.amax(dim=-1)  # [1,6300]
max_scores, index = torch.topk(max_scores, max_det, axis=-1)  # [1,300], [1,300]
index = index.unsqueeze(-1)
boxes = torch.gather(boxes, dim=1, index=index.repeat(1, 1, boxes.shape[-1]))  		# [1,300,4]
scores = torch.gather(scores, dim=1, index=index.repeat(1, 1, scores.shape[-1]))	# [1,300,80]
# step 3
scores, index = torch.topk(scores.flatten(1), max_det, axis=-1)
labels = index % nc
index = index // nc
boxes = boxes.gather(dim=1, index=index.unsqueeze(-1).repeat(1, 1, boxes.shape[-1]))
return boxes, scores, labels

Train

  YOLOv10 最大的特点就是在预测阶段不需要 NMS,而这个功能正是通过训练来实现的。
  YOLOv10 在训练中会对 One-to-many Head 和 One-to-one Head 两个头的输出都计算损失,而损失函数与 YOLOv8 相同。具体看下面代码,仅仅是 tal_topk 参数设置不同,也就是在参与损失计算的正样本的选择上有所不同。

class v10DetectLoss:def __init__(self, model):self.one2many = v8DetectionLoss(model, tal_topk=10)self.one2one = v8DetectionLoss(model, tal_topk=1)def __call__(self, preds, batch):one2many = preds["one2many"]loss_one2many = self.one2many(one2many, batch)one2one = preds["one2one"]loss_one2one = self.one2one(one2one, batch)return loss_one2many[0] + loss_one2one[0], torch.cat((loss_one2many[1], loss_one2one[1]))

  YOLOv8 的损失计算代码较多,关于代码逐句解析请看此文。本文将以尽可能简洁明了的方式说明损失的计算流程。

1. 前期准备

  在训练阶段使用的网络输出为 Head 的输出 x 1 , x 2 , x 3 x_1,x_2,x_3 x1,x2,x3,并将其分离为分类得分 pred_scores [b, a, 80]、原始检测框 pred_dist [b, a, 16] 以及解码后的检测框 pred_bboxes [b, a, 4]。对于标签也会做简单处理,得到分类标签 gt_labels [b, n, 1] 和目标框标签 gt_bboxes [b, n, 4]
b:BatchSize
a:Anchors
80:分类数量
4:xyxy
n:该 Batch 中的最大实例数,实例数不足的图像会填充0,方便后续矩阵运算

2. 正样本选择与指标计算

  选择 Anchor 坐标在 gt_bboxes 内部的输出来计算指标:

overlaps = CIoU(gt_boxes, pd_boxes)
align_metric = bbox_scores.pow(self.alpha) * overlaps.pow(self.beta)

此处 bbox_scores 仅保留 Anchor 所在 gt_bboxes 对应类别的得分,alpha=0.5, beta=6。对应 YOLOv10 论文中的公式( s s s 代表 Anchor 是否在实例内部):
m ( α , β ) = s ⋅ p α ⋅ I o U ( b ^ , b ) β m(\alpha,\beta) = s·p^{\alpha} · \mathrm{IoU}(\hat{b}, b)^\beta m(α,β)=spαIoU(b^,b)β

  选出每个 gt 目标中 align_metric 前 10 / 1 的输出,如果同一个 Anchor 的输出入选多个 gt 目标的 Top10 / 1,选择 overlaps 即 IoU 较高的。

  通俗来说对于每个实例,都会选择一些与其匹配得分较高的输出作为正样本,但对于一个 Anchor 的输出同时只能作为一个目标的正样本。而 One-to-many Head 和 One-to-one Head 的不同之处就在于一个会选择多个(Top 10)得分较高的作为正样本,一个只选择得分最高的作为正样本。

3. target scores

t j = u ∗ ⋅ m j m ∗ t_j = u^*·\frac{m_j}{m^*} tj=ummj
  其中 t j t_j tj 代表某个实例的 j j j 号正样本的 target_score u ∗ u^* u 代表所有正样本中 IoU 的最大值, m j m_j mj 代表该正样本的 align_metric m ∗ m^* m 同理为最大值。

4. 计算损失

4.1 Class

self.bce = nn.BCEWithLogitsLoss(reduction="none")
target_scores_sum = max(target_scores.sum(), 1)
loss[1] = self.bce(pred_scores, target_scores.to(dtype)).sum() / target_scores_sum

l n = − w n [ y n ⋅ log ⁡ σ ( x n ) + ( 1 − y n ) ⋅ log ⁡ ( 1 − σ ( x n ) ) ] l_{n}=-w_{n}\left[y_{n} \cdot \log \sigma\left(x_{n}\right)+\left(1-y_{n}\right) \cdot \log \left(1-\sigma\left(x_{n}\right)\right)\right] ln=wn[ynlogσ(xn)+(1yn)log(1σ(xn))]

l n l_n ln 表示某个 Anchor 在某个类别上的分类损失,一共有 b ∗ a ∗ 80 b*a*80 ba80 l l l
w n w_n wn 统一取 1;
y n y_n yn 在正样本处的值为对应的 target_score,其余负样本处的值为 0;

L c l s = ∑ l ∑ t L_{cls}=\frac{\sum{l}}{\sum{t}} Lcls=tl

4.2 Box

weight = target_scores.sum(-1)[fg_mask].unsqueeze(-1)
iou = bbox_iou(pred_bboxes[fg_mask], target_bboxes[fg_mask], xywh=False, CIoU=True)
loss_iou = ((1.0 - iou) * weight).sum() / target_scores_sum

L b o x = ∑ t j ( 1 − C I o U j ) ∑ t L_{box}=\frac{\sum{t_j(1 - \mathrm{CIoU}_j)}} {\sum{t}} Lbox=ttj(1CIoUj)

I o U \mathrm{IoU} IoU 仅计算正样本,并且会以 target_score 作为权重 weight
注:一个 Anchor 输出仅作为一个实例的正样本,仅在实例的类别上存在 target_score,可用以下代码作为验证

(target_scores.sum(-1) == target_scores.max(-1)[0]).all()
> True

4.3 DFL

target_ltrb = bbox2dist(anchor_points, target_bboxes, self.reg_max)
loss_dfl = self._df_loss(pred_dist[fg_mask].view(-1, self.reg_max + 1), target_ltrb[fg_mask]) * weight
loss_dfl = loss_dfl.sum() / target_scores_sumdef _df_loss(pred_dist, target):tl = target.long()  # target lefttr = tl + 1  # target rightwl = tr - target  # weight leftwr = 1 - wl  # weight rightreturn (F.cross_entropy(pred_dist, tl.view(-1), reduction="none").view(tl.shape) * wl+ F.cross_entropy(pred_dist, tr.view(-1), reduction="none").view(tl.shape) * wr).mean(-1, keepdim=True)

注:这里计算损失时使用的 pred_dist 是网络对于 Box 的原始输出,未经过 DFL 解码成常规的 Box,而标签则是将常规的 target_bboxes 转化成了距离对应 Anchor 坐标的距离,与 pred_dist 的形式相匹配。

l n = − w y n log ⁡ exp ⁡ ( x n , y n ) ∑ c = 1 C exp ⁡ ( x n , c ) ⋅ 1 { y n ≠ i g n o r e _ i n d e x } l_{n}=-w_{y_{n}} \log \frac{\exp \left(x_{n, y_{n}}\right)}{\sum_{c=1}^{C} \exp \left(x_{n, c}\right)} \cdot 1\left\{y_{n} \neq \mathrm { ignore\_index }\right\} ln=wynlogc=1Cexp(xn,c)exp(xn,yn)1{yn=ignore_index}

上式为 F.cross_entropy 计算公式,等价于用 Softmax 计算分类概率 p p p l n = − log ⁡ p n l_n = -\log p_n ln=logpn 作为损失,其中 p n p_n pn 为标签类别对应的概率。
l d f l = ( y i + 1 − y ) l i + ( y − y i ) l i + 1 l_{dfl} = (y_{i+1} - y)l_i + (y-y_i)l_{i+1} ldfl=(yi+1y)li+(yyi)li+1
其中 y y y 为真实的标签,即某个坐标到 Anchor 坐标的距离, y i + 1 y_{i+1} yi+1 代表对 y y y 向上取整, y i y_i yi 代表对 y y y 向下取整。

  举例进行说明,假设 y = 3.7 y = 3.7 y=3.7 l d f l = ( 4 − 3.7 ) l 3 + ( 3.7 − 3 ) l 4 l_{dfl} = (4-3.7)l_3 + (3.7-3)l_4 ldfl=(43.7)l3+(3.73)l4,由于实际的 y y y 通常不会是个整数,单纯的将输出往单一类别收敛是不行的,理想情况就是让 3 和 4 两个类别的概率都比较高,那么通过 DFL 层的计算坐标就会落在 3~4 之间,同时以 y y y 到两边的距离作为权重来平衡两个类别的概率,往理想的 0.3 × 3 + 0.7 × 4 = 3.7 0.3 \times 3 + 0.7 \times 4=3.7 0.3×3+0.7×4=3.7 收敛。

注:每个正样本的损失为 4 个坐标的 DFL 损失的均值,最终当前 Batch 的 DFL 损失为所有正样本损失的和除以 target_scores_sum

模型优化

1. Lightweight Classification Head

  在 YOLOv8 的检测头中,分类头比回归头的参数量和计算量都要大。论文中表示在分析了分类误差和回归误差的影响后,发现回归头意义更大,因此减少分类头的开销不会对性能有较大损害。
  论文的分析实验为分别用真实的回归值和分类值代替输出,使回归或分类的损失置零,最终在验证集上的精度无回归的要比无分类的高很多。个人理解就是类似单独训练两个头,已知检测框位置训练分类,和已知分类训练检测框位置,得出的结论就是针对检测框的回归任务更难,分类任务简单很多,那么分类头就可以简化一些,至少参数量没必要比回归头还多。

  分类头从两个 3 × 3 3\times 3 3×3 卷积轻量化为两个的深度可分离卷积,深度可分离卷积由一个 3 × 3 3\times 3 3×3 的深度卷积和一个 1 × 1 1\times 1 1×1 的逐点卷积构成。

  在结构图中,卷积上方参数对应 [size, stride, padding, groups]。下面结合代码,感受 groups 对于卷积计算的影响(在深度可分离卷积中通常输入通道数和输出通道数相同,为了更直观,示例中使用不同的通道数)

import torch.nn as nn
from ptflops import get_model_complexity_infoconv1 = nn.Conv2d(64, 128, 3, 1, 1, bias=False)
conv2 = nn.Conv2d(64, 128, 3, 1, 1, groups=64, bias=False)
conv3 = nn.Conv2d(64, 128, 3, 1, 1, groups=2, bias=False)flops, params = get_model_complexity_info(conv1, (64, 320, 320), as_strings=False, print_per_layer_stat=True)
print(f"FLOPs: {flops}, {64*3*3*128*320*320}")
print(f"Parameters: {params}, {128*64*3*3}")flops, params = get_model_complexity_info(conv2, (64, 320, 320), as_strings=False, print_per_layer_stat=True)
print(f"FLOPs: {flops}, {1*3*3*128*320*320}")
print(f"Parameters: {params}, {128*1*3*3}")flops, params = get_model_complexity_info(conv3, (64, 320, 320), as_strings=False, print_per_layer_stat=True)
print(f"FLOPs: {flops}, {32*3*3*128*320*320}")
print(f"Parameters: {params}, {128*32*3*3}")

  in_channelsout_channels 都需要可被 groups 整除,标准卷积 groups=1。可以看作把输入按通道维度划分为 groups 组,并将卷积核按输出通道即卷积核个数也划分为 groups 组,然后进行 groups 个并行的标准卷积。

2. SCDown

在这里插入图片描述
  YOLOv8 使用一个标准卷积同时实现空间下采样 h , w → h / 2 , w / 2 h,w\to h/2,w/2 h,wh/2,w/2 和通道变化 c → 2 c c \to 2c c2c,计算成本高。
  SCDown(Spatial-channel decoupled downsampling)将上面两个操作——空间和通道解耦。先通过 1 × 1 1\times 1 1×1 的逐点卷积调节通道数,再通过 3 × 3 3\times 3 3×3 的深度卷积做空间下采样,在降低计算成本的同时最大限度保留信息。

3. CIB

在这里插入图片描述
  在结构上 C2fCIB 就是用 CIB (compact inverted block)替换了原本 C2f 中的 BottleneckCIB 则是将 Bottleneck 中的标准卷积用深度卷积加逐点卷积进行替换。

  论文中,计算每个 stage 最后一个 basic block 中最后一个卷积的数值秩(numerical rank),数值秩越低表示冗余越多,即可进行简化。数值秩是先计算矩阵的奇异值,奇异值大于阈值的数量为数值秩,奇异值大代表重要的信息,奇异值小代表冗余或噪声。
  最终得到的结论如下图,stage 越大,模型越大,冗余越多。这里的 stage 看起来是对应了网络中的 8 个 C2f
在这里插入图片描述
  在模块替换时,大致方法为对数值秩进行排序,逐步替换,直到出现性能下降。因此不同 scale 的模型在模块选择上也有所不同。(具体原理和细节暂不深究)

4. Large-kernel Conv

  用 size 较大的深度卷积可以扩大感受野,增强模型能力,但简单使用会影响针对小目标的浅层特征,也会在高分辨率阶段引入 I/O 开销和延迟。建议在小模型的深层阶段(例如 YOLOv10n 的 22 层),将 CIB 中的第二个深层卷积替换为 7 × 7 7\times 7 7×7 3 × 3 3\times3 3×3 的深度卷积,具体还是看代码比较直观。

class CIB(nn.Module):def __init__(self, c1, c2, shortcut=True, e=0.5, lk=False):super().__init__()c_ = int(c2 * e)  # hidden channelsself.cv1 = nn.Sequential(Conv(c1, c1, 3, g=c1),Conv(c1, 2 * c_, 1),Conv(2 * c_, 2 * c_, 3, g=2 * c_) if not lk else RepVGGDW(2 * c_),Conv(2 * c_, c2, 1),Conv(c2, c2, 3, g=c2),)class RepVGGDW(torch.nn.Module):def __init__(self, ed) -> None:super().__init__()self.conv = Conv(ed, ed, 7, 1, 3, g=ed, act=False)self.conv1 = Conv(ed, ed, 3, 1, 1, g=ed, act=False)self.dim = edself.act = nn.SiLU()def forward(self, x):return self.act(self.conv(x) + self.conv1(x))

5. PSA

在这里插入图片描述
  论文中对这个模块并没有原理上的说明,主要是自注意力的开销比较大,所以设计了 PSA(Partial self-attention)对分辨率最低的特征的一半进行计算,将对于全局的学习能力以较小的计算成本融入 YOLO 中。

  Attention 部分的具体计算方式结合下图和代码查看:
在这里插入图片描述

class Attention(nn.Module):def __init__(self, dim, num_heads=8, attn_ratio=0.5):super().__init__()self.num_heads = num_headsself.head_dim = dim // num_headsself.key_dim = int(self.head_dim * attn_ratio)self.scale = self.key_dim ** -0.5nh_kd = self.key_dim * num_headsh = dim + nh_kd * 2self.qkv = Conv(dim, h, 1, act=False)self.proj = Conv(dim, dim, 1, act=False)self.pe = Conv(dim, dim, 3, 1, g=dim, act=False)def forward(self, x):B, C, H, W = x.shapeN = H * Wqkv = self.qkv(x)q, k, v = qkv.view(B, self.num_heads, self.key_dim*2 + self.head_dim, N).split([self.key_dim, self.key_dim, self.head_dim], dim=2)attn = ((q.transpose(-2, -1) @ k) * self.scale)attn = attn.softmax(dim=-1)x = (v @ attn.transpose(-2, -1)).view(B, C, H, W) + self.pe(v.reshape(B, C, H, W))x = self.proj(x)return x

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

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

相关文章

【Python教程】2-函数、逻辑运算与条件判断

在整理自己的笔记的时候发现了当年学习python时候整理的笔记,稍微整理一下,分享出来,方便记录和查看吧。个人觉得如果想简单了解一名语言或者技术,最简单的方式就是通过菜鸟教程去学习一下。今后会从python开始重新更新&#xff0…

Python基础——字符串

一、Python的字符串简介 Python中的字符串是一种计算机程序中常用的数据类型【可将字符串看作是一个由字母、数字、符号组成的序列容器】,字符串可以用来表示文本数据。 通常使用一对英文的单引号()或者双引号(")…

计算机网络ppt和课后题总结(下)

常用端口总结 计算机网络中,端口是TCP/IP协议的一部分,用于标识运行在同一台计算机上的不同服务。端口号是一个16位的数字,范围从0到65535。通常,0到1023的端口被称为“熟知端口”或“系统端口”,它们被保留给一些标准…

springboot高校运动会信息管理系统设计与实现-计算机毕业设计源码92968

摘 要 本论文介绍了一个高校运动会信息管理系统的设计和实现过程。首先是高校运动会的需求分析和可行性分析,通过比较运动会的各个工作流程,确定了系统的数据流程和数据库结构,然后介绍了高校运动会信息管理系统开发所使用的软件开发工具&…

Clo3D导出服装动画,使用Unity3D展示

1.前言 Clo3D是一款应用于时装行业的3D服装设计软件,其强大的布料模拟算法可在3D空间中实现设计、制版、试衣和走秀,大幅提升数字作品逼真度和制作效率。为了让服装动画效果展示在Unity3D上模拟效果,需要Clo3D模拟出逼着的衣服动画。总体流程为Clo3D - Mixamo -Blen…

【算法篇】求最长公共前缀JavaScript版本

题目描述 给你一个大小为 n 的字符串数组 strs &#xff0c;其中包含n个字符串 , 编写一个函数来查找字符串数组中的最长公共前缀&#xff0c;返回这个公共前缀。 数据范围&#xff1a; 数据范围:0<n<5000&#xff0c;0<len(strsi)< 5000 进阶:空间复杂度 O(1)&a…

金融数据中心能力建设指引

金融数据中心能力建设指引 金融数据中心能力建设指引旨在通过高标准的基础设施建设、完善的数据管理、强大的信息安全防护和业务连续性规划&#xff0c;确保数据中心具备高效、安全、可靠的运行能力&#xff0c;支持金融业务的稳定发展。该指引强调技术创新、标准化管理、人才…

【机器学习】Python与深度学习的完美结合——深度学习在医学影像诊断中的惊人表现

&#x1f525; 个人主页&#xff1a;空白诗 文章目录 一、引言二、深度学习在医学影像诊断中的突破1. 技术原理2. 实际应用3. 性能表现 三、深度学习在医学影像诊断中的惊人表现1. 提高疾病诊断准确率2. 辅助制定治疗方案 四、深度学习对医疗行业的影响和推动作用 一、引言 随着…

Java加密体系结构参考指南-Java Cryptography Architecture

本文是从英文的官网摘了翻译的&#xff0c;用作自己的整理和记录。水平有限&#xff0c;欢迎指正。版本是&#xff1a;22 原文地址&#xff1a;https://docs.oracle.com/en/java/javase/22/security/java-cryptography-architecture-jca-reference-guide.html#GUID-815542FE-CF…

web入门(1)---6.10

总结&#xff1a; 多做一点NSSCTF的新手赛&#xff0c;了解基本题型&#xff0c;然后打牢基础知识 谢队讲解 攻防世界 Web入门题 讲解_哔哩哔哩_bilibili 题目来源&#xff1a;攻防世界新手区 1.view_source 查看源代码 2.get_post 收获&#xff1a; get方法是直接在url…

群体优化算法----火山爆发算法介绍以及离散优化Pareto最优解示例

介绍 火山爆发算法&#xff08;Volcano Eruption Algorithm&#xff0c;VEA&#xff09;是一种新兴的群智能优化算法&#xff0c;其灵感来源于火山爆发的自然现象。火山爆发算法模拟了火山爆发过程中熔岩流动和喷发的行为&#xff0c;以寻找全局最优解。这种算法利用了火山爆发…

Linux下打印封装_统计函数执行时间_线程号时间戳打印

统计函数执行时间&#xff08;多线程环境下统计结果不准&#xff09; // 无返回值 #define FUNC_EXEC_TIME_NORET(fun,promote) ({ \ unsigned long long timeDelta 0; \ struct timespec t1 {0}; \ struct timespec t2 {0}; \ clock_gettime(CLOCK_MONOTONIC, &t1); \ …

度小满金融大模型的应用创新

XuanYuan/README.md at main Duxiaoman-DI/XuanYuan GitHub

【MySQL】(基础篇四) —— 检索数据

检索数据 检索数据是我们使用数据库时进行最多的操作&#xff0c;其中包括了检索条件、排序、过滤、分组等等。我会在后续的多篇博客中为你进行详细地介绍它们。 这次先让我们来粗略的了解一下SELECT&#xff0c;为了使用SELECT检索表数据&#xff0c;必须至少明确两点信息—…

汇编:结构体

在32位汇编中&#xff0c;结构体&#xff08;structures&#xff09;用于组织和管理复杂的数据类型&#xff0c;结构体可以包含多个不同类型的数据项&#xff08;成员&#xff09;&#xff1b;在MASM&#xff08;Microsoft Macro Assembler&#xff09;中&#xff0c;使用结构体…

Linux入门学习(2)

1.相关复习新的指令学习 &#xff08;1&#xff09;我们需要自己创建一个用户&#xff0c;这个用户前期可以是一个root用户&#xff0c;后期使用创建的普通用户 &#xff08;2&#xff09;文件等于文件内容加上文件属性,对于文件的操作就包括对于文件内容的操作和文件属性&…

Polar Web【困难】上传

Polar Web【困难】上传 Contents Polar Web【困难】上传探索&思路&效果进入环境绕过过程Webshell连接 EXPPayload 总结 探索&思路&效果 本题的主题可见为文件上传&#xff0c;详情在破解的过程中逐步发掘&#xff1a; 进入环境&#xff0c;为一个文件上传功界面…

html5实现个人网站源码

文章目录 1.设计来源1.1 网站首页页面1.2 个人工具页面1.3 个人日志页面1.4 个人相册页面1.5 给我留言页面 2.效果和源码2.1 动态效果2.2 目录结构 源码下载 作者&#xff1a;xcLeigh 文章地址&#xff1a;https://blog.csdn.net/weixin_43151418/article/details/139564407 ht…

HCIP-Datacom-ARST自选题库_10_其他判断【23道题】

1.端到端时延等于路径上所有处理时延与队列时延之和。 2.部署PPP Multilink之后&#xff0c;数据将根据源地址和目的地址均匀的分配在各条成员链路上。 3.流镜像分为本地流镜像和远程流镜像两种方式。√ 4.IP报文中用Tos字段进行Q0S标记&#xff0c;Tos字段中是使用前6bit来…

【数据结构】排序(上)

个人主页~ 堆排序看这篇~ 还有这篇~ 排序 一、排序的概念及应用1、概念2、常见的排序算法 二、常见排序的实现1、直接插入排序&#xff08;1&#xff09;基本思想&#xff08;2&#xff09;代码实现&#xff08;3&#xff09;时间复杂度&#xff08;4&#xff09;空间复杂度 2…