深度学习课程实验三训练和测试卷积神经网络

一、 实验目的

1、学会搭建、训练和测试卷积神经网络,并掌握其应用。
2、掌握使用numpy实现卷积(CONV)和池化(POOL)层,包括正向春传播和反向传播。

二、 实验步骤

Convolutional Neural Networks: Step by Step
1、导入所需要的安装包
2、构建卷积神经网络
3、零填充、
4、卷积的单个步骤、
5、卷积神经网络的正向传播
6、池化层的正向传播
Convolutional Neural Networks: Application
1、TensorFlow模型
2、创建占位符
3、初始化参数
4、正向传播
5、计算损失
6、构建模型
Residual Networks
1、导入所需要的安装包
2、深层神经网络带来的问题
3、建立残差网络(前向传播残差块、反向传播残差块)
4、建立第一个ResNet模型
5、测试我们自己的图片(可选练习)
Autonomous driving - Car detection
1、导入所需要的安装包
2、问题描述
3、YOLO
⑴模型的详细信息
⑵对类别分数进行过滤
⑶非极大值抑制
⑷将两者组合以筛选边界框
4、输入图像测试YOLO预训练模型
⑴定义类,瞄点和图像维度
⑵加载预训练模型
⑶将模型的输出转换为可用的边界框张量
⑷筛选框

三、 实验代码分析

