阿里99大促 | 模型识别背后的样本生成

背景

在上一篇文章详解阿里99大促活动页内容识别技术实现,我们介绍了在淘宝99大促中,我们使用了怎样的算法模型去识别并完成自动化测试的。

迫切解决的样本问题

淘宝大促有近百个模块、上千个页面,模块间具有相似性,并且模块内部具备多种状态,如果想要准确识别每个模块类型,单模块的样本数量至少要达到万级,而人工标注成本高、效率低下、数据量少,纯靠人力是无法满足模型诉求的。基于此,今天,我来介绍下,模型识别背后的大批量数据样本生成的技术方案。

思路

总体技术方案如下: 

模型的样本要求

算法模型识别的输入是99大促的各个会场截图,输出是目标模块名称及其在截图中的坐标位置。 

模型训练时,就是把模块渲染图、相应坐标位置与模块类型输入给模型,交给模型去进行监督学习。而模型需要的,就是各个模块大批量的图片样本。 

一个模块,是由View和ViewModel组合而成,而View是固定的,ViewModel跟随会场场景不同,是动态变化的。 

那么,如果我们能拿到描述模块的View的这一层DSL,辅助以动态的ViewModel数据,再把View和ViewModel渲染成图片,那我们就可以生成无穷无尽的样本数据了。

DSL描述View

仔细梳理之后,View拆分为原子级元素(Text、Image、Shape)和原子级元素的组合关系(Group),即与HTML DOM树状结构中的各层级容器嵌套与叶子节点类型是同样的逻辑。 
基于节点类型和节点样式的DSL,我们就能描述一个完整的View了。

{"layers": [{"frame": {"y": 354,"x": 44,"height": 32,"width": 312},"id": 2,"type": "text","value": "Adidas Stan Smith","textStyles": {"fontFamily": "Helvetica, sans-serif","fontSize": 24}}, {"frame": {"y": 0,"x": 384,"height": 342,"width": 342},"id": 3,"type": "image","value": "//img.alicdn.com/bao/uploaded/i1/TB1.mcuNpXXXXctXFXXSutbFXXX.jpg_350x350Q50s50.jpg_.webp","styles": {"height": 342,"width": 342}}, {"frame": {"y": 0,"x": 384,"height": 342,"width": 342},"id": 4,"type": "shape","styles": {"height": 342,"width": 342,"backgroundColor": "rgba(0, 0, 0, 0.1)"}}],"frame": {"y": 0,"x": 0,"height": 4920,"width": 750},"id": 1,"type": "group","moduleName": "pmod-zebra-recommand-item"
}

其中,除了节点类型和节点样式之外,最外层的moduleName代表模块名称,id是为了标记每一个子元素,frame是每个子元素的坐标位置、辅助算法模型识别模块内部子元素,value值只有text和image才有,对应相应的文本值还有图片链接。

获取模块View的DSL

有3种方案可以获取到模块View的DSL,分别是: 
1、从代码仓库中获取; 
2、从sketch视觉稿中生成; 
3、从浏览器渲染好的页面中获取。

我最后选择了第三种方案,放弃第一个方案是因为代码写法千差万别,很多展现逻辑还包含在js代码中,并且还要处理各种for循环子View、style的映射关系等等,复杂度太高。第二个方案目前集团内已有技术方案imgcook,这一块的准确率听说还不错,并且一直在持续优化,而最终选择第三个方案的原因是,能100%准确地还原模块DSL,并且只需要关注模块最终展现给用户时候的形态,不需要理会过程中开发者做得各种复杂业务逻辑,复杂度相对低很多。

技术方案

在开发流程上,每个模块在开发完成后,都会有对应的模块预览页面。我使用了puppeteer模拟真实浏览器,对模块的节点信息进行提取,并保存为规范的DSL。

清洗window.getComputedStyle

通过window.getComputedStyle获取DOM节点的样式,会返回包含280个样式属性的对象,如果把每个DOM节点的所有280个样式属性都存储到DSL中,会造成两个问题: 
1、DSL文件冗余,且文件大小过大,解析耗时; 
2、增加算法同学对DSL的理解和调整成本。

第一步,隐藏默认属性值; 
大部分的样式属性都是默认值,我们首先把默认的样式属性剔除出去。

{
alignSelf: 'auto',
...
}

第二步,剔除无效属性; 
开发者常用的样式属性在20个左右,有很多的样式是不具备实际效用的,把无效用的样式属性剔除掉,比如说:

{
zoom: '1',
writingMode: 'horizontal-tb',
...
}

第三步,transform动态计算 
通过getComputedStyle拿到的transform属性值是一个矩阵方法matrix(),感兴趣的同学可以戳这里理解下2D转换矩阵。我们使用puppeteer模拟浏览器设置的屏幕宽度是750,也就是说,得到的transform值中translateX和translateY两个值是以750为基准换算得到的一个数字,假如想要在下面描述到的将DSL渲染成图时(算法同学期望能模拟各种各样的屏幕尺寸去生成样本),就必须将获取到的transform值换算成相应屏幕设备时的值。

