2023认证杯B题:金属表面缺陷检测|数学中国数学建模国际赛(小美赛) |数学建模完整代码+建模过程全解全析

当大家面临着复杂的数学建模问题时,你是否曾经感到茫然无措?作为2022年美国大学生数学建模比赛的O奖得主,我为大家提供了一套优秀的解题思路,让你轻松应对各种难题。
让我们来看看认证杯的B题!
在这里插入图片描述

完整内容可以在文章末尾领取!

问题重述

金属或塑料产品表面的缺陷不仅会影响产品的外观,还可能对产品的性能或耐久性造成严重损害。自动表面异常检测已成为一个引人关注且有前景的研究领域,对视觉检查应用领域有着非常高且直接的影响[1]。Kolektor集团提供了一组有缺陷的生产物品图像数据集[2],我们希望利用这个数据集作为示例,研究通过照片自动检测产品表面缺陷的数学模型。

问题一、确定照片中是否出现表面缺陷,并测量模型执行此操作所需的计算量和存储空间。

使用Vision Transformer(ViT)算法进行表面缺陷检测需要经历以下步骤:

数据准备: 将Kolektor集团提供的有缺陷的生产物品图像数据集用于训练和测试。确保数据集包括正常和有缺陷的样本,并进行适当的标注。

模型选择: ViT是一个基于注意力机制的图像分类模型,可以用于检测表面缺陷。选择适当的预训练的ViT模型,例如Google的ViT或其他经过训练的变体。

模型微调: 使用数据集对所选的ViT模型进行微调,以适应特定的表面缺陷检测任务。调整模型的输出层,使其适应二分类问题(缺陷/正常)。

计算量和存储空间优化: ViT模型可能相对较大,因此需要优化计算量和存储空间。可以使用以下策略:

模型剪枝: 剪枝掉不重要的权重,减小模型参数数量。
量化: 降低模型参数的位数,减小存储空间和计算量。
深度可分离卷积替代注意力层: 在资源受限的情况下,可以考虑使用深度可分离卷积替代注意力层,以减少计算量。

性能评估: 使用测试集评估模型的性能,包括准确性、召回率和精确度。这有助于了解模型在检测表面缺陷方面的效果。

Vision Transformer(ViT)是一种基于注意力机制的深度学习模型,专门设计用于图像分类任务。传统的卷积神经网络(CNN)在图像分类中取得了巨大成功,但ViT采用了一种全新的思路,将图像划分为均匀的图块,并通过自注意力机制来捕捉图块之间的关系。

以下是ViT的主要组成部分和工作原理:

  1. 图像的划分: ViT将输入的图像划分为一系列非重叠的图块,每个图块称为一个“补丁”。这些补丁被拉平成一维向量,然后作为输入序列传递给模型。

  2. 嵌入层(Embedding Layer): 对每个补丁进行线性映射,将其转换为一个具有较低维度的嵌入向量。这些嵌入向量将作为输入序列传递给Transformer模型。

  3. Transformer编码器: ViT使用Transformer编码器来处理输入序列。每个Transformer编码器由多个自注意力头和全连接前馈网络组成。这使得模型能够捕捉序列中不同位置的关系。

  4. 多头注意力机制: 自注意力机制允许模型在处理序列时动态关注不同位置的信息。多头注意力则是通过并行计算多个注意力机制,增加了模型对不同特征尺度的感知。

  5. 全局池化: ViT使用全局平均池化来整合整个序列的信息,得到最终的特征表示。这一步代替了传统CNN中的全连接层,使得ViT更具可扩展性。

ViT的主要优势在于,相对于传统的CNN,它不再需要手工设计的卷积层,而是通过自注意力机制直接学习输入序列中的全局关系。这种思想使得ViT在处理图像分类任务时表现出色,并且在一些领域展现出强大的泛化能力。在图像分类以外的任务中,ViT的变体也被成功地应用,例如目标检测和语义分割。

