当前位置: 首页 > 后端技术 > Node.js

UI2CODE系列文章-如何批量生产高质量的样本

时间:2023-04-03 17:08:32 Node.js

在UI2CODE项目中,我们大量使用了深度学习的方法来做一些物体检测。深度学习模型的训练不可避免地需要大量的样本,那么如何让大量的样本满足模型训练的需要是我们必须要解决的问题。在本文中,我们将介绍我们如何使用工具对大量样本进行批量泛化,为模型训练提供数据保障。1.样本状态我们的模型需要解决的问题是识别设计稿图像上的基本控件等信息,包括位置和类别。至于它需要的样本,主要有两个问题:数据量小:一个APP的页面是有限的,尤其是对单个APP进行优化适配的时候,页面数量比较少,可能几十到数百。对模型样本数的需求是巨大的,尤其是比较复杂的模型,数据量要求至少10000条,单靠真实样本是远远不能满足要求的。标注成本高:物体检测的样本标注不仅需要标注物体的类别,还需要标注物体的具体位置,而且一个样本上会有多个物体标签。因此,标记此类样品的成本非常高。2.获取样本的方式获取样本的方式主要有以下几种。对于真实样品,这种质量是最高的。要训??练出一个效果好的模型,这类样本基本是必不可少的。但由于此类样本数量少、成本高,需要通过其他方法补充样本。数量。对于数据增广,这种方法简单快速,但是效果也有限,尤其是我们UI2CODE中识别控件的任务,旋转等操作基本无效。因此,我们需要使用samplemock来扩大我们的数据量,尽量模拟出高质量、大容量的样本。这里我们选择使用Weex页面来进行样本的Mock泛化。(当然还有其他方法,比如利用Android的特性,在运行时抓取APP页面的页面数据,过滤清洗,获取标记样本,这里不再展开)3.泛化WEEX页面示例这里介绍如何使用Weex页面批量泛化样本,获取样本标注。前端页面特点我们之所以选择使用前端页面来生成样本,是因为前端页面更多的是展示数据,它有完整的DOM树。我们只要拿着DOM树,就可以解析出里面的各种元素。对于节点内容,我们只要改变元素内容即可。这样一来,我们就可以很容易地从一个前端页面中泛化出不同文本和不同图片的多个样本。当然我们闲鱼APP上有大量的Weex活动页面,这也是我们选择泛化Weex页面的原因之一。泛化思路我们需要的基本控件的分类是“文字”、“图片”和“形状”。对于一个页面来说,我们的文字和图片内容基本上是可以替换的,所以我们解析出所有的节点之后,替换里面的文字和图片,然后渲染得到一个新的样本。使用Puppeteer实现泛化要得到Weex页面,我们需要一个渲染容器,我们可以很方便的修改它的内容。这里,我们选择了谷歌的Puppeteer,它是谷歌推出的一款可以运行ChromeHeadless环境并对其进行操作的js界面套件。通过它,我们可以模拟一个Chrome的运行环境,并对其进行操作。官方介绍在这里。首先启动一个没有界面的浏览器:constbrowser=awaitpuppeteer.launch({headless:true});开始一个页面,然后打开一个网站:constpage=awaitbrowser.newPage();等待page.goto(nowUrls,{waitUntil:['load','domcontentloaded','networkidle0']});模拟iPhone6环境:awaitpage.emulate({'name':'iPhone6','userAgent':'Mozilla/5.0(iPhone;CPUiPhoneOS11_0likeMacOSX)AppleWebKit/604.1.38(KHTML,likeGecko)版本/11.0移动/15A372Safari/604.1','viewport':{'width':750,'height':1334,'deviceScaleFactor':1,'isMobile':true,'hasTouch':true,'isLandscape':错误的}});搜索需要的控件:letd_root=document.querySelectorAll('.weex-root');letnodes_root=[];collectChildren(d_root,nodes_root);/***遍历节点并收集所有需要的控件*/functioncollectChildren(d,_nodes){for(vari=0,l=d.length;i-1||_className.indexOf('weex-image')>-1){_nodes.push(d[i]);}}}}return_nodes;}获取控制信息:/***获取基底层视图元素的属性*/functiongetRelyStyle(node,attrKey){letwvStyle=window.getComputedStyle(node);如果(节点[attrKey]&&节点[attrKey]!==''){返回节点[attrKey];}else{returnwvStyle[attrKey]}}/***获取基础视图元素的位置*/functiongetViewPosition(node){const{top,left,bottom,right}=node.getBoundingClientRect();return{"y":top,"x":left,"height":bottom-top,"width":right-left}}获取页面图片:awaitpage.screenshot({path:pngName,fullPage:true});清理数据:部分页面会有弹窗(遮罩层),而我们的标注规则是只标注上层,所以还需要根据位置和大小过滤掉下层的控件的掩模层。通过上面的方法,我们可以得到每一个文字、图片、Shape以及它们的位置和属性。根据位置和控制类别信息,我们可以得到标有位置和类别的样本。泛化文字和图片通过上面的方法,只要提供一个Weex页面url,就可以得到一个带注解的真实样本。后面我们只需要修改里面的text和picture节点的内容就可以泛化多个sample了。这些样本都是基于真实的页面布局,质量比较高,泛化比例可以随意控制。比如你设置1:10,你可以从100个样本中生成10000份拷贝,这样就大大增加了样本量。5.总结通过Weex归纳样本的方法,我们从100多个Weex活动页面中归纳出了10000+样本,而且不需要人工标注,节省了大量的标注成本。并且因为样本质量比较高,模型的准确率有了很大的提升。当然,我们也探索了很多其他的方法,包括抓取Android运行时页面数据生成自动标注数据,使用训练好的模型自动预标注节省人工标注的人工成本等等,未来我们会继续继续探索更多样本生成和自动标记方法,为模型训练提供更多有用数据。本文作者:闲鱼科技-楚枫阅读原文本文为云栖社区原创内容,未经允许不得转载。