# 为了方便算法同学更好使用DSL渲染成图的工具,这里使用python来实现
# screenshotShape是一个数组,代表屏幕宽高  [width, height]
if 'transform' in style and 'matrix' in style['transform']:matrix = style['transform'][7:-1].split(',')translate = list(map(float, matrix[-2:]))translateResult =  list(map(str, [distance*(screenshotShape[0]/750) for distance in translate]))matrix[-2:] = translateResult

通过以上3个步骤,最终得到的DOM节点样式属性个数一般维持在20个以内,能使输出的DSL精简非常多。

DSL渲染成图片

同样的,我们能基于puppeteer去对页面做操作,也能使用它去把DSL渲染成目标模块页面,并截图。

首先,建立DSL与HTML标签的映射关系

其次,如果是DSL类型为Group,就递归遍历里面的所有子元素,以此类推。
完整的渲染流程图如下:

ViewModel动态数据

一个模块,应用到99大促、双十一等各种会场,背后样式都是一致的,只有对应的数据不同,动态的数据一般是商品图片和商品信息。 
闲鱼有一亿多的商品数据,如果把这商品数据拿过来与View一起渲染成模块,每个模块就有了成千上万种展现形态,且贴合算法模型实际识别过程中的输入,既能满足样本数量的要求,也能符合模型实际识别的场景,使模型准确率获得更大地提升。

效果

通过这样一条生成样本的通道,每个模块都能够提供给算法同学几万张质量很高的样本截图,使模型的准确率达到98%以上。

未来

上述文章描述了如何批量生成样本来帮助解决算法模型对99大促和双十一会场中各个模块的识别。

目前,对模块DSL的动态调整依赖算法同学对模块的理解,eg.改变圆角borderRadius生成更多正向样本,或者增加噪声,eg.删除商品内容节点等生成负向样本,这些操作都需要算法同学对DSL进行定制化配置。在未来,我们希望尝试把这部分的工作也交给模型去处理,让模型对样本生成做决策,调整DSL的局部,并生成样式更加丰富和可靠的样本。


原文链接
本文为云栖社区原创内容,未经允许不得转载。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/517869.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数组,下标越界及小结

数组,下标越界及小结 数组的四个基本特点 其长度是确定的。数组一旦被创建,它的大小就是不可以改变的。其元素必须是相同类型,不允许出现混合类型。数组中的元素可以任何数据类型,包括基本类型和引用类型。数组变量属引用类型&a…

这6种编码方法,你掌握了几个?

阿里妹导读:Don Roberts 提出的一条重构准则:第一次做某件事时只管去做;第二次做类似的事时会产生反感,但无论如何还是可以去做;第三次再做类似的事时,你就应该重构。 编码也是如此,当多次编写…

数组的使用