ViT(Vision Transformer)的核心思想是使用自注意力机制(Self-Attention)捕捉输入序列中元素之间的关系。以下是ViT中的一些关键公式:

  1. 输入序列表示:

    • 假设输入图像被划分为 N 个补丁(patches),每个补丁的维度为 d_patch
    • 将每个补丁拉平成一维向量,得到输入序列: X = [ x 1 , x 2 , … , x N ] \mathbf{X} = [x_1, x_2, \ldots, x_N] X=[x1,x2,,xN],其中 x i ∈ R d patch x_i \in \mathbb{R}^{d_{\text{patch}}} xiRdpatch
  2. 嵌入层(Embedding Layer):

    • 使用一个线性映射来将每个补丁转换为低维嵌入向量: E = Linear ( X ) \mathbf{E} = \text{Linear}(\mathbf{X}) E=Linear(X),其中 E = [ e 1 , e 2 , … , e N ] \mathbf{E} = [e_1, e_2, \ldots, e_N] E=[e1,e2,,eN] e i ∈ R d embed e_i \in \mathbb{R}^{d_{\text{embed}}} eiRdembed
  3. 自注意力机制(Self-Attention):

    • 对于输入序列的每个位置 i i i,计算注意力分数(注意力权重):
      Attention ( E ) i j = exp ⁡ ( E i ⋅ E j ) ∑ k exp ⁡ ( E i ⋅ E k ) \text{Attention}(\mathbf{E})_{ij} = \frac{\exp(\mathbf{E}_i \cdot \mathbf{E}_j)}{\sum_k \exp(\mathbf{E}_i \cdot \mathbf{E}_k)} Attention(E)ij=kexp(EiEk)exp(EiEj)
    • 这里, E i \mathbf{E}_i Ei 表示位置 i i i 的嵌入向量。
  4. 多头自注意力机制(Multi-Head Self-Attention):

    • 使用多个注意力头( h h h 个)并行计算:
      MultiHead ( E ) = Concat ( Head 1 , Head 2 , … , Head h ) ⋅ W O \text{MultiHead}(\mathbf{E}) = \text{Concat}(\text{Head}_1, \text{Head}_2, \ldots, \text{Head}_h) \cdot \mathbf{W}_O MultiHead(E)=Concat(Head1,Head2,,Headh)WO
    • 每个注意力头的计算类似,但使用不同的线性映射参数。
  5. 全连接前馈网络(Feedforward Network):

    • 对每个位置 i i i 的多头注意力输出应用前馈网络:
      FFN ( MultiHead ( E ) ) i = ReLU ( W 1 ⋅ MultiHead ( E ) i + b 1 ) ⋅ W 2 + b 2 \text{FFN}(\text{MultiHead}(\mathbf{E}))_i = \text{ReLU}(\mathbf{W}_1 \cdot \text{MultiHead}(\mathbf{E})_i + \mathbf{b}_1) \cdot \mathbf{W}_2 + \mathbf{b}_2 FFN(MultiHead(E))i=ReLU(W1MultiHead(E)i+b1)W2+b2
    • 这里, W 1 , W 2 , b 1 , b 2 \mathbf{W}_1, \mathbf{W}_2, \mathbf{b}_1, \mathbf{b}_2 W1,W2,b1,b2 是网络参数。
  6. 全局平均池化(Global Average Pooling):

    • 将前馈网络的输出进行全局平均池化,得到最终的特征表示:
      Pool ( FFN ( MultiHead ( E ) ) ) = 1 N ∑ i = 1 N FFN ( MultiHead ( E ) ) i \text{Pool}(\text{FFN}(\text{MultiHead}(\mathbf{E}))) = \frac{1}{N} \sum_{i=1}^{N} \text{FFN}(\text{MultiHead}(\mathbf{E}))_i Pool(FFN(MultiHead(E)))=N1i=1NFFN(MultiHead(E))i

这些公式概括了ViT的核心组成部分,其中自注意力机制和多头机制是其独特之处。这些公式描述了如何从输入图像序列中学习全局关系,以便进行有效的图像分类。

在工业表面缺陷检测的问题场景中应用ViT:

输入数据: 使用Kolektor集团提供的有缺陷的生产物品图像数据集作为训练和测试数据。确保数据集包括正常和有缺陷的样本,并进行适当的标注。

图像划分: 将每张图像划分为均匀的图块,每个图块作为一个输入补丁。这些补丁将被拉平为一维向量,并作为输入序列传递给ViT模型。