1、import numpy as np:将numpy库导入为np。numpy是一个用于进行数组和矩阵运算的常用库。
2、import h5py:导入h5py库。h5py是一个用于读写HDF5格式数据的库。HDF5是一种灵活、可扩展和高效的数据存储格式。
3、import matplotlib.pyplot as plt:导入matplotlib.pyplot库,并将其简称为plt。matplotlib.pyplot是一个用于绘制图形的库。它提供了一系列用于创建图形、设置图形属性和显示图形的函数。
4、X_pad = np.pad(X, ((0,0), (pad,pad), (pad,pad), (0,0)), “constant”):定义了一个函数zero_pad,用于在数据X的四个维度上应用零填充。
函数接受两个参数:X为输入的数据,pad为填充的大小。代码中通过调用 np.pad函数实现了零填充操作。np.pad函数可以在多维数组的各个维度上进行填充操作,第一个参数为输入数组,第二个参数为填充的形状。在这里,通过传入((0,0), (pad,pad), (pad,pad), (0,0))作为填充形状,实现了对X在第二、第三个维度上进行pad大小的零填充。最后,将填充后的结果存储在变量X_pad中,并返回该变量作为函数的输出。
5、s = np.multiply(a_slice_prev, W):a_slice_prev是输入的切片,W是卷积核参数,b是偏置参数。代码中,首先通过使用np.multiply函数实现了输入切片a_slice_prev与卷积核参数W的逐元素相乘
6、Z = np.sum(s):然后,通过使用np.sum函数计算了相乘结果的和,并将结果存储在变量Z中。
7、Z = Z + float(b):将偏置参数b转换为浮点型,并与变量Z相加,将结果存储回Z中。
8、(m, n_H_prev, n_W_prev, n_C_prev) = A_prev.shape:获取上一层输出数据 A_prev的形状,其中m表示样本数,n_H_prev表示上一层输出的高度,n_W_prev表示上一层输出的宽度,n_C_prev表示上一层输出的通道数。
9、(f, f, n_C_prev, n_C) = W.shape:获取卷积核参数 W的形状,其中 f表示卷积核的大小,n_C_prev表示上一层输出的通道数,n_C表示卷积核的个数。
10、stride = hparameters[“stride”]:从超参数中获取卷积的步长(stride)
11、pad = hparameters[“pad”]:从超参数中获取卷积的填充大小。
12、n_H = (n_H_prev - f + 2 * pad) / stride + 1:计算卷积输出的高度
13、n_W = (n_W_prev - f + 2 * pad) /stride + 1:计算卷积输出的宽度
14、Z = np.zeros((m, n_H, n_W, n_C)):创建一个全零的数组作为卷积层的输出结果。
15、A_prev_pad = zero_pad(A_prev, pad):对输入数据A_prev进行零填充,得到填充后的矩阵A_prev_pad。
16、a_slice_prev = a_prev_pad[vert_start : vert_end, horiz_start : horiz_end, : ]:从填充后的数据中切取与卷积核大小一致的切片。
17、Z[i, h, w, c] = conv_single_step(a_slice_prev, W[:, :, :, c], b[:, :, :, c]):使用函数 conv_single_step计算卷积操作的输出值:,并将结果存储在输出结果 Z中
18、cache = (A_prev, W, b, hparameters):将输入数据、卷积核参数、偏置参数和超参数存储为缓存,用于反向传播。
19、if mode == “max”: A[i, h, w, c] = np.max(a_prev_slice) :如果mode等于"max",那么会计算a_prev_slice中的最大值,并把结果赋值给A[i, h, w, c]。即将a_prev_slice中的元素取最大值后赋值给指定位置。
20、elif mode == “average”: A[i, h, w, c] = np.mean(a_prev_slice):如果mode等于"average",那么会计算a_prev_slice的平均值,并把结果赋值给A[i, h, w, c]。即将a_prev_slice中的元素取平均值后赋值给指定位置。
21、X = tf.placeholder(tf.float32, shape=[None, n_H0, n_W0, n_C0]):X是一个四维的浮点数张量,用来存储输入数据的特征。它的形状是[None, n_H0, n_W0, n_C0],其中None表示可以传入任意数量的样本,n_H0、n_W0和n_C0分别表示特征的高度、宽度和通道数。
22、Y = tf.placeholder(tf.float32, shape=[None, n_y]):Y是一个二维的浮点数张量,用来存储输入数据的标签或目标输出。它的形状是[None, n_y],其中None表示可以传入任意数量的样本,n_y表示目标输出的数量。
23、W1=tf.get_variable(“W1”,[4,4,3,8], initializer=tf.contrib.layers.xavier_initializer(seed=0)):使用TensorFlow的 get_variable()函数创建了一个名为"W1"的变量(即权重矩阵),它的形状为[4, 4, 3, 8]。其中,4代表滤波器的高度,4代表滤波器的宽度,3代表输入通道的数量,8代表输出通道(即滤波器数量)的数量。该变量的初始化器是 tf.contrib.layers.xavier_initializer(seed=0),它使用Xavier初始化方法进行权重矩阵的初始化,其中seed=0表示设置随机种子为0,以保证结果的可复现性。
24、W2=tf.get_variable(“W2”,[2,2,8,16], initializer=tf.contrib.layers.xavier_initializer(seed=0) :使用TensorFlow的 get_variable()函数创建了一个名为"W2"的变量(即权重矩阵),它的形状为[2, 2, 8, 16]。其中,2代表滤波器的高度,2代表滤波器的宽度,8代表输入通道的数量,16代表输出通道(即滤波器数量)的数量。该变量的初始化器是 tf.contrib.layers.xavier_initializer(seed=0),同样使用Xavier初始化方法并且设置了随机种子为0。
25、cost=tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=Z3, labels=Y)):使用reduce_mean函数和nn.softmax_cross_entropy_with_logits()函数计算了神经网络模型的成本。Z3是最后一层经过全连接层计算得到的未激活的输出。Y是真实的标签值。tf.nn.softmax_cross_entropy_with_logits()函数首先对Z3进行softmax处理以获取模型的预测结果。然后,它计算了预测结果与真实标签值之间的交叉熵损失。该函数会自动将预测结果和真实标签进行归一化,以确保计算结果的数值稳定性。reduce_mean()函数将整个batch中的交叉熵损失取均值,得到一个标量值作为最终的成本。该值表示整个模型在给定的训练样本集上的平均损失。
26、X, Y = create_placeholders(64, 64, 3, 6):调用名为create_placeholders()的函数,创建了两个placeholder变量X和Y,用来存储训练样本和标签。
27、parameters = initialize_parameters():调用名为initialize_parameters()的函数,初始化神经网络的参数,并将结果存储在变量parameters中。
28、Z3 = forward_propagation(X, parameters):调用名为forward_propagation()的函数,进行神经网络的前向传播计算,得到最后一层的输出Z3。
29、cost = compute_cost(Z3, Y):调用名为compute_cost()的函数,计算成本函数,即神经网络预测结果与真实标签之间的损失。
30、optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(cost):创建了一个Adam优化器,并指定学习率为learning_rate。然后,使用优化器的 minimize()方法来最小化成本函数cost。
31、X = Conv2D(filters = F2, kernel_size = (f, f), strides = (1,1), padding = ‘same’, name = conv_name_base + ‘2b’, kernel_initializer = glorot_uniform(seed=0))(X)
32、X = BatchNormalization(axis=3, name = bn_name_base + ‘2b’)(X)
33、X = Activation(‘relu’)(X):这三行代码实现了残差块的第二个卷积层。它使用fxf大小的卷积核进行卷积,激活函数使用ReLU,同时进行批归一化操作。
34、X = Conv2D(filters = F3, kernel_size = (1, 1), strides = (1,1), padding = ‘valid’, name = conv_name_base + ‘2c’, kernel_initializer = glorot_uniform(seed=0))(X)
35、X = BatchNormalization(axis=3, name = bn_name_base + ‘2c’)(X):两行代码实现了残差块的第三个卷积层。它使用1x1的卷积核进行卷积,不设置偏移量,同时进行批归一化操作。
36、box_scores = box_confidence * box_class_probs:计算每个候选框的分数,即将盒子置信度box_confidence与盒子类别概率box_class_probs进行相乘。
37、box_classes = K.argmax(box_scores, axis=-1):找到每个候选框拥有最高分数的类别,即沿着最后一个维度(axis=-1)找到最大值的索引。
38、box_class_scores = K.max(box_scores, axis=-1, keepdims=False):计算每个候选框的最高分数,即沿着最后一个维度(axis=-1)找到最大值。
39、filtering_mask = box_class_scores > threshold:创建了一个布尔掩码,用来标记分数高于阈值的候选框。
40、scores = tf.boolean_mask(box_class_scores, filtering_mask):
41、boxes = tf.boolean_mask(boxes, filtering_mask):
42、classes = tf.boolean_mask(box_classes, filtering_mask):三行代码使用tf.boolean_mask函数根据布尔掩码来过滤出分数高于阈值的候选框的分数、位置和类别。
43、xi1 = max(box1[0], box2[0])
44、yi1 = max(box1[1], box2[1])
45、xi2 = min(box1[2], box2[2])
46、yi2 = min(box1[3], box2[3]):这四行代码计算两个矩形框的相交矩形框的左上角坐标(xi1, yi1)和右下角坐标(xi2, yi2)。使用max和min函数将两个矩形框的坐标投影到水平和垂直方向上。
47、inter_area = (xi2 - xi1) * (yi2 - yi1):计算相交矩形框的面积,通过相交矩形框的宽度(xi2 - xi1)和高度(yi2 - yi1)的乘积计算得到。
48、box1_area = (box1[2] - box1[0]) * (box1[3] - box1[1])
49、box2_area = (box2[2] - box2[0]) * (box2[3] - box2[1]):两行代码分别计算两个矩形框的面积,通过矩形框的宽度和高度的乘积计算得到。
50、union_area = box1_area + box2_area - inter_area:计算两个矩形框的并集面积,通过两个矩形框的面积之和减去相交矩形框的面积(inter_area)计算得到。
51、iou = inter_area / union_area:计算交并比,即相交矩形框的面积(inter_area)除以并集矩形框的面积(union_area)。
52、nms_indices=tf.image.non_max_suppression(boxes, scores, max_boxes, iou_threshold, name=None):使用tf.image.non_max_suppression函数进行非极大值抑制操作,根据所给的分数、位置、最大保留框数和交并比阈值,返回选择后的候选框的索引。
53、scores = K.gather(scores, nms_indices)
54、boxes = K.gather(boxes, nms_indices)
55、classes = K.gather(classes, nms_indices):这三行代码使用K.gather函数根据非极大值抑制的索引从scores、boxes和classes中选择对应的候选框的分数、位置和类别。
56、box_confidence, box_xy, box_wh, box_class_probs = yolo_outputs:从yolo_outputs中获取YOLO模型的输出,包括盒子置信度、盒子中心坐标、盒子宽高和盒子类别概率等。
57、boxes = yolo_boxes_to_corners(box_xy, box_wh):调用yolo_boxes_to_corners函数,将盒子的中心坐标和宽高转换为左上角和右下角坐标表示的形式。
58、scores,boxes,classes=yolo_filter_boxes(box_confidence, boxes, box_class_probs, score_threshold):调用yolo_filter_boxes函数,对候选框进行过滤操作,根据分数阈值将低得分的候选框过滤掉,只保留高分数的候选框,并得到经过过滤后的分数、位置和类别。
59、boxes = scale_boxes(boxes, image_shape):调用scale_boxes函数,将候选框的位置坐标缩放到与原始图像匹配的尺寸。
60、scores, boxes, classes=yolo_non_max_suppression(scores, boxes, classes, max_boxes, iou_threshold):调用yolo_non_max_suppression函数,进行非极大值抑制操作,根据交并比阈值和最大保留框数来选择最终的候选框,并返回分数、位置和类别。

