password
URL
type
status
date
slug
summary
tags
category
icon
周起始
标签
是否汉化
1. 为什么要进行测试
对于机器学习项目,需要解决如下疑问:
- 模型能力达到什么样的标准才可以部署到生产环境中?
- 如何设计测试用例才能以最小的成本完成上述标准的测试?
- 如何获取测试数据?
- 训练数据是不是和测试数据完全不一致?其质量如何?
- 测试数据能否很好地反映出模型的能力?
- 如何评估特征的质量?
- 模型的性能和健壮性是否良好?
- 模型上线后,测试工程师如何跟踪模型的效果?
这些答案的获取,需要充分的测试工作。
2. 机器学习测试与传统软件测试的不同
- 数据依赖性:
- 机器学习模型的性能高度依赖于训练数据的质量和多样性,而传统软件测试主要关注代码的正确性。
- 非确定性:
- 机器学习模型可能存在随机性,如初始化参数的随机性,导致每次训练的结果可能不同。
- 评估指标:
- 机器学习测试通常使用特定的评估指标(如准确率、召回率)来衡量模型性能,而传统软件测试侧重于功能覆盖和代码正确性。
- 模型泛化能力:
- 机器学习测试需要评估模型在未见数据上的泛化能力,而传统软件测试更多关注已知场景和用例。
3. 测试重点
机器学习系统的测试是一个复杂的过程,它不仅包括传统的软件测试,还涉及模型特定的测试。以下是机器学习测试的一些重点:
3.1 测试数据准备
目的:确保测试数据集的质量和多样性,以便准确评估模型性能。准备测试数据的方法有:
- 数据收集:收集足够的数据以覆盖模型在实际使用中可能遇到的各种情况。
- 数据清洗:清洗数据,移除错误、重复或不相关的数据点。
- 数据分割:将数据集分割为训练集、验证集和测试集,以进行不同的测试阶段。
- 数据增强:在必要时,通过旋转、缩放、裁剪等方法增加数据多样性,特别是在图像处理中。
- 数据标注:确保数据集正确标注,特别是在监督学习中。
3.2 特征质量测试
目的:验证输入特征的有效性和相关性,以确保模型能够学习到正确的信息。
测试点:
- 特征阈值:检查特征值是否都在值域内。
- 特征选择:测试是否选择了最有用的特征进行模型训练。
- 特征分布:检查特征的分布是否符合模型的假设,如正态分布。
- 缺失值处理:测试缺失值的处理方法是否得当。
- 异常值处理:评估异常值的处理策略,如删除、替换或使用模型估计。
- 特征编码:验证类别特征是否正确编码,如使用独热编码。
- 特征缩放:测试特征缩放(如归一化或标准化)的效果,特别是对距离敏感的算法。
测试方法:
- 单元测试:特征计算一般比较繁琐,需要通过对相关代码进行单元测试。
- 代码走查:手动和自动化的方式对计算特征的代码进行审查,如静态代码工具评估代码质量。
3.3 模型质量测试
目的:评估模型的性能、泛化能力和健壮性。
- 性能评估:使用适当的评估指标(如准确率、召回率、F1分数)来测试模型的性能。
- 泛化能力:通过交叉验证和独立的测试集来评估模型的泛化能力。
- 过拟合/欠拟合:检查模型是否存在过拟合或欠拟合的问题。
- 超参数调优:测试不同的超参数设置对模型性能的影响。
- 模型健壮性:评估模型对输入噪声、异常值和对抗性样本的敏感性。
- 公平性和偏见:检查模型是否存在潜在的偏见或不公平性。
- 预测效率:对于需要实时预测的模型,测试其在实际部署环境中的性能。
4. 测试难点
机器学习与传统软件不同,后者的行力基于不同的输入预先确定。在传统软件中,运算逻辑是一开始就确定好的,给定一个输入便会有相应确定的输出,输出是否正确,我们可以手动根据运算逻辑来检查。而在机器学习中,输入的是数据及其标签,输出的是模型,模型对新数据进行预测。模型的训练基于大量数据,且训练过程是黑盒形式的,无法人工检验其训练效果。
概括来说,模型测试的难点集中在以下几点:
- 测试数据问题
- 难以获取丰富的、高质量、无偏差的训练数据集。
- 特征质量问题
- 需要进行反复的特征工程工作,确保选择的特征能够达到最好的效果。
- 结果难以验证
- 由于模型训练是黑盒子,无法确认输入对应的输出是否符合逻辑
- 线上效果偏差
- 线上模型预测效果随着新数据的增加,模型效果会产生偏差,需要及时跟踪并进行模型优化调整。
1. 测试数据准备
对于测试人员,如何收集到符合场景要求的数据以及如何保证这些数据的质量,是进行机器学习项目测试的重要基础,也是占用测试人员时间最多的环节。 所以虽然我们是在测试 AI,但实际上我们掌握的最多的技能却是数据处理相关的,比如 spark, flink,opencv,ffmpeg 等等。
1.1 结构化数据
1.2 文本数据
1.3 图片数据
1.4 视频数据
数据测试集准备
对于测试人员,如何收集到符合场景要求的测试数据以及如何保证这些数据的质量,是进行机器学习项目测试的重要基础,也是占用测试人员时间最多的环节。通常数据准备分为:数据采集和挖掘、数据标注两个环节。
1. 数据采集和挖掘
在进行效果测试工作时,我们需要根据业务规则从海量的数据中筛选出符合特定测试场景要求的数据。效果测试时要采集到足够的数据,可能要面对数以百万,千万甚至亿的数据量,这样才能更全面的评估模型针对不同场景的效果。
1.1 结构化数据
百万,千万甚至亿的数据量情况下,我们熟悉的pandas 库就无法满足数据处理的要求了,需要用到分布式计算框架Spark。Spark 在结构化数据中能适应绝大多数的数据存储系统。 并且它也有 Dataframe 和 SQL 两种高级 API 供用户选择, 喜欢 SQL 的同学可以用 SQL,喜欢 Pandas 风格的同学可以使用 Dataframe。
例如,筛选性别为男性,年龄大于30的人员作为评测集。
1.2 图像数据
对于图片数据集, 相关法规和行业规则下,我们不能随便去网络上爬人的图片的,因为人是有隐私的。要提需求给数据组,数据组会找到安全合规的数据。 所以我们自己只能在已有的图片库里去筛选。
在结构化数据里每一列的意思都很清楚,我们可以通过简单的脚本就可以把我们需要的数据筛选出来。
但是从海量的图片中去筛选出符合我们场景需要的图片就没那么简单了,需要的是大量的人工筛选工作。不过我们也是有一些方法能尽量减少人工介入的成本。例如通过组合使用OpenCV 计算图片的相似度、YOLOV 模型识别目标、BLIP 模型识别细节目标的方式,进行海量图片筛选。
1.2.1 OpenCV计算图片的相似度
- 使用结构相似性指数
结构相似性指数(Structural Similarity Index,SSIM)是一种衡量两个图像相似度的指标,它考虑了图像的亮度、对比度和结构信息。SSIM的值范围在\[-1, 1]之间,值越接近1,表示两个图像越相似。
需要安装
scikit-image
库,因为OpenCV本身没有直接计算SSIM的函数,而scikit-image
库提供了这个功能。可以使用pip install scikit-image
命令安装。structural_similarity
函数返回两个值,第一个是SSIM值,第二个是差异图diff_map
(可选),差异图可以用于可视化两个图像之间的差异。- 使用直方图比较
直方图比较是通过比较两个图像的直方图来评估它们的相似度。直方图是图像像素强度分布的图形表示,如果两个图像的直方图相似,那么它们在视觉上可能也比较相似。
cv2.calcHist
函数用于计算图像的直方图,其中[0]
表示只计算第一个通道(对于彩色图像,可以分别计算三个通道的直方图),None
表示不使用掩膜(即对整个图像计算直方图),[256]
表示直方图的bins数量,[0, 256]
是直方图的范围。cv2.compareHist
函数用于比较两个直方图,cv2.HISTCMP_CORREL
是比较方法,它计算两个直方图的相关性,返回值范围在\[-1, 1]之间,值越接近1,表示两个直方图越相似。- 使用特征匹配
特征匹配是通过检测图像中的特征点(如角点、边缘等),然后比较两个图像之间的特征点匹配程度来评估相似度。这种方法对图像的旋转、缩放等变化具有一定的鲁棒性。
首先使用特征检测算法(如SIFT、SURF、ORB等)检测两个图像的特征点,然后使用特征匹配算法(如BFMatcher、FLANN等)进行匹配,最后根据匹配点的数量和质量来评估相似度。以下是使用ORB和BFMatcher的Python代码示例:
cv2.BFMatcher
创建一个暴力匹配器,cv2.NORM_HAMMING
是距离度量方式,适用于ORB等二进制描述符,crossCheck=True
表示进行双向匹配检查,以提高匹配的准确性。通过匹配点数量与特征点总数的比值来简单评估相似度,这个比值范围在\[0, 1]之间,值越接近1,表示两个图像越相似。
1.2.2 YOLOv 模型识别目标
YOLOv(通常指YOLO系列的某个版本,如YOLOv5、YOLOv8等)是一种流行的目标检测模型,由Joseph Redmon和Ali Farhadi等人开发。YOLO的全称是You Only Look Once,其核心思想是将目标检测任务转化为一个回归问题,通过一个卷积神经网络直接在图像上进行推理,实现实时目标检测。
例如我们的评测集需要一些包含人体存在的图像。可以借助yolov模型来对收集到的图片进行筛选,通过yolov模型检测图片中是否有人体,从而把那些没有人体的图片过滤掉,只保留包含人体的图片,这样就能更高效地收集到我们需要的评测集。
确保已经安装了
ultralytics
(YOLOv8的官方库)等,并且确保你有合适的YOLOv8模型权重文件。我们来逐步解析一下
any(det[5] == 0 for det in results.xyxy[0].cpu().numpy())
:results.xyxy[0].cpu().numpy()
:results
是YOLOv8模型对图片进行检测后返回的结果对象。results.xyxy
是一个列表,其中包含了检测结果的张量(tensor),每个张量对应一个批次(batch)的图片检测结果。由于我们这里是一张一张图片进行检测的,所以results.xyxy
列表中只有一个元素,即results.xyxy[0]
。.cpu()
是将张量从可能在GPU上的计算设备移动到CPU上,以便后续可以在CPU上进行操作。.numpy()
是将张量转换为NumPy数组,方便进行Python原生的数组操作。
for det in results.xyxy[0].cpu().numpy()
:- 这是一个for循环,遍历
results.xyxy[0].cpu().numpy()
这个NumPy数组中的每一个元素。每个元素det
代表一个检测到的目标对象的信息,通常包含6个值:\[x1, y1, x2, y2, confidence, class],其中(x1, y1)和(x2, y2)是目标的边界框坐标,confidence是检测的置信度,class是目标的类别ID。
det[5] == 0
:det[5]
表示获取每个检测目标的类别ID。== 0
是判断类别ID是否等于0。在YOLO模型的预训练权重中,类别ID为0通常代表“人”(person)这个类别。
any(det[5] == 0 for det in results.xyxy[0].cpu().numpy())
:any()
是Python内置的一个函数,用于判断给定的可迭代参数中是否至少有一个元素为True。如果是,则返回True,否则返回False。det[5] == 0 for det in results.xyxy[0].cpu().numpy()
是一个生成器表达式,它会遍历每个检测目标,判断其类别ID是否为0(即是否为人体)。- 因此,整个
any()
函数的作用就是判断在所有检测到的目标中,是否存在至少一个类别ID为0(人体)的目标。如果存在,则has_person
变量的值为True,表示这张图片中检测到了人体;否则为False,表示没有检测到人体。
大家也可以到B站上搜索一下YOLO使用的视频教程。
1.2.3 BLIP模型识别细节
BLIP(Bootstrapping Language-Image Pre-training)是由Salesforce在2022年提出的一种多模态预训练模型,它是用 4 亿个文本 - 图片 配对来进行训练的模型, 原理上它把图片数据和文本数据分别编码后形成了特征向量,然后计算图片向量和文本向量的余弦相似度。这样它就建立了一个图像 - 文本的映射关系。
比如给定一个图片, 你可以让BLIP生成一个针对这个图片的文本, 也可以给定一个文本和图片,让BLIP 判断它们的匹配程度, 也可以做图片分类。
比如,我们需要一批人拿着手机的图片,或者拿着水杯的图片作为评测数据。我们可以利用BLIP 的图片理解能力,帮我们在图片库中找到符合要求的图片。
对于文本-图像检索任务,BLIP系列中的
blip-itm-base-flickr
模型是一个很好的选择。这个模型在Flickr30k数据集上进行了图像-文本匹配的训练,能够有效地进行文本检索图像或图像检索文本的双向检索功能。以下是一个使用
blip-itm-base-flickr
模型进行文本-图像检索的代码示例:在这个代码示例中,我们使用了
blip-itm-base-flickr
模型来计算每张图片与查询文本("人拿着手机")之间的匹配分数。如果匹配分数高于某个阈值(这里以0.5为例),则将该图片保存到输出文件夹中。你可以根据实际需求调整查询文本和阈值。1.3 视频数据
在计算机视觉领域中的模型,也是针对图片进行处理的,而不是视频。 业务上可能对接的是视频数据,但最终也需要针对视频流进行解码/抽帧/图像增强/预处理等操作后把一张张图片交给模型处理。 所以本质上模型处理的都是图片。
但在测试中我们是针对整个系统进行测试的,在现实项目中系统的数据往往对接各种各样的摄像设备进行采集的,比如路边的各种摄像头。 所以我们需要去模拟视频数据进行测试。 而这时候我们需要 ffmpeg 完成视频数据的制作。
1.3.1 视频合成
- 例如在制作教学视频时,可以将教师的讲解视频(前景)叠加到教学课件视频(背景)上,让观众同时看到教师的讲解动作和课件内容。
- 再如将一部电影的多个片段拼接起来,只要这些片段的编码格式相同,就可以快速完成合成。
- 比如让一张图片连续播放多少秒来模拟视频。
f image2
代表输入的格式,在这里我们输入的是一系列图片。r 1/10
设置帧率(FPS,每秒刷新的帧数,文章后面详细讲解),1/10 代表一帧图片会播放 10s 钟i %03d.jpg
设置输入图片的规则
1.3.2 裁剪视频
- 在制作短视频时,可能需要将原始视频中的一些特定画面(如人物特写、产品展示等)裁剪出来,以突出重点内容。比如从一个风景视频中裁剪出一个湖泊的画面,用于制作专门展示湖泊美景的短视频。
- 裁剪视频的播放时间
当视频中有冗长的开头或者结尾,或者只需要其中精彩的部分时,就可以使用这种方式裁剪。比如一个会议视频,只需要保留会议主题发言的部分,就可以通过裁剪时间来提取这部分内容。
1.3.3 视频拼接
- 适用于将多个视频片段(如一个系列讲座的不同部分)按照顺序拼接成一个完整的视频文件。这种方式在处理大量视频文件拼接时比较高效,因为它避免了重复的编码过程。
- 在拼接视频之前,对每个视频片段进行分辨率调整或者添加水印等操作。
1.4 文本数据
文本数据的采集是非常难的, 我们可以在网络上找到非常庞大的文本并建立语料库, 但是为这些文本生成标注就非常难了。 假设你的团队在构建一个大模型, 这需要非常庞大的 文本 - 答案 数据。 除了要从专业的论文和专业的人员中获取相关数据之外, 项目中往往也会用以下几种方法来构建数据集:
- 问答挖掘模型:根据给定的文本或对话,提取出一个或多个问题 + 答案对。
- 文本摘要模型:将较长的文本或对话转换成简短,流畅而准确的摘要。
- 权威模型借鉴:将文本输入到权威模型中(比如 gpt4),把权威模型输出的答案作为问题的答案。
也就是说,我们是用模型来去提取文本中的训练和测试数据。
2. 数据标注
标注数据为模型提供了“真实答案”,是衡量模型预测结果准确性的关键基准。例如,在一个垃圾邮件分类模型的评测中,评测数据集中的每封邮件都被标注为“垃圾邮件”或“非垃圾邮件”。模型会对这些邮件进行分类预测,通过将模型的预测结果与标注的真实类别进行对比,我们才能准确地计算出模型的准确率、召回率、精确率等性能指标。
在不同的应用场景中,数据标注的内容也不同。
例如,在推荐系统中,需要标注用户是否喜欢某个内容,这通常是一个二分类标注,比如用1表示喜欢,0表示不喜欢。在反欺诈系统里,需要标注数据是否为欺诈行为,同样是二分类标注。而在计算机视觉的目标检测场景中,标注工作更为复杂,不仅要标注图片中是否有目标物体,还需要标注出物体的具体坐标,如中心点坐标(x,y)和长度宽度(w,h),或者物体四个角点的坐标,这样才能让算法学会如何在图片中定位目标物体。
结构化数据的标注相对简单,只需要在数据表的对应列中填写相应的值即可。而对于图片数据,有专门的数据标注工具可以使用,这些工具能够帮助标注人员更方便、更准确地进行标注工作。
大多数时候数据标注的工作是不需要测试人员来做的,一般都会有专门标注组来做这些基础的事情。
2.1 结构化数据
结构化数据的标注是比较简单的,大多数时候就是一张表,可以设置一列叫做 target,将这个数据的标注信息写上去就可以了。 如下图是BBH数据集的date\_understanding子集内容。target就是标注的答案。

