UI2CODE系列文章|如何批量制造高质量样本

简介: 作者:闲鱼技术-楚丰在 UI2CODE 项目中,我们大量使用了深度学习方法来做一些物体检测。而深度学习模型的训练,避免不了需要大量的样本,因此如何制造大量样本,来满足模型训练需要是我们必须要解决的一个问题。

作者:闲鱼技术-楚丰

在 UI2CODE 项目中,我们大量使用了深度学习方法来做一些物体检测。而深度学习模型的训练,避免不了需要大量的样本,因此如何制造大量样本,来满足模型训练需要是我们必须要解决的一个问题。在这篇文章中,我们将介绍我们如何利用工具,批量泛化出大量样本,为模型训练提供数据保障。

1.样本现状

我们的模型要解决的问题是在一个设计稿图片上识别出基础控件等信息,包括位置和类别。而它所需要的样本,主要存在两个问题:

  1. 数据量少:一个APP的页面是有限的,特别是针对单个APP做优化适配的时候,页面的数量是相对较少的,可能在几十到上百个。而模型的对样本数量的需求是巨大的,特别像较为复杂的模型,对数据量的要求至少是万级别的,单靠真实样本,是远远达不到要求的。
  2. 标注成本高:物体检测的样本标注,不仅需要标注物体的类别,更需要标注出物体的具体位置,而一个样本上会存在多个物体标注。因此,这类样本打标成本非常大。

2.样本获取途径

获取样本,主要有几种途径。

image.png

对于真实样本,这类质量是最高的,要想训练出效果很好的模型,这类样本基本是必不可少的,但是由于这类样本数量少,成本高,因此还需要其他方法来补充样本量。

对于数据增广,这种方法简单快速,但是效果也有限,特别是对于我们 UI2CODE 里识别控件这个任务来说,做旋转等操作基本是无效的。

因此,我们需要利用样本Mock,来扩充我们的数据量,尽量模拟出质量又多,量又大的样本。这里我们选择的是利用Weex页面来进行样本的Mock泛化。(当然还有一些其它方法,比如利用 Android 的特性,在运行时的APP页面,抓取页面数据,经过过滤和清洗,得到带标注的样本,这里不做展开)

3.WEEX页面样本泛化

在这里,我们介绍如何利用 Weex 页面,来批量泛化样本,并且得到样本标注的方法。

前端页面特点

之所以选择使用前端页面来生成样本,是因为前端页面更多的是做一些数据展示,并且其拥有完整的 DOM 树,只要我们拿着DOM树就可以解析出里面的各个元素。

对于节点内容,只要我们改变元素内容即可。这样我们就可以由一个前端页面很方便地泛化出不同文字、不同图片的多个样本。

当然,我们的闲鱼APP上有大量的Weex活动页,这也是我们选择做Weex页面泛化的原因之一。

泛化思路

我们需要的基础控件的分类有“文本”、“图片”、“Shape”这三类,对于一个页面来说,我们的文本和图片内容基本都是可替换的,因此我们解析出所有节点以后,对里面的文本和图片进行替换,再进行渲染就可以得到新的样本。

利用 Puppeteer 实现泛化

要想得到Weex页面,需要有一个渲染容器,并且我们可以很方便地修改其内容。这里,我们选择了Google的Puppeteer,它是Google推出的可以运行 Chrome Headless 环境以及对其进行操控的js接口套装。通过它,我们可以模拟一个Chrome运行环境,并且进行操控。官方简介在这里.

首先启动一个不带界面的浏览器:

const browser = await puppeteer.launch({
    headless: true
});

启动一个页面,然后打开一个网站:


const page = await browser.newPage();
await page.goto(nowUrls, {waitUntil: ['load','domcontentloaded','networkidle0']});
    

模拟IPhone6环境:

await page.emulate({
    'name': 'iPhone 6',
    'userAgent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1',
    'viewport': {
      'width': 750,
      'height': 1334,
      'deviceScaleFactor': 1,
      'isMobile': true,
      'hasTouch': true,
      'isLandscape': false
    }
});
    

搜索所需控件:

let d_root = document.querySelectorAll('.weex-root');
let nodes_root = [];
collectChildren(d_root, nodes_root);

/**
* 遍历节点,搜集所有需要的控件
*/
function collectChildren(d, _nodes) {
    for(var i = 0,l = d.length;i < l;i++){
        let hasPushed = false;
        //nodeType === 1 时 push
        if (d[i].nodeType !== 1 && d[i].nodeType !== 3) {
            continue;
        }
        if(d[i].style){
            let backgrounColorValue = d[i].style['background-color'];
            if(backgrounColorValue && backgrounColorValue !== 'rgb(255, 255, 255)' &&  backgrounColorValue !== 'rgb(0, 0, 0)' && backgrounColorValue !== 'transparent'){
                _nodes.push(d[i]);
                hasPushed = true;
            }
        }
        if(d[i].hasChildNodes()){
          collectChildren(d[i].childNodes, _nodes);
        }else{
            let _node = d[i];
            let _className = _node.className;
            if(!_className && _node.nodeName === '#text'){
                _className = _node.parentNode.className;
            }
            if(_className && !hasPushed){
                if(_className.indexOf('weex-text') > -1 || _className.indexOf('weex-image') > -1){
                    _nodes.push(d[i]);
                }
            }
        }
    }
    return _nodes;
}

获取控件信息:

/**
* 获取 基础视图元素的属性
*/
function getRealyStyle(node,attrKey){
    let wvStyle = window.getComputedStyle(node);
    if(node[attrKey] && node[attrKey] !== ''){
        return node[attrKey];
    }else{
        return wvStyle[attrKey]
    }
}

/**
* 获取 基础视图元素的位置
*/
function getViewPosition(node){
    const {top, left, bottom, right} = node.getBoundingClientRect();
    return {
        "y": top,
        "x": left,
        "height": bottom-top,
        "width": right-left
    }
} 

获取页面图片:

await page.screenshot({
    path: pngName,
    fullPage : true
});

清理数据:

部分页面会存在弹窗的情况(mask图层),而我们的标注规则是希望只标注上面的图层,因此还需要根据mask图层的位置和大小,过滤掉底下图层里的控件。

通过上述方法,我们就能得到各个文本、图片、Shape以及他们的位置和属性等。基于位置和控件类别信息,我们就能够得到带有位置和类别标注的样本。

泛化文本和图片

通过上面的方法,只要提供一个Weex页面的url,就可以获取到一个带有标注的真实样本,后面我们只要修改里面文本和图片节点的内容,就可以批量泛化出多个样本。这些样本基于真实的页面布局,质量相对较高,并且可以随意控制泛化比例,比如设置 1:10,就可以有100分样本生成出10000份,大大提高了样本量。

5. 总结

通过Weex泛化样本的方法,我们由100多个Weex活动页,泛化出10000+个样本,并且无需手动打标,节省了大量的打标成本。且由于样本质量相对较高,模型的准确率得到了很大的提升。当然,我们也探索了很多其它方法,包括抓取Android运行时的页面数据来生成自动打标的数据,以及利用已训练模型自动预打标来节省手动打标的人力成本等,未来我们还会继续探索更多的样本生成及自动打标方法,为模型训练提供更多有用数据。

相关文章
|
4月前
|
人工智能 监控 Serverless
函数计算产品使用问题之sdXL 1.0模型启动无效,该怎么办
实时计算Flink版作为一种强大的流处理和批处理统一的计算框架,广泛应用于各种需要实时数据处理和分析的场景。实时计算Flink版通常结合SQL接口、DataStream API、以及与上下游数据源和存储系统的丰富连接器,提供了一套全面的解决方案,以应对各种实时计算需求。其低延迟、高吞吐、容错性强的特点,使其成为众多企业和组织实时数据处理首选的技术平台。以下是实时计算Flink版的一些典型使用合集。
|
5月前
|
API 开发工具 git
大事件项目26---文章分类——铺设数据
大事件项目26---文章分类——铺设数据
|
6月前
GEE——Google dynamic world中在影像导出过程中无法完全导出较大面积影像的解决方案(投影的转换)EPSG:32630和EPSG:4326的区别
GEE——Google dynamic world中在影像导出过程中无法完全导出较大面积影像的解决方案(投影的转换)EPSG:32630和EPSG:4326的区别
123 0
|
5月前
|
机器学习/深度学习 人工智能 监控
人工智能平台PAI产品使用合集之设置了7个特征,但在最后生成的数据表中只包含了6个id_feature的特征,是什么导致的
阿里云人工智能平台PAI是一个功能强大、易于使用的AI开发平台,旨在降低AI开发门槛,加速创新,助力企业和开发者高效构建、部署和管理人工智能应用。其中包含了一系列相互协同的产品与服务,共同构成一个完整的人工智能开发与应用生态系统。以下是对PAI产品使用合集的概述,涵盖数据处理、模型开发、训练加速、模型部署及管理等多个环节。
|
6月前
|
算法 异构计算
基于直方图的图像曝光量分析FPGA实现,包含tb测试文件和MATLAB辅助验证
该内容包括了算法的运行效果展示、软件版本信息、理论概述和核心程序代码。在正常图像中,`checkb`位于`f192b`和`f250b`之间,而多度曝光图像中`checkb`超出此范围,判断为曝光过度。使用的软件为Vivado 2019.2和MATLAB 2022a。理论依据未详细给出,但提及主要方法。提供的Verilog代码段用于处理图像数据,包括读取文件、时钟控制及图像histogram计算等,其中模块`im_hist`似乎是关键部分。
|
6月前
|
机器学习/深度学习 数据可视化 数据挖掘
R语言响应面(RSM)、线性模型lm分析生产过程影响因素可视化
R语言响应面(RSM)、线性模型lm分析生产过程影响因素可视化
|
6月前
|
人工智能 数据可视化 算法
AI Earth ——开发者模式案例3:典型植被指数计算及区域统计
AI Earth ——开发者模式案例3:典型植被指数计算及区域统计
163 1
|
文字识别 算法 测试技术
DeepSORT再升级 | Deep OC-SORT引入目标外观信息,大幅领先SOTA
DeepSORT再升级 | Deep OC-SORT引入目标外观信息,大幅领先SOTA
1023 0
|
XML 机器学习/深度学习 算法
数据倍化术——提升数据数量同时满足小目标图像构建
数据倍化术——提升数据数量同时满足小目标图像构建
73 0
数据倍化术——提升数据数量同时满足小目标图像构建
ML之FE:基于load_mock_customer数据集(模拟客户)利用featuretools工具实现自动特征生成/特征衍生
ML之FE:基于load_mock_customer数据集(模拟客户)利用featuretools工具实现自动特征生成/特征衍生
ML之FE:基于load_mock_customer数据集(模拟客户)利用featuretools工具实现自动特征生成/特征衍生