四、 运行结果
Convolutional Neural Networks: Step by Step
1、zero-pad
在这里插入图片描述
2、切片
在这里插入图片描述

3、卷积前向传播
在这里插入图片描述
4、池化前向传播
在这里插入图片描述

5、卷积反向传播
在这里插入图片描述
6、create_mask_from_window
在这里插入图片描述

7、 distribute_value
在这里插入图片描述

8、池化层反向传播
在这里插入图片描述
Convolutional Neural Networks: Application
1、加载索引为2的数据集
在这里插入图片描述

2、检查数据的维度
在这里插入图片描述
3、创建占位符
在这里插入图片描述

4、初始化参数
在这里插入图片描述

5、正向传播
在这里插入图片描述

6、计算损失
在这里插入图片描述
7、构建模型
在这里插入图片描述

Residual Networks
1、残差块输出
在这里插入图片描述

2、卷积块输出
在这里插入图片描述
3、加载数据集
在这里插入图片描述

4、训练了两个epoch在测试集上的表现
在这里插入图片描述
Autonomous driving - Car detection
1、对类别分数进行过滤
在这里插入图片描述

2、非极大值的iou值
在这里插入图片描述

3、非极大值抑制后的结果
在这里插入图片描述

4、将两者结合以筛选边界框
在这里插入图片描述
5、运行计算图结果
在这里插入图片描述

