答案是:可以。与传统测试相比,后者的测试对象、方法和策略都有很大不同。从传统的验证被测对象的实际结果和明确的预期结果,转向了基于测试集数据设计的算法模型指标验证和结果分析。
随着人工智能的快速发展和应用,如OCR识别、推荐算法、目标检测算法等。算法测试逐渐进入软件测试行业的视野。对于算法测试,传统的功能测试策略难以满足人工智能(AI)产品的质量保证,对测试提出了更高的要求。
结合人脸检测与检索算法的测试探索与实践过程,本文将从以下几个方面介绍人工智能(AI)算法的测试策略。
测试集数据准备
算法功能测试
算法性能测试
算法测试(模型评价指标)
算法结果分析
算法测试报告
我们将算法测试过程中的几个核心环节提炼到以上几点,构成了我们目前算法测试的测试策略。
测试集数据准备测试集准备对于整体算法测试非常重要。通常,在测试集准备过程中应考虑以下几点:
测试集的覆盖率
测试集的独立性
测试集的准确性
测试集的覆盖率
如果测试集准备只是随机选取测试数据,容易造成测试结果的失真,降低算法模型评估结果的可靠性。
像我们的功能测试,根据功能测试设计,我们为测试覆盖构建相应的数据。算法也是如此。至于人脸检测算法,除了选择正样本和负样本,还需要考虑人脸特征在正样本中的覆盖情况,如人脸比例、模糊度、光照、姿态(角度)、完整性(遮挡)等特征。
选择了相应的测试数据后,在后期的指标计算和结果分析中,需要对数据和相应的特征进行标注。以人脸检测为例,使用工具制作人脸图标的人脸坐标框图,并记录存储相应的特征,如下图所示。
此外,除了数据特征的覆盖,还需要考虑数据源的覆盖,结合实际应用环境和场景数据进行数据模拟和准备。比如公共场所摄像头下的人脸检索,图片一般比较模糊,图片的光照强度也不一样。所以在准备数据的时候,也需要根据这个场景来模拟数据。一般来说,最好以真实的生产环境数据作为测试数据,根据数据特征的分布从中选取测试数据。
另外,关于测试数据量,一般来说,测试数据越多,越能客观的反映算法的真实效果。但出于测试成本的考虑,不能穷尽。一般以真实生产环境为参考,选取20%。如果生产环境有大量数据,则选择1%~2%或更少。由于我们生产环境中的数据量巨大,考虑到测试成本,我们选取了大约2W的图像进行测试。
测试集的独立性测试集的独立性主要考虑测试数据集相互干扰导致测试结果失真的风险。
以我们的人脸检索为例,我们准备了200组人脸测试数据,每组都是同一个人在不同时期或角度的10张人脸照片。在计算人脸检索算法模型的指标时,比如计算TOP10的准确率,如果数据库中有上述200组人的其他照片,就会影响指标计算结果。例如,我们的200组人脸包括杰克,但数据库中除了杰克的10张照片外,还有其他8张。如果算法微服务接口返回的前10张图片包括我们测试集中的6张Jack图片,数据库中另外2张不在测试集中的Jack图片,2张非Jack图片,如何计算测试的准确率?根据我们的测试集(标注),准确率为60%,但实际准确率为80%,导致准确率指标计算结果失真。
因此,我们需要在准备测试集数据时考虑数据干扰,并在测试准备阶段评估数据库中的其他测试数据。比如从200组人脸测试数据中,我们进行一个预测试,判断相似度非常高的数据是否是同一个人,如果是,就从200组测试集中删除照片或者不删除这个人。
测试集的准确性数据集的准确性很容易理解。一般是指数据标注的准确性。比如杰克的照片不应该被贴上汤姆的标签,照片的模糊特征也不应该被贴上清晰的标签。如果数据标注错误,将直接影响算法模型指标的计算结果。
对于测试集准备,为了提高测试集准备的效率和可重用性,我们尝试构建一个算法数据仓库平台,可以实现数据(图片)的在线标注和存储功能,并作为算法测试数据的同一个接入点。
同时,测试集一般包括数据清洗操作。数据清洗是为了保证后续模型的索引结果、索引分析和特征分析的有效性,减少垃圾数据和干扰数据的影响。
算法测试,就我现在接触的人工智能系统而言,是以微服务接口的形式对外提供服务,类似于百度AI开放平台。
因此,需要对算法微服务接口的功能性进行验证,例如,结合应用场景,必需、非必需、参数组合验证等。应该从功能性、可靠性和可维护性的角度,以积极的、不同的方向进行测试。这里就不多介绍了。与常见的API接口测试策略一致,结合接口测试质量评价标准,从以下角度进行设计:
业务覆盖是否完整,业务规则覆盖是否完整,参数验证是否符合要求(边界、业务规则),接口异常场景覆盖是否完整,性能指标是否符合要求,安全指标是否符合要求。
算法微服务接口的性能测试众所周知。对于算法微服务,还需要进行性能测试,比如基准测试、性能测试(验证是否符合性能指标)、长短稳定性测试,这些都是算法微服务每个版本中要测试的内容。同时,横向比较不同版本的性能,感知性能变化。常见的指标有平均响应时间、95%响应时间、TPS以及GPU、内存等系统资源的使用情况。
Jmeter一般用于接口性能测试。但在实际应用中,为了整合算法微服务接口的功能测试和性能测试,从而降低自动化测试的开发、使用和学习成本,提高可持续性,我们基于关键字驱动和数据驱动的测试思路,利用Python Request和Locust模块实现了功能和性能自定义关键字的开发。每轮测试结束后,完成算法微服务功能自动化测试。如果函数执行通过,则自动拉起不同执行策略对应的性能测试用例,并将每次测试执行的结果存入数据库,从而输出不同版本算法微服务接口的性能指标对比结果。
算法评价指标
首先,不同类型的算法侧重于算法模型的不同评价指标。
比如人脸检测算法,经常用准确率、召回率、准确率、误报率来评价。人脸检索算法通常使用TOPN精确率、召回率和前N个连续正确率。
其次,同一类型的算法,在不同的应用场景下,评价指标是不一样的。
比如人脸检索应用于高铁站人脸比对(重点人员检索)时,并不太注重召回率,而是要求大量的准确性,避免抓错人,造成公共场所秩序混乱。但是在海量人脸检索的应用场景下,我们愿意牺牲一部分准确率来提高召回率,所以在这种场景下不能盲目追求准确率。
除了上述算法模型的评价指标外,ROC和PR曲线也常被用来衡量算法模型的效果。
在算法微服务的功能和性能测试中,介绍了我们采用了基于关键字驱动和数据驱动的测试思路,使用Python请求和蝗虫模块分别实现了功能和性能自定义关键字的开发。考虑到测试技术栈的统一性和可重用性,基于上述设计,我们实现了算法模型评价指标自定义关键字的开发,每次输出同一测试集下不同版本模型评价指标的横向比较。
当然,除了不同版本对比模型的评价指标对比,如果条件允许,还需要对比某些竞品,对比市场上相同和相似算法的差异,取长补短。
算法结果分析在对算法模型的指标进行评估后,我们不仅感知到了不同版本算法模型评估指标的差异,还希望进一步分析,得到具体算法模型优化的优化方向。这时候就需要结合数据的标注信息进行深入分析,发现算法的优劣是否受到哪些数据特征的影响,影响程度有多大。比如结合数据特征或者控制某些特征的一致性,可以看到其他特征对算法效果的影响程度等等。
这时候我们通常通过开发一些脚本来实现我们的分析过程,根据算法微服务接口的响应体和数据准备阶段标注的数据特征来开发分析脚本。
另外,索引结果的进一步分析也要结合算法设计,比如人脸检索算法,每张图片的检索过程是“输入图片的人脸检测”——;“输入图片的人脸特征提取”——;“相似特征检索”,通过这个查询过程,不难看出,人脸检索的整体准确率受到上述三个环节的影响,所以基于索引结果的深入分析也需要从这三个层面入手。
算法测试报告一般算法测试报告由以下要素组成:
算法功能测试结果
算法性能测试结果
模型评价指标结果
算法结果分析
因为算法微服务测试的复杂度比普通服务接口要高,所以报告要简明扼要。