2.2 图片数据
针对图片数据,一般需要对应的工具来标记分类的位置信息。 业界有很多的开源工具可以做到这一点, 各个厂商也会有自研的数据标注平台。 这里以开源的 labelme 为例。
安装方法参考https://www.labelme.io/docs/install-labelme-pip
使用方法很简单,用户需要画出目标物体的位置并且告诉这个目标数据哪个分类。

然后它会把标注信息生成一个 json 文件:
参考资料
选择合适的性能测试指标
选择合适的性能评估指标取决于模型的类型和目标任务的特点。以下是一些基本的指导原则:
1. 分类模型
- 二分类问题:
- 准确率(Accuracy): 适用于样本均衡的情况。
- 精确度(Precision) 和 \\召回率(Recall)\\: 适用于类别不平衡的情况,特别是当假正例和假反例的代价不同。
- F1 分数(F1 Score): 综合考虑精确度和召回率,适用于类别不平衡。
- ROC 曲线和 AUC: 评估模型在不同阈值下的表现,适合所有类型的分类问题。
- 混淆矩阵(Confusion Matrix): 提供了模型预测的详细视图,包括真正例、假正例、真反例和假反例。
- 多分类问题:
- 多类别准确率: 所有正确预测的样本数占总样本数的比例。
- 宏平均(Macro-average) 和 微平均(Micro-average) 精确度、召回率和 F1 分数: 宏平均对每个类别分别计算指标,然后取平均;微平均先计算所有类别的总真正例、假正例和假反例,然后计算指标。
- 加权平均(Weighted-average) 精确度、召回率和 F1 分数: 考虑每个类别的样本数量,适用于类别不平衡的情况。
2. 回归模型
- 均方误差(MSE) 和 \\均方根误差(RMSE)\\: 衡量预测值与实际值之间的平均误差。
- 平均绝对误差(MAE): 预测误差的绝对值的平均,对异常值的敏感度较低。
- R² 分数(R-squared): 衡量模型的解释能力,即模型预测值与实际值的接近程度。
- 调整 R²: 考虑自由度对 R² 的调整,适用于比较不同复杂度的模型。
3. 聚类模型
- 轮廓系数(Silhouette Coefficient): 衡量聚类效果,值越大表示聚类效果越好。
- 戴维斯·库尔丁指数(Davies-Kirkpatrick Index): 考虑聚类内部的一致性和聚类之间的分离度。
- Calinski-Harabasz指数(Calinski-Harabasz Index): 衡量聚类内部的一致性和聚类之间的分离度。
4. 异常检测模型
- 真正例率(True Positive Rate) 和 \\假正例率(False Positive Rate)\\: 衡量模型在检测异常时的准确性。
- ROC 曲线和 AUC: 评估模型在不同阈值下的表现。
5. 推荐系统
- 准确率(Accuracy): 预测正确的推荐数量占总推荐数量的比例。
- 召回率(Recall): 预测正确的推荐数量占实际推荐数量的比例。
- 覆盖率(Coverage): 推荐系统能够推荐的物品数量占总物品数量的比例。
- 新颖性(Novelty): 推荐系统推荐的物品与用户已知物品的差异性。
- 多样性(Diversity): 推荐列表中物品的差异性。
6. 深度学习模型
- 交叉验证: 评估模型的泛化能力,避免过拟合。
- 贝叶斯信息准则(BIC) 和 \\赤池信息准则(AIC)\\: 用于模型选择,考虑模型复杂度和拟合优度。
7. 强化学习模型
- 累积奖励(Cumulative Reward): 模型在一定时间内获得的总奖励。
- 策略损失(Policy Loss): 预测策略与最优策略之间的差异。
- 价值函数误差(Value Function Error): 预测价值函数与实际价值函数之间的差异。
选择指标时,还需要考虑任务的具体需求和数据集的特性,例如数据是否平衡、类别分布是否均匀等。有时候,可能需要结合多个指标来全面评估模型的性能。
离开乏味的皮囊,自由的灵魂在路上
- Name: Alan Hsu
- Tag: 随感、技术、经验、旅行、推荐、生活、音乐、电影 etc.
- Email:xulanzhong521gmail.com
- Twitter:@AlanHsu521
- Telegram:@AlanHsu521
- WeChat: Alan_Hsu_521
- Github: https://github.com/xsoway/
- Blog: https://xmylog.com


- Author:Alan_Hsu
- URL:https://xmylog.com/article/articles_MLTest_Test
- Copyright:All articles in this blog, except for special statements, adopt BY-NC-SA agreement. Please indicate the source!
Relate Posts