五、 实验结果分析、体会

在逐步实现卷积神经网络实验的过程中,我得出了以下实验结果分析与体会:
卷积神经网络的特征提取能力:卷积神经网络具有强大的特征提取能力,能够从图像中学习出高级的特征表示。在我的实验中,随着卷积层和池化层的叠加,模型逐渐学习到了更加抽象和复杂的特征。这使得模型在对图像进行分类和识别时表现出较好的准确率。
模型的深度与性能关系:在实验中,我尝试了不同的神经网络深度,即调整了卷积层和全连接层的数量和大小。通过对比实验结果,我发现较深的网络结构在处理复杂图像任务时往往能够达到更好的效果。但需要注意的是,过深的网络可能导致模型训练困难、计算资源需求增加等问题,因此需要进行权衡和平衡。在卷积神经网络的应用中,可以用TensorFlow实现功能全面的ConNet。
在残差网络的实验中,我了解到残差连接的作用:在实验中,我使用了残差连接来构建深度残差网络。通过比较带有和不带有残差连接的网络模型,在相同层数下进行训练和测试。实验结果显示,带有残差连接的网络模型相比于普通的深度模型,具有更好的性能。这是因为残差连接允许信息在网络中更有效地传递,减轻了梯度消失问题,从而使网络更容易训练和优化。
模型收敛速度的改善:在实验中,我观察到使用残差连接的深度模型相对于传统深度模型,在训练过程中显示出更快的收敛速度。这意味着残差网络能够更快地学习有效的特征表示,从而提高了整体的训练效率。这对于处理大规模数据集或训练复杂深度模型是非常有价值的。
模型复杂性与泛化能力的权衡:在实验过程中,我改变了残差连接网络的深度和宽度来评估模型的性能。通过实验对比,我发现增加网络的深度可以进一步提升性能,但也容易导致过拟合的问题。因此,在设计残差网络时,需要权衡模型的复杂性和泛化能力,避免深度过大导致的训练困难和计算资源消耗。
在自动驾驶-车辆识别的实验中,我了解到模型的准确率和鲁棒性:在实验中,我使用了深度学习模型对车辆进行识别。通过对大量的车辆图像进行训练和测试,模型在识别车辆方面表现出了较高的准确率。然而,我也发现在处理复杂场景、光照条件变化或车辆姿态变化等较为复杂的情况下,模型的性能受到了一定的影响。因此,提升模型的鲁棒性是未来研究的一个重要方向。
数据集的重要性:实验中,我使用了大规模的车辆图像数据集进行训练和评估。一个充分且多样化的数据集是保证模型性能的关键因素。通过使用多个数据源和增加数据增强操作,我能够获得更具代表性和广泛分布的车辆样本,进而改善模型的表现。模型的效率与实时性:在自动驾驶场景中,及时有效的车辆识别十分重要。在实验过程中,我优化了模型的结构和参数,以提高模型的计算效率和响应速度。通过模型压缩和硬件优化等技术手段,我能够获得更高的实时性和较低的计算资源消耗。真实场景的应用挑战:实验结果也揭示出在真实场景中的一些挑战。例如,复杂的背景干扰、部分遮挡、多尺度车辆等因素可能导致模型的识别表现下降。

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

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

