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

基于 C# 的 AI 算法测试方法

基于 C# 的 AI 算法测试方法
在当今人工智能蓬勃发展的时代,AI 算法的质量和可靠性至关重要。对于使用 C# 开发的 AI 算法,我们需要一套有效的测试方法来确保其性能、准确性和稳定性。本文将详细探讨基于 C# 的 AI 算法测试方法,帮助开发者更好地验证和优化他们的算法。
一、测试框架的选择与搭建
NUnit 或 MSTest
C# 中有多种单元测试框架可供选择,NUnit 和 MSTest 是较为常用的两种。它们提供了丰富的断言和测试组织功能,方便我们编写和运行测试用例。
例如,使用 NUnit,我们可以创建测试类和测试方法,如下所示:

csharp
Copy
using NUnit.Framework;public class MyAIAlgorithmTests
{[Test]public void TestAlgorithmOutput(){// 这里编写测试算法输出的代码}
}

构建测试项目
为了进行有效的测试,我们通常会创建一个单独的测试项目。在 Visual Studio 中,可以右键解决方案,添加一个新的测试项目,并将相关的测试代码添加到该项目中。
测试项目可以引用包含 AI 算法的项目,以便访问和测试算法的类和方法。
二、数据准备与管理
数据集的选择
对于 AI 算法测试,合适的数据集是关键。可以选择公开的数据集,如 MNIST(手写数字图像识别数据集)、CIFAR-10(用于图像分类的数据集)等,这些数据集有已知的标签和标准结果,方便我们验证算法的准确性。
也可以根据算法的应用场景创建自定义数据集。例如,如果是开发一个用于文本分类的 AI 算法,可以收集相关的文本数据并进行标注。
数据预处理
在将数据输入到 AI 算法之前,通常需要进行预处理。这可能包括数据清洗(去除噪声、异常值等)、数据归一化(将数据值映射到特定范围)、数据分割(分为训练集、验证集和测试集)等操作。
C# 中有许多库可以帮助我们进行数据预处理,例如 Accord.NET 库提供了数据处理和分析的功能。
以下是一个简单的数据归一化示例:

csharp
Copy
using Accord.Math;public class DataPreprocessor
{public double[] NormalizeData(double[] data){double min = data.Min();double max = data.Max();return data.Select(x => (x - min) / (max - min)).ToArray();}
}

数据加载与管理
在测试过程中,我们需要高效地加载和管理数据。可以使用 C# 的文件读取功能来读取数据集文件,或者使用数据库来存储和检索数据。
如果数据集较大,可以考虑使用内存映射文件或分布式文件系统来提高数据加载速度。
例如,以下是使用 C# 的 File.ReadAllLines 方法读取文本数据文件的示例:

csharp
Copy
public class DataLoader
{public string[] LoadTextData(string filePath){return File.ReadAllLines(filePath);}
}

三、性能测试
算法执行时间测量
对于 AI 算法,执行时间是一个重要的性能指标。我们可以使用 C# 的 System.Diagnostics.Stopwatch 类来测量算法的执行时间。
以下是一个简单的示例:

csharp
Copy
using System.Diagnostics;public class PerformanceTester
{public double MeasureExecutionTime(Action algorithm){Stopwatch stopwatch = new Stopwatch();stopwatch.Start();algorithm();stopwatch.Stop();return stopwatch.Elapsed.TotalSeconds;}
}

在测试方法中,可以这样调用:

csharp
Copy
[Test]
public void TestAlgorithmPerformance()
{PerformanceTester tester = new PerformanceTester();double executionTime = tester.MeasureExecutionTime(() =>{// 调用 AI 算法进行计算MyAIAlgorithm algorithm = new MyAIAlgorithm();algorithm.Compute();});Assert.That(executionTime, Is.LessThan(1.0)); // 假设算法执行时间应小于 1 秒,可根据实际情况调整
}

内存使用分析
分析算法的内存使用情况可以帮助我们发现潜在的内存泄漏和优化内存消耗。.NET 提供了一些工具和 API 来监控内存使用。
可以使用 System.Runtime.MemoryFailPoint 类来模拟内存压力情况,检查算法在内存受限环境下的行为。
另外,使用性能分析工具,如 Visual Studio 的性能分析器,可以详细了解算法在运行过程中的内存分配和使用情况。
可扩展性测试
随着数据量和计算任务的增加,AI 算法需要具备良好的可扩展性。我们可以通过逐渐增加数据集的大小或计算复杂度,观察算法的性能变化。
例如,可以编写一个循环来多次运行算法,每次增加数据量,然后测量执行时间和内存使用,绘制性能曲线,以评估算法的可扩展性。
四、准确性测试
与基准算法比较
对于一些常见的 AI 任务,有一些成熟的基准算法可供参考。我们可以将自己开发的 AI 算法与基准算法在相同的数据集上进行比较,评估其准确性。
例如,在图像分类任务中,可以将自己的算法与传统的机器学习算法(如支持向量机、决策树等)或先进的深度学习算法(如 ResNet、VGG 等)进行比较。
使用准确率、召回率、F1 值等指标来衡量算法的性能。C# 中有一些库可以帮助我们计算这些指标,如 Accord.NET 的 Measures 类。
以下是一个计算准确率的示例:

csharp
Copy
using Accord.Math;
using Accord.Statistics.Models.Regression;
using Accord.Statistics.Models.Classification;public class AccuracyCalculator
{public double CalculateAccuracy(GeneralizedLinearModel model, double[][] inputs, int[] actualOutputs){int[] predictedOutputs = model.Decide(inputs);return Measures.Accuracy(actualOutputs, predictedOutputs);}
}

交叉验证
交叉验证是一种常用的评估算法准确性的方法。它将数据集分为多个子集,轮流将其中一个子集作为测试集,其余子集作为训练集,多次训练和测试算法,然后取平均值作为最终的评估结果。
C# 中可以手动实现交叉验证逻辑,也可以使用一些机器学习库提供的交叉验证功能。
以下是一个简单的手动实现的交叉验证示例:

csharp
Copy
public class CrossValidationTester
{public double CrossValidate(MyAIAlgorithm algorithm, double[][] data, int[] labels, int k){int n = data.Length;int foldSize = n / k;double totalAccuracy = 0.0;for (int i = 0; i < k; i++){int startIndex = i * foldSize;int endIndex = (i == k - 1)? n : (i + 1) * foldSize;// 划分训练集和测试集double[][] trainData = data.Take(startIndex).Concat(data.Skip(endIndex)).ToArray();int[] trainLabels = labels.Take(startIndex).Concat(labels.Skip(endIndex)).ToArray();double[][] testData = data.Skip(startIndex).Take(foldSize).ToArray();int[] testLabels = labels.Skip(startIndex).Take(foldSize).ToArray();// 训练算法algorithm.Train(trainData, trainLabels);// 测试算法并计算准确率int[] predictedLabels = algorithm.Predict(testData);totalAccuracy += CalculateAccuracy(predictedLabels, testLabels);}return totalAccuracy / k;}private double CalculateAccuracy(int[] predictedLabels, int[] actualLabels){int correctCount = 0;for (int i = 0; i < predictedLabels.Length; i++){if (predictedLabels[i] == actualLabels[i]){correctCount++;}}return (double)correctCount / predictedLabels.Length;}
}

异常值和边界情况处理测试
AI 算法在面对异常值和边界情况时可能会出现问题。我们需要专门设计测试用例来验证算法在这些情况下的表现。
例如,对于图像识别算法,可以测试一些模糊、变形或极端亮度的图像;对于数值计算的 AI 算法,可以测试极大值、极小值或特殊数值组合等边界情况。
在测试过程中,观察算法的输出是否合理,是否能够正确处理这些异常情况,或者是否有适当的错误处理机制。
五、模型验证与调优
参数调整
AI 算法通常有一些参数需要调整,如学习率、迭代次数、正则化参数等。我们可以通过实验不同的参数组合,观察算法的性能变化,找到最佳的参数设置。
可以使用网格搜索或随机搜索等方法来遍历参数空间。例如,以下是一个简单的网格搜索示例:

csharp
Copy
public class ParameterTuner
{public void GridSearch(MyAIAlgorithm algorithm, double[][] data, int[] labels, double[] learningRates, int[] iterationCounts){double bestAccuracy = 0.0;double bestLearningRate = 0.0;int bestIterationCount = 0;foreach (double learningRate in learningRates){foreach (int iterationCount in iterationCounts){algorithm.SetLearningRate(learningRate);algorithm.SetIterationCount(iterationCount);algorithm.Train(data, labels);int[] predictedLabels = algorithm.Predict(data);double accuracy = CalculateAccuracy(predictedLabels, labels);if (accuracy > bestAccuracy){bestAccuracy = accuracy;bestLearningRate = learningRate;bestIterationCount = iterationCount;}}}Console.WriteLine($"Best learning rate: {bestLearningRate}, Best iteration count: {bestIterationCount}, Best accuracy: {bestAccuracy}");}private double CalculateAccuracy(int[] predictedLabels, int[] actualLabels){int correctCount = 0;for (int i = 0; i < predictedLabels.Length; i++){if (predictedLabels[i] == actualLabels[i]){correctCount++;}}return (double)correctCount / predictedLabels.Length;}
}

模型评估指标的选择与分析
除了准确率等常见指标外,还有其他一些模型评估指标,如均方误差(MSE)用于回归问题、混淆矩阵用于分类问题等。根据 AI 算法的任务类型,选择合适的评估指标,并深入分析这些指标的含义和结果。
例如,对于一个预测房价的回归模型,可以计算 MSE 和平均绝对误差(MAE),并分析误差的分布情况,了解模型的预测偏差和精度。
以下是一个计算 MSE 的示例:

csharp
Copy
public class MSECalculator
{public double CalculateMSE(double[] predictedValues, double[] actualValues){double sumSquaredError = 0.0;for (int i = 0; i < predictedValues.Length; i++){double error = predictedValues[i] - actualValues[i];sumSquaredError += error * error;}return sumSquaredError / predictedValues.Length;}
}

可视化分析
可视化工具可以帮助我们更直观地理解算法的性能和结果。可以绘制算法的学习曲线(如训练误差和验证误差随迭代次数的变化)、ROC 曲线(用于分类问题的二分类器评估)、特征重要性图等。
C# 中有一些库可以用于数据可视化,如 Plotly.NET 等。通过可视化分析,我们可以发现算法的过拟合或欠拟合情况,以及特征对模型的贡献程度等信息。
以下是一个简单的使用 Plotly.NET 绘制学习曲线的示例(假设已经安装了 Plotly.NET 库):

csharp
Copy
using Plotly.NET;
using Plotly.NET.LayoutObjects;public class LearningCurveVisualizer
{public void PlotLearningCurve(double[] trainingErrors, double[] validationErrors, int[] iterationNumbers){var trace1 = new Scatter(){x = iterationNumbers,y = trainingErrors,mode = "lines+markers",name = "Training Error"};var trace2 = new Scatter(){x = iterationNumbers,y = validationErrors,mode = "lines+markers",name = "Validation Error"};var layout = new Layout(){title = "Learning Curve",xaxis = new XAxis() { title = "Iteration" },yaxis = new YAxis() { title = "Error" }};var chart = Chart.Combine(new[] { trace1, trace2 }, layout);chart.Show();}
}

六、持续集成与持续测试
集成到开发流程中
将 AI 算法测试纳入到持续集成(CI)和持续交付(CD)流程中,可以确保每次代码变更都能及时进行测试,快速发现问题并反馈给开发团队。
使用工具如 Jenkins、Azure DevOps 等,可以配置自动化测试任务,在代码提交或构建时自动运行测试用例。
例如,在 Azure DevOps 中,可以创建一个构建管道,添加测试任务,指定测试项目和测试框架,然后设置触发条件(如代码推送、定时构建等),使测试自动执行。
监控测试结果
建立监控机制,实时关注测试结果和指标。可以设置阈值,当测试指标超出预期范围时及时发出警报,以便开发人员及时采取措施。
使用电子邮件通知、即时通讯工具通知或在项目管理平台上显示警报信息等方式,确保相关人员能够及时获取到测试结果的变化情况。
例如,可以编写一个简单的脚本,定期检查测试报告文件,当发现准确率下降或执行时间增加等异常情况时,发送电子邮件通知相关人员。
七、总结
基于 C# 的 AI 算法测试是一个综合性的过程,涉及到测试框架的选择、数据准备、性能测试、准确性测试、模型验证与调优等多个方面。通过合理运用各种测试方法和工具,我们可以有效地发现算法中的问题,提高算法的质量和可靠性,为 AI 应用的成功部署提供保障。同时,持续集成与持续测试的实践可以确保算法在不断迭代和优化的过程中始终保持良好的状态。希望本文介绍的方法能为 C# 开发者在 AI 算法测试方面提供有益的参考和指导。

相关文章:

基于 C# 的 AI 算法测试方法

基于 C# 的 AI 算法测试方法 在当今人工智能蓬勃发展的时代&#xff0c;AI 算法的质量和可靠性至关重要。对于使用 C# 开发的 AI 算法&#xff0c;我们需要一套有效的测试方法来确保其性能、准确性和稳定性。本文将详细探讨基于 C# 的 AI 算法测试方法&#xff0c;帮助开发者更…...

Find My画框|苹果Find My技术与画框结合,智能防丢,全球定位

画框通常用于保护和固定艺术品&#xff0c;尤其是绘画作品。它是一种可以展示艺术品的框架&#xff0c;用于保护艺术品免受损坏或污染。艺术品被放置在画框内&#xff0c;可以避免受到空气、尘土和其他外部因素的损害。同时&#xff0c;画框还可以增强艺术品的展示效果&#xf…...

布谷语音源码服务器搭建环境及配置流程

布谷语音源码部署环境安装要求&#xff08;只有在相同的环境下才更容易避免一些不必要的麻烦&#xff09;&#xff1a;●安装Center OS 7.9&#xff0c;我们自己的服务器使用的是7.9建议相同系统&#xff0c;非强制●安装宝塔环境&#xff08;强烈推荐使用&#xff09;●安装软…...

算法|牛客网华为机试21-30C++

牛客网华为机试 上篇&#xff1a;算法|牛客网华为机试10-20C 文章目录 HJ21 简单密码HJ22 汽水瓶HJ23 删除字符串中出现次数最少的字符HJ24 合唱队HJ25 数据分类处理HJ26 字符串排序HJ27 查找兄弟单词HJ28 素数伴侣HJ29 字符串加解密HJ30 字符串合并处理 HJ21 简单密码 题目描…...

Tomcat servlet response关于中文乱码的经验

前言 最近修改老项目项目&#xff0c;使用zuul网关返回的中文内容乱码了&#xff0c;如果使用GBK或者GB2312编码确正常显示&#xff0c;稍微实验了一下&#xff0c;发现里面很多细节&#xff0c;毕竟Springboot对我们做了很多事情&#xff0c;而且当我们使用不同的模式会出现很…...

WebGIS开发丨从入门到进阶,全系列课程分享

WebGIS开发所需的技能 1.前端技能&#xff1a;Html、CSS、 Javascript、WebAPLs、Vue 2.二维技能&#xff1a;WebGIS基础理论及开发、MapGIS二次开发Openlayers、Leaflet、Mapbox 、Echarts、公共开发平台开发等 3.三维技能&#xff1a;Blender、Three.js、Cesium等 Web开发…...

C++ 模板专题 - 标签分派(Tag Dispatching)

一&#xff1a;概述: 在 C 中&#xff0c;Tag Dispatching 是一种编程技巧&#xff0c;主要用于在编译期根据不同的类型或特征选择不同的函数重载或代码分支。Tag Dispatching 借助类型标签&#xff08;tags&#xff09;进行函数调度&#xff0c;用于在模板中实现编译期的静态分…...

如何解决RabbitMQ消息的重复消费问题

什么情况下会导致消息的重复消费——在消费者还没成功发送自动确认机制时发生&#xff1a; 网络抖动消费者挂了 解决方案 每条消息设置一个唯一的标识id幂等方案&#xff1a;【Redis分布式锁、数据库锁&#xff08;悲观锁、乐观锁&#xff09;】 面试官&#xff1a;如何解决…...

Java调用chatgpt

目前openai的chatgpt在国内使用有一定难度&#xff0c;不过国内的大模型在大部分情况下已经不弱于chatgpt&#xff0c;而且还更便宜&#xff0c;又能解决国内最敏感的内容安全问题。本文后续以spring ai调用国内chatgpt厂商实现为例&#xff0c;讲解怎么构建一个java调用chatgp…...

将你的 Kibana Dev Console 请求导出到 Python 和 JavaScript 代码

作者&#xff1a;来自 Elastic Miguel Grinberg Kibana Dev Console 现在提供将请求导出到可立即集成到你的应用程序中的 Python 和 JavaScript 代码的选项。 你使用过 Kibana 开发控制台吗&#xff1f;这是一个非常棒的原型设计工具&#xff0c;可让你以交互方式构建和测试 El…...

成都世运会志愿者招募报名流程及证件照制作方法

成都世运会志愿者招募正在如火如荼地进行中&#xff0c;许多热心公益的青年们纷纷报名参与。本文将详细介绍如何通过官方渠道报名&#xff0c;并使用手机来自行制作符合要求的4:5比例的白底证件照。 一、志愿者报名流程概述首先&#xff0c;报名成都世运会志愿者需要通过官方指…...

大数据技术的前景如何?

在当今数字化迅猛发展的时代&#xff0c;大数据技术的前景显得尤为广阔。随着数据量的激增&#xff0c;如何有效利用这些数据成为了各行各业关注的焦点。未来五年&#xff0c;大数据技术的发展趋势可以从市场规模、技术融合、行业应用和政策支持等多个方面进行深入分析。 1. 市…...

LLM | 论文精读 | 基于大型语言模型的自主代理综述

论文标题&#xff1a;A Survey on Large Language Model based Autonomous Agents 作者&#xff1a;Lei Wang, Chen Ma, Xueyang Feng, 等 期刊&#xff1a;Frontiers of Computer Science, 2024 DOI&#xff1a;10.1007/s11704-024-40231-1 一、引言 自主代理&#xff08;…...

详解Redis相关缓存问题

目录 缓存更新策略 定期⽣成 实时⽣成 缓存淘汰策略 Redis内置缓存淘汰策略 缓存预热 缓存穿透 缓存雪崩 缓存击穿 缓存更新策略 定期⽣成 每隔⼀定的周期(⽐如⼀天/⼀周/⼀个⽉), 对于访问的数据频次进⾏统计. 挑选出访问频次最⾼的前 %N的数据. 实时⽣成 先给缓存…...

ubuntu 24 (wayland)如何实现无显示器远程桌面

ubuntu 24默认采用的是wayland而非x11&#xff0c;查过文档vnc对wayland的支持不是很好&#xff0c;折腾了好久&#xff0c;弄了一个如下的方案供参考&#xff1a; 硬件条件 需要一个显卡欺骗器或者可以接HDMI口作为视频信号源输出的设备。 将ubuntu的主机的HDMI输出接到该硬…...

《模拟电子技术基础》第六版PDF课后题答案详解

《模拟电子技术基础》第六版是在获首届全国优秀教材建设奖一等奖的第五版的基础上&#xff0c;总结6年来的教学实践经验修订而成的新形态教材。为满足国家人才培养的需求&#xff0c;适应新型教学模式&#xff0c;并考虑到大多数院校逐渐减少课程学时的现状&#xff0c;在不降低…...

python知识收集

文章目录 语法def声明函数class声明类class 子类(父类) 继承 数据结构列表列表操作 元组元组操作 字典遍历字典 集合 文件读写读文件写文件 csv模块读入写入 time模块发送邮件制作二维码滚动广告 语法 def声明函数 class声明类 class 子类(父类) 继承 数据结构 列表 列表…...

传奇996_3——使用补丁添加怪物

找素材&#xff0c;看素材是否是打包好的&#xff0c;没有的话就使用工具进行素材打包&#xff08;打包好后尽量别改名&#xff09;&#xff0c;并复制进客户端&#xff0c;D:\chuanqinew\996M2_debug\dev\anim\monster找到模型表cfg_model_info.xls&#xff0c;复制表中前几行…...

「Mac畅玩鸿蒙与硬件13」鸿蒙UI组件篇3 - TextInput 组件获取用户输入

在鸿蒙应用开发中,TextInput 组件用于接收用户输入,适用于文本、密码等多种输入类型。本文详细介绍鸿蒙 TextInput 组件的使用方法,包括输入限制、样式设置、事件监听及搜索框应用,帮助你灵活处理鸿蒙应用中的用户输入。 关键词 TextInput 组件用户输入输入限制事件监听搜索…...

MCU裸机任务调度架构

第1章 方式一(平均主义) int main(int argc, char **argv){/* RTC 初始化 */bsp_RTC_Init(&rtc);/* 串口初始化 */uartInit(115200);/* LED初始化 */ledInit();while(1){// 任务1(获取传感器数据)// 任务2// 任务3} } 1.1 平均主义的缺陷 获取传感器数据可以600ms去读取一…...

剑指offer20_链表中环的入口节点

链表中环的入口节点 给定一个链表&#xff0c;若其中包含环&#xff0c;则输出环的入口节点。 若其中不包含环&#xff0c;则输出null。 数据范围 节点 val 值取值范围 [ 1 , 1000 ] [1,1000] [1,1000]。 节点 val 值各不相同。 链表长度 [ 0 , 500 ] [0,500] [0,500]。 …...

Nginx server_name 配置说明

Nginx 是一个高性能的反向代理和负载均衡服务器&#xff0c;其核心配置之一是 server 块中的 server_name 指令。server_name 决定了 Nginx 如何根据客户端请求的 Host 头匹配对应的虚拟主机&#xff08;Virtual Host&#xff09;。 1. 简介 Nginx 使用 server_name 指令来确定…...

《基于Apache Flink的流处理》笔记

思维导图 1-3 章 4-7章 8-11 章 参考资料 源码&#xff1a; https://github.com/streaming-with-flink 博客 https://flink.apache.org/bloghttps://www.ververica.com/blog 聚会及会议 https://flink-forward.orghttps://www.meetup.com/topics/apache-flink https://n…...

dify打造数据可视化图表

一、概述 在日常工作和学习中&#xff0c;我们经常需要和数据打交道。无论是分析报告、项目展示&#xff0c;还是简单的数据洞察&#xff0c;一个清晰直观的图表&#xff0c;往往能胜过千言万语。 一款能让数据可视化变得超级简单的 MCP Server&#xff0c;由蚂蚁集团 AntV 团队…...

【Android】Android 开发 ADB 常用指令

查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...

HybridVLA——让单一LLM同时具备扩散和自回归动作预测能力:训练时既扩散也回归,但推理时则扩散

前言 如上一篇文章《dexcap升级版之DexWild》中的前言部分所说&#xff0c;在叠衣服的过程中&#xff0c;我会带着团队对比各种模型、方法、策略&#xff0c;毕竟针对各个场景始终寻找更优的解决方案&#xff0c;是我个人和我司「七月在线」的职责之一 且个人认为&#xff0c…...

LLaMA-Factory 微调 Qwen2-VL 进行人脸情感识别(二)

在上一篇文章中,我们详细介绍了如何使用LLaMA-Factory框架对Qwen2-VL大模型进行微调,以实现人脸情感识别的功能。本篇文章将聚焦于微调完成后,如何调用这个模型进行人脸情感识别的具体代码实现,包括详细的步骤和注释。 模型调用步骤 环境准备:确保安装了必要的Python库。…...

验证redis数据结构

一、功能验证 1.验证redis的数据结构&#xff08;如字符串、列表、哈希、集合、有序集合等&#xff09;是否按照预期工作。 2、常见的数据结构验证方法&#xff1a; ①字符串&#xff08;string&#xff09; 测试基本操作 set、get、incr、decr 验证字符串的长度和内容是否正…...

表单设计器拖拽对象时添加属性

背景&#xff1a;因为项目需要。自写设计器。遇到的坑在此记录 使用的拖拽组件时vuedraggable。下面放上局部示例截图。 坑1。draggable标签在拖拽时可以获取到被拖拽的对象属性定义 要使用 :clone, 而不是clone。我想应该是因为draggable标签比较特。另外在使用**:clone时要将…...

Flask+LayUI开发手记(八):通用封面缩略图上传实现

前一节做了头像上传的程序&#xff0c;应该说&#xff0c;这个程序编写和操作都相当繁琐&#xff0c;实际上&#xff0c;头像这种缩略图在很多功能中都会用到&#xff0c;屏幕界面有限&#xff0c;绝不会给那么大空间摆开那么大一个界面&#xff0c;更可能的处理&#xff0c;就…...