模型选择: 选择适当的ViT模型,可以是预训练的ViT模型或者在图像分类任务上微调过的模型。

微调: 对选择的ViT模型进行微调,以适应表面缺陷检测任务。调整模型的输出层,使其能够输出缺陷/正常的分类结果。

优化计算和存储: 使用模型剪枝、量化和深度可分离卷积等技术,以优化模型的计算量和存储空间。这对于在廉价手持设备上部署模型至关重要。

模型评估: 使用测试集评估模型在表面缺陷检测任务上的性能,包括准确性、召回率和精确度。确保模型能够有效地检测出表面缺陷。

import torch
import torch.nn as nn
import torch.optim as optim
from torchvision import transforms
from torch.utils.data import DataLoader, Dataset# 定义简单的Vision Transformer模型
class ViTModel(nn.Module):def __init__(self, num_classes, embed_dim=256, num_heads=4, num_layers=6):super(ViTModel, self).__init__()self.embedding = nn.Linear(3 * 16 * 16, embed_dim)self.transformer = nn.TransformerEncoder(nn.TransformerEncoderLayer(d_model=embed_dim, nhead=num_heads),num_layers=num_layers)self.fc = nn.Linear(embed_dim, num_classes)def forward(self, x):x = self.embedding(x.view(x.size(0), -1))x = x.permute(1, 0, 2)x = self.transformer(x)x = x.mean(dim=0)x = self.fc(x)return x# 定义数据集
class SurfaceDefectDataset(Dataset):def __init__(self, data, labels, transform=None):self.data = dataself.labels = labelsself.transform = transformdef __len__(self):return len(self.data)def __getitem__(self, idx):image = self.data[idx]label = self.labels[idx]if self.transform:image = self.transform(image)return image, label# 定义数据转换
transform = transforms.Compose([transforms.ToTensor(),# Add more transformations as needed
])# 准备数据
# Replace 'train_data', 'train_labels', 'test_data', 'test_labels' with your actual data
train_dataset = SurfaceDefectDataset(train_data, train_labels, transform=transform)
test_dataset = SurfaceDefectDataset(test_data, test_labels, transform=transform)train_loader = DataLoader(train_dataset, batch_size=32, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=32, shuffle=False)# 初始化模型、损失函数和优化器
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model = ViTModel(num_classes=2).to(device)
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)# 训练模型
num_epochs = 10
for epoch in range(num_epochs):model.train()for inputs, labels in train_loader:inputs, labels = inputs.to(device), labels.to(device)optimizer.zero_grad()outputs = model(inputs)loss = criterion(outputs, labels)loss.backward()optimizer.step()# 在测试集上评估模型model.eval()with torch.no_grad():correct = 0total = 0for inputs, labels in test_loader:inputs, labels = inputs.to(device), labels.to(device)outputs = model(inputs)_, predicted = torch.max(outputs.data, 1)total += labels.size(0)correct += (predicted == labels).sum().item()accuracy = correct / totalprint(f'Epoch [{epoch+1}/{num_epochs}], Test Accuracy: {accuracy:.4f}')

问题二:自动标记表面缺陷出现的位置或区域,并测量模型所需的计算量、存储空间和标记准确性。

Faster R-CNN(Region-based Convolutional Neural Network)是一种用于目标检测的深度学习模型。其核心理论是通过引入两个阶段的网络,即区域提议网络(Region Proposal Network,RPN)和目标检测网络,来实现快速而准确的目标检测。

  1. 区域提议网络(RPN):

    • Faster R-CNN引入了一个专门的区域提议网络,该网络负责生成潜在的目标框(区域提议)。
    • RPN通过在输入图像上滑动一个小窗口,计算每个窗口中是否包含目标,并为每个窗口生成多个候选框(边界框)以及相应的置信度分数。
    • RPN使用锚框(anchor boxes)来生成候选框,这些锚框具有多个尺度和长宽比,以适应不同大小和形状的目标。
  2. 目标检测网络:

    • 在Faster R-CNN中,RPN生成的候选框将被用于提取特征。这些候选框中的区域被RoI池化层处理,将它们映射为固定大小的特征图。
    • 特征图随后被传递给目标检测网络,通常是一个深度卷积神经网络,如ResNet或VGG。该网络对每个RoI进行分类(目标/非目标)和回归(边界框微调)。
  3. 损失函数:

    • Faster R-CNN使用联合损失函数,结合了RPN和目标检测网络的损失。该损失包括分类损失(如交叉熵损失)和回归损失(如平滑的L1损失)。
    • 分类损失用于确保模型正确分类RoI,而回归损失用于确保模型准确地调整RoI的边界框。
  4. 训练过程:

    • Faster R-CNN的训练过程是端到端的,通过在整个模型中反向传播误差信号来更新网络参数。
    • 训练过程中,模型同时学习RPN的区域提议和目标检测网络的参数,以便更好地适应具体任务。
  5. 推理过程:

    • 在推理过程中,Faster R-CNN通过RPN生成候选框,然后使用目标检测网络对这些候选框进行分类和回归,最终得到最终的目标检测结果。