相关文章

RabbitMQ安装与应用

文章目录 1. RabbitMQ1.1. 同步通讯与异步通讯1.2. 异步通讯的优缺点1.3. 几种MQ的对比1.4. docker安装运行RabbitMQ 流程1.5. RabbitMQ的几个概念1.6. 五种模型1.6.1. 基本消息队列 1.7. 基本使用1.7.1. 1建立连接时会出现以下界面![在这里插入图片描述](https://img-blog.csd…

信息论与编码期末复习——概念论述简答题(一)

个人名片: 🦁作者简介:一名喜欢分享和记录学习的在校大学生 🐯个人主页:妄北y 🐧个人QQ:2061314755 🐻个人邮箱:2061314755qq.com 🦉个人WeChat:V…

箱体透明屏的原理

箱体透明屏的原理主要是通过特殊的结构设计,使得屏幕具有透光性,从而实现在显示内容的同时保持箱体的透明效果。具体来说,箱体透明屏采用镂空结构的设计,将灯条一根根的排列成透明状,使得屏幕整体看起来具有透明感。在…

基于卷积神经网络的回归分析

目录 背影 卷积神经网络CNN的原理 卷积神经网络CNN的定义 卷积神经网络CNN的神经元 卷积神经网络CNN的激活函数 卷积神经网络CNN的传递函数 卷积神经网络的回归分析 完整代码:卷积神经网络的回归分析(代码完整,数据齐全)资源-CSDN文库 https://download.csdn.net/download/…

如何设置pygame窗口的标题

通过 pygame.display.set_caption("这是标题") 可以绘制窗口的标题 import pygame #导包 from pygame.locals import* import sysscreen_width600 screen_height600 pygame.init() #初始化 screen pygame.display.set_mode(size(screen_width,screen_height)) py…

postgresql可视化导入文件

不需要在命令行copy了,只需简单点几下 注意:要选清楚各列类型(第6步),不然会出错! 1.在数据库下建一个schema 右击选中数据库-new schema 2.双击你创建的schema,出现tables 3.右击tables&am…

【论文阅读笔记】医学多模态新数据集-Large-scale Long-tailed Disease Diagnosis on Radiology Images

这是复旦大学2023.12.28开放出来的数据集和论文,感觉很宝藏,稍微将阅读过程记录一下。 Zheng Q, Zhao W, Wu C, et al. Large-scale Long-tailed Disease Diagnosis on Radiology Images[J]. arXiv preprint arXiv:2312.16151, 2023. 项目主页&#xf…

DC电源模块的可持续发展与环境保护

BOSHIDA DC电源模块的可持续发展与环境保护 DC电源模块的可持续发展与环境保护是一个重要议题。DC电源模块是一种能够将交流电转换为直流电的设备,广泛应用于各种电子设备和系统中。然而,传统的DC电源模块存在一些环境问题,如能源浪费和电磁…

解决sublime中文符号乱码问题

效果图 原来 后来 问题不是出自encode文件编码,而是win10的字体问题。 解决方法 配置: { "font_face":"Microsoft Yahei", "dpi_scale": 1.0 } 参考自 Sublime 输入中文显示方框问号乱码_sublime中文问号-CSDN博…

redis中bitmap应用

原理介绍 Redis Bitmap 是 Redis 中的一种数据结构,它类似于位图,可以用来表示一组二进制位,每个二进制位只能是 0 或 1。Redis Bitmap 提供了一些操作命令,如 SETBIT、GETBIT、BITCOUNT 等,可以对位图进行设置、…

2023春季李宏毅机器学习笔记 05 :机器如何生成图像

资料 课程主页:https://speech.ee.ntu.edu.tw/~hylee/ml/2023-spring.phpGithub:https://github.com/Fafa-DL/Lhy_Machine_LearningB站课程:https://space.bilibili.com/253734135/channel/collectiondetail?sid2014800 一、图像生成常见模型…

Qt通过pos()获取坐标信息

背景:这是一个QWidget窗体,里面是各种布局的组合,一层套一层。 我希望得到绿色部分的坐标信息(x,y) QPoint get_pos(QWidget* w, QWidget* parent) {if ((QWidget*)w->parent() parent) {return w->pos();}else {QPoint pos(w->po…

Vue-Cli 5.0.0搭建Cesium环境

1、创建vue-cli项目 1、查看vue版本 使用指令:vue -V 2、创建Vue项目 1、在需要创建文件的目录,输入cmd 2、在命令行,输入 vue create <project-name>,并选择最后一项 3、选择插件 4、选择Vue版本3.0 5、根据图示选择

2.HDFS 架构

目录 概述架构HDFS副本HDFS数据写入流程NN 工作原理DN 工作原理 结束 概述 官方文档快递 环境&#xff1a;hadoop 版本 3.3.6 相关文章速递 架构 HDFS HDFS 架构总结如下&#xff1a; a master/slave architecture 一主多从架构a file is split into one or more blocks a…

激光焊接机:塑料产品制造中的革命性优势

随着科技的飞速发展&#xff0c;激光焊接机在塑料产品制造领域的应用越来越广泛。相较于传统的焊接技术&#xff0c;激光焊接机在塑料产品制造中展现出诸多优势&#xff0c;成为现代工业生产中不可或缺的一部分。 一、精确、高效的焊接性能 激光焊接机采用高能激光束作为焊接热…

华为交换机怎么添加和剥除VLAN标签

知识改变命运&#xff0c;技术就是要分享&#xff0c;有问题随时联系&#xff0c;免费答疑&#xff0c;欢迎联系&#xff01; 华为交换机VLAN标签的添加和剥除处理过程 接口对收发的以太网数据帧添加或剥除VLAN标签的处理依据接口的接口类型和缺省VLAN。 由上面各类接口添加或…

windows通过ssh连接Liunx服务器并实现上传下载文件

连接ssh 输入&#xff1a;ssh空格用户名ip地址&#xff0c;然后按Enter 有可能出现下图提示&#xff0c;输入yes 回车即可 输入 password &#xff0c;注意密码是不显示的&#xff0c;输入完&#xff0c;再按回车就行了 以上是端口默认22情况下ssh连接&#xff0c;有些公司它…

(vue)el-popover鼠标移入提示效果

(vue)el-popover鼠标移入提示效果 效果&#xff1a; 代码&#xff1a; <el-form-itemv-for"(item,index) of ele.algorithmParameters":key"index":label"item.parametersName"class"descInput" ><el-input v-model"i…

柱面,盘片,盘面,扇面,磁头,磁道,扇区,CHS地址,LAB地址

柱面&#xff0c;盘片&#xff0c;盘面&#xff0c;扇面&#xff0c;磁头&#xff0c;磁道&#xff0c;扇区&#xff0c;CHS地址&#xff0c;LAB地址1 CHS地址 CHS地址指的是柱面&#xff08;Cylinder&#xff09;、磁头&#xff08;Head&#xff09;、扇区&#xff08;Secto…

Kotlin:Set其实是有插入的顺序?

MutableSet怎么能调用indexOf去获取它的插入顺序呢&#xff1f;参考官网Collections overview | Kotlin Documentationhttps://kotlinlang.org/docs/collections-overview.html#set翻不了墙的看下面 &#xff08;MutableSet的默认实现是LinkedHashSet&#xff0c;LinkedHashSet…