数组的使用 数组使用 普通的For循环 package com.boss.array;public class ArrayDemo04 {public static void main(String[] args) {int[] arrays{1,2,3,4,5};//打印全部的数组元素for (int i 0; i <arrays.length ; i) {System.out.println(arrays[i]);}System.out.pri…

扎根中国20年,F5“代码到用户”线上峰会盛大启幕

2020年5月20日&#xff0c;全球领先的多云应用服务厂商F5公司以线上峰会的形式开启了F5 2020 “代码到用户” 暨F5中国20周年纪念庆典&#xff0c;深入解读了F5“代码到用户” 的战略。F5全球首席执行官范仲林先生、F5全球首席科学家及首席技术官林耕先生、NGINX创始人Igor Sys…

Hadoop集群安装部署_伪分布式集群安装_01

文章目录一、配置基础环境1. 设置静态ip2. hostname3. firewalld4. ssh免密码登录5. JDK一、配置基础环境 1. 设置静态ip [rootbigdata01 ~]# vi /etc/sysconfig/network-scripts/ifcfg-ens33BOOTPROTO"static" IPADDR192.168.92.100 GATEWAY192.168.92.2 DNS1192.…

【从入门到放弃-ZooKeeper】ZooKeeper实战-分布式队列

前言 上文【从入门到放弃-ZooKeeper】ZooKeeper入门中&#xff0c;我们学习了ZooKeeper的简单安装和cli使用。 接下来我们开始基于java API的实战编程。本文先来写一个分布式队列的代码实现。 设计 我们来写一个先进先出的分布式无界公平队列。参考我们之前介绍的【从入门到…

Hadoop集群安装部署_伪分布式集群安装_02

文章目录一、解压安装1. 安装包上传2. 解压hadoop安装包二、修改Hadoop相关配置文件2.1. hadoop-env.sh2.2. core-site.xml2.3. hdfs-site.xml2.4. mapred-site.xml2.5. yarn-site.xml2.6. workers三、格式化与启动集群3.1. 格式化HDFS3.2. 启动伪分布集群3.3. 异常解决方案3.4…

在 520 这天,竟然有人把 Docker讲清楚了? | 原力计划

作者 | 夏目 "责编 | 王晓曼头图 | CSDN下载自东方IC出品 | CSDN博客简介1、了解Docker的前生LXCLXC为Linux Container的简写。可以提供轻量级的虚拟化&#xff0c;以便隔离进程和资源&#xff0c;而且不需要提供指令解释机制以及全虚拟化的其他复杂性。相当于C中的NameSp…

为什么它有典型FaaS能力,却是非典型FaaS架构?

阿里妹导读&#xff1a;FaaS—Function as a service&#xff0c;函数即服务。它是2014年由于亚马逊的AWS Lambda的兴起&#xff0c;而被大家广泛认知。FaaS能力是NBF中的一项非常重要的能力&#xff0c;NBF是一个非典型的FaaS架构&#xff0c;但是具备了典型的FaaS能力。文章将…

二维数组使用

二维数组使用 多维数组 多维数组可以看成数组的数组&#xff0c;比如二维数组就是一个特殊的一维数组&#xff0c;其每个元素都是一个一维数组。 二维数组 int a[][]new int[2][5];解析&#xff1a;以上二维数组a可以看成一个两行五列的数组思考&#xff1a;多维数组的使用…

如何解决90%的问题?10位阿里大牛公布方法

世界在变&#xff0c;技术在变&#xff0c;需求在变。 唯一不变的是变化。 面对变化&#xff0c;技术人如何在不确定性的世界中寻找最优解&#xff1f; 查理芒格说&#xff1a;“掌握一定数量的思维模型&#xff0c;能解决这世上90%的问题。”与其在重复的“增、删、改、查”…

Hadoop集群安装部署_分布式集群安装_01

文章目录1. 分布式集群规划2. 数据清理3. 基础环境准备4. 配置ip映射5. 时间同步6. SSH免密码登录完善7. 免密登录验证1. 分布式集群规划 伪分布集群搞定了以后我们来看一下真正的分布式集群是什么样的 看一下这张图&#xff0c;图里面表示是三个节点&#xff0c;左边这一个是…

今天,Python信息量很大!

小白程序员Python自学之痛&#xff1a;第一周找学习资源&#xff0c;第二周入门到放弃&#xff0c;第三周怀疑自己。明明10元钱就能搞定的事情&#xff0c;为什么要反反复复折磨自己呢&#xff1f;为了让用户用更优惠的价格买到优质的课程&#xff0c;CSDN和老师反复争取&#…

Arrays类解析

Arrays类解析 数组的工具类java.util.Arrays 由于数组对象本身并没有什么方法可以供我们调用&#xff0c;但API中提供一个工具类Arrays供我们使用&#xff0c;从而可以对数据对象进行一些基本的操作。 查看JDK帮助文档 Arrays类中的方法都是static修饰的静态方法&#xff0c…

闲鱼如何利用端计算提升推荐场景的ctr

背景 闲鱼作为一个电商场景的app&#xff0c;最丰富的部分就是作为商品宝贝浏览承载的feeds&#xff0c;比如首页下面的宝贝信息流&#xff0c;搜索结果页以及详情页下面的猜你喜欢&#xff0c;这些feeds场景都少不了推荐算法在背后的支撑。 传统的推荐算法是依托于云上沉淀的…

Hadoop集群安装部署_分布式集群安装_02

文章目录一、上传与 解压1. 上传安装包2. 解压hadoop安装包二、修改hadoop相关配置文件2.1. hadoop-env.sh2.2. core-site.xml2.3. hdfs-site.xml2.4. mapred-site.xml2.5. yarn-site.xml2.6. workers2.7. 修改启动脚本三、同步初始化3.1. 安装包同步3.2. 主节点格式化HDFS3.3.…

基于融合计算?蚂蚁金服的在线机器学习是如何做的

金融领域越来越多的活动场景&#xff0c;如双十一、双十二、财富日、新春大促&#xff0c;具有活动持续时间短强度高的特点&#xff0c;解决场景中的计算冷启动问题&#xff0c;优化系统效率和用户体验的需求越来越多。在生产环境的应用中&#xff0c;还需要满足高吞吐和端到端…

重要的节日那么多,要及时「缓存」你们的珍贵时光

作者 | 后端学长责编 | Carol出品 | 程序员 cxuan缓存概述在很久很久以前人类和洪水作斗争的过程中&#xff0c;水库发挥了至关重要的作用 : 在发洪水时可以蓄水&#xff0c;缓解洪水对下游的冲击&#xff1b;在干旱时可以把库存的水释放出来以供人们使用。这里的水库就起着缓存…

冒泡排序(重要)

冒泡排序&#xff08;重要&#xff09; 冒泡排序无疑是最为出名的排序算法之一&#xff0c;一共有八大排序&#xff01;冒泡代码还是相当简单的&#xff0c;两层循环&#xff0c;外层冒泡轮数&#xff0c;里层依次比较&#xff0c;江湖中人尽皆知。我们看到嵌套循环&#xff0…