总的来说,Faster R-CNN的设计使得它能够在目标检测任务中实现更高的准确性和更快的推理速度。这种两阶段的框架允许模型专注于生成高质量的候选框,然后对这些候选框进行详细的分类和位置调整。

在问题场景下,进行目标检测任务,以自动标记表面缺陷出现的位置或区域,目标检测通常需要使用带有标注框的训练数据集进行训练。

import torch
import torchvision
from torchvision.models.detection import FasterRCNN
from torchvision.models.detection.rpn import AnchorGenerator
from torchvision.transforms import functional as F
from PIL import Image, ImageDraw# 定义Faster R-CNN模型
def get_faster_rcnn_model(num_classes):backbone = torchvision.models.mobilenet_v2(pretrained=True).featuresbackbone.out_channels = 1280anchor_generator = AnchorGenerator(sizes=((32, 64, 128, 256, 512),),aspect_ratios=((0.5, 1.0, 2.0),))roi_pooler = torchvision.ops.MultiScaleRoIAlign(featmap_names=['0'],output_size=7,sampling_ratio=2)model = FasterRCNN(backbone,num_classes=num_classes,rpn_anchor_generator=anchor_generator,box_roi_pool=roi_pooler)return model# 定义数据集和转换
class SurfaceDefectDataset(Dataset):# 请根据你的数据集格式进行定义# 需要包含图像和对应的标注框信息# 参考 torchvision.transforms 的文档以及自定义的标注框格式# https://pytorch.org/vision/stable/transforms.html# 训练模型
def train_model(model, train_loader, num_epochs=5):device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')model.to(device)params = [p for p in model.parameters() if p.requires_grad]optimizer = torch.optim.SGD(params, lr=0.005, momentum=0.9, weight_decay=0.0005)lr_scheduler = torch.optim.lr_scheduler.StepLR(optimizer, step_size=3, gamma=0.1)for epoch in range(num_epochs):model.train()for images, targets in train_loader:images = [img.to(device) for img in images]targets = [{k: v.to(device) for k, v in t.items()} for t in targets]loss_dict = model(images, targets)losses = sum(loss for loss in loss_dict.values())optimizer.zero_grad()losses.backward()optimizer.step()lr_scheduler.step()print(f"Epoch {epoch+1}/{num_epochs}, Loss: {losses.item()}")# 在测试集上评估模型
def evaluate_model(model, test_loader):model.eval()device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')model.to(device)for images, targets in test_loader:images = [img.to(device) for img in images]targets = [{k: v.to(device) for k, v in t.items()} for t in targets]with torch.no_grad():predictions = model(images)# 处理预测结果,计算标记准确性等指标# 可以使用预测框与实际框的IoU(Intersection over Union)等指标# 可视化预测结果
def visualize_predictions(model, test_loader):model.eval()device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')model.to(device)for images, targets in test_loader:images = [img.to(device) for img in images]targets = [{k: v.to(device) for k, v in t.items()} for t in targets]with torch.no_grad():predictions = model(images)# 可视化预测结果for i in range(len(images)):image = F.to_pil_image(images[i].cpu())draw = ImageDraw.Draw(image)# 可视化真实框for box in targets[i]["boxes"]:draw.rectangle([(box[0], box[1]), (box[2], box[3])], outline="green", width=2)# 可视化预测框for box, score in zip(predictions[i]["boxes"], predictions[i]["scores"]):draw.rectangle([(box[0], box[1]), (box[2], box[3])], outline="red", width=2)draw.text((box[0], box[1]), f"{score:.2f}", fill="red")image.show()

更多内容具体可以看看我的下方名片!里面包含有认证杯一手资料与分析!
另外在赛中,我们也会陪大家一起解析认证杯的一些方向
关注 CS数模 团队,数模不迷路~

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

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

相关文章

你对SPA单页面的理解,它的优缺点分别是什么?

面试官:你对SPA单页面的理解,它的优缺点分别是什么?如何实现SPA应用呢 一、什么是SPA SPA(single-page application),翻译过来就是单页应用SPA是一种网络应用程序或网站的模型,它通过动态重写当…

Whisper

文章目录 使后感Paper Review个人觉得有趣的Log Mel spectrogram & STFT Trainingcross-attention输入cross-attention输出positional encoding数据 Decoding为什么可以有时间戳的信息 Test code 使后感 因为运用里需要考虑到时效和准确性,类似于YOLO&#xff…

vue3使用动态component

使用场景: 多个组件通过component标签挂载在同一个组件中,通过触发时间进行动态切换。vue3与vue2用法不一样,这里有坑! 使用方法: 1.通过vue的defineAsyncComponent实现挂载组件 2.component中的is属性 父组件&am…

GaussDB如何进行性能调优

GaussDB如何进行性能调优 GaussDB性能调优过程需要综合考虑多方面因素,因此,调优人员应对系统软件架构、软硬件配置、数据库配置参数、并发控制、查询处理和数据库应用有广泛而深刻的理解。 调优流程 调优各阶段说明,如下表所示。 数据库性…

深入探究Photoshop图像修复与润饰技巧

💂 个人网站:【 海拥】【神级代码资源网站】【办公神器】🤟 基于Web端打造的:👉轻量化工具创作平台💅 想寻找共同学习交流的小伙伴,请点击【全栈技术交流群】 在Photoshop中,图像修复和润饰是强…

Vim Coc插件实现代码跳转

Vim Coc插件实现代码跳转 按照coc主页的配置 里面是有提供代码跳转的功能的 具体配置如下 " GoTo code navigation nmap <silent> gd <Plug>(coc-definition) nmap <silent> gy <Plug>(coc-type-definition) nmap <silent> gi <Plug…

CNN对 MNIST 数据库中的图像进行分类

加载 MNIST 数据库 MNIST 是机器学习领域最著名的数据集之一。 它有 70,000 张手写数字图像 - 下载非常简单 - 图像尺寸为 28x28 - 灰度图 from keras.datasets import mnist# 使用 Keras 导入MNIST 数据库 (X_train, y_train), (X_test, y_test) mnist.load_data()print(&…

代码随想录算法训练营第三十六天| 435 无重叠区间 763 划分字母区间 56 合并区间

目录 435 无重叠区间 763 划分字母区间 56 合并区间 435 无重叠区间 将intervals数组按照左端点进行升序排序。 设置变量len标志此时新加入端点后所有区间的位置&#xff0c;将其赋初值为第一对区间的右端点&#xff0c;因为该点是一定可达的。设置变量res来存储需要移除空间…

上海亚商投顾:沪指震荡反弹 消费、医药股走势活跃

上海亚商投顾前言&#xff1a;无惧大盘涨跌&#xff0c;解密龙虎榜资金&#xff0c;跟踪一线游资和机构资金动向&#xff0c;识别短期热点和强势个股。 一&#xff0e;市场情绪 指数今日窄幅震荡&#xff0c;黄白二线分化明显&#xff0c;权重股力挺指数&#xff0c;题材小票走…

INA219电流感应芯片_程序代码

详细跳转借鉴链接INA219例程此处进行总结 简单介绍一下 INA219&#xff1a; 1、 输入脚电压可以从 0V~26V,INA219 采用 3.3V/5V 供电. 2、 能够检测电流&#xff0c;电压和功率&#xff0c;INA219 内置基准器和乘法器使之能够直接以 A 为单位 读出电流值。 3、 16 位可编程地…

《数字图像处理-OpenCV/Python》连载(50)非线性灰度变换

《数字图像处理-OpenCV/Python》连载&#xff08;50&#xff09;非线性灰度变换 本书京东优惠购书链接&#xff1a;https://item.jd.com/14098452.html 本书CSDN独家连载专栏&#xff1a;https://blog.csdn.net/youcans/category_12418787.html 第 7 章 图像的灰度变换 灰度变…

Unity | 渡鸦避难所-0 | 创建 URP 项目并导入商店资源

0 前言 知识点零零碎碎&#xff0c;没有目标&#xff0c;所以&#xff0c;一起做游戏吧 各位老师如果有什么指点、批评、漫骂、想法、建议、疑惑等&#xff0c;欢迎留言&#xff0c;一起学习 1 创建 3D&#xff08;URP&#xff09;项目 在 Unity Hub 中点击新项目&#xff…

【ESP32】手势识别实现笔记:红外温度阵列 | 双三次插值 | 神经网络 | TensorFlow | ESP-DL

目录 一、开发环境搭建与新建工程模板1.1、开发环境搭建与卸载1.2、新建工程目录1.3、自定义组件 二、驱动移植与应用开发2.1、I2C驱动移植与AMG8833应用开发2.2、SPI驱动移植与LCD应用开发2.3、绘制温度云图2.4、启用PSRAM&#xff08;可选&#xff09;2.5、画面动静和距离检测…

SSM框架详解:结构创建与注解应用

文章目录 1. 引言2. SSM框架项目结构创建2.1 目录结构2.2 说明 3. 注解的应用3.1 Controller3.2 Service3.3 Repository3.4 Autowired3.5 RequestMapping3.6 Select、Insert等 4. 结语 &#x1f388;个人主页&#xff1a;程序员 小侯 &#x1f390;CSDN新晋作者 &#x1f389;欢…

专业级音频处理 Logic Pro X 中文 for Mac

Logic Pro X是一款专业音频制作和音乐创作软件。它是Mac电脑上最受欢迎和广泛使用的音频工作站&#xff08;DAW&#xff09;。Logic Pro X提供了丰富的功能和工具&#xff0c;适用于音乐制作、录音、编辑、混音和音频处理等方面。以下是Logic Pro X软件的一些主要特点和功能&am…

怎么取消苹果订阅自动续费?分享3个可行方法!

在日常生活中&#xff0c;我们经常会使用到各种应用程序或服务&#xff0c;其中很多都提供了订阅自动续费的功能。然而&#xff0c;有时候用户可能会忘记取消订阅&#xff0c;从而导致不必要的扣费&#xff0c;给用户带来麻烦和困扰。 那么&#xff0c;对于使用苹果手机的小伙…

【JUC】十八、happens-before先行发生原则

文章目录 1、先行发生原则happens-before2、happens-before总原则3、8条happens-before规则4、案例 1、先行发生原则happens-before 在Java中&#xff0c;Happends-Before本质上是规定了一种可见性&#xff0c; A Happends-Before B&#xff0c;则A发生过的事情对B来说是可见的…

Discuz论坛自动采集发布软件

随着网络时代的不断发展&#xff0c;Discuz论坛作为一个具有广泛用户基础的开源论坛系统&#xff0c;其采集全网文章的技术也日益受到关注。在这篇文章中&#xff0c;我们将专心分享通过输入关键词实现Discuz论坛的全网文章采集&#xff0c;同时探讨采集过程中伪原创的发布方法…

.net-去重的几种情况

文章目录 前言1. int 类型的list 去重2. string类型的 list 去重3. T泛型 List去重4. 使用HashSet List去重5. 创建静态扩展方法 总结 前言 .net 去重的几种情况 1. int 类型的list 去重 // List<int> List<int> myList new List<int>(){ 100 , 200 ,100…

Selenium定位元素的方法css和xpath的区别!

selenium是一种自动化测试工具&#xff0c;它可以通过不同的定位方式来识别网页上的元素&#xff0c;如id、name、class、tag、link text、partial link text、css和xpath。 css和xpath是两种常用的定位方式&#xff0c;它们都可以通过元素的属性或者层级关系来定位元素&#…