前端代码是怎样智能生成的?

简介: 作为阿里经济体前端委员会四大技术方向之一,前端智能化项目经历了 2019 双十一的阶段性考验,交出了不错的答卷,天猫淘宝双十一会场新增模块 79.34% 的线上代码由前端智能化项目自动生成。在此期间研发小组经历了许多困难与思考,本次 《前端代码是怎样智能生成的》 系列分享,将与大家分享前端智能化项目中技术与思考的点点滴滴。

屏幕快照 2020-02-14 下午1.14.10.png

作者|莱斯
出品|阿里巴巴新零售淘系技术部

导读:作为阿里经济体前端委员会四大技术方向之一,前端智能化项目经历了 2019 双十一的阶段性考验,交出了不错的答卷,天猫淘宝双十一会场新增模块 79.34% 的线上代码由前端智能化项目自动生成。在此期间研发小组经历了许多困难与思考,本次 《前端代码是怎样智能生成的》 系列分享,将与大家分享前端智能化项目中技术与思考的点点滴滴。

概述

无线大促页面的前端代码中,存在大量的业务模块或业务组件(下文统称业务模块),即具有一定业务功能的代码单位。获取页面中业务模块的信息之后,可以用于复用代码、绑定业务字段等后续功能。因此从视觉稿识别出业务模块,在前端智能化领域中成为用途广泛的功能环节。

与面向中后台的基础组件识别和表单识别功能不同,业务模块识别主要面向无线端页面,并且来源主要是视觉稿。相对的,业务模块 UI 结构更加复杂,并且视觉稿提供的内容已经有较多可辨别的信息(如文本内容、图片尺寸等),因此我们没有直接使用图片深度学习的方案,而是从视觉稿产出的 DSL 中提取预定义的特征值,用传统学习多分类的方法来实现模块识别。本识别功能最终返回业务模块的类别、视觉稿中的位置等信息。

总体功能如下图所示。包括:

  • 样本构造,根据用户配置和自定义的数据增强规则对视觉稿进行 UI 层的增强,以得到视觉多样化的样本。然后在定义好业务字段的基础上,进行特征值抽取并存储。
  • 算法选择,目前提供的都是传统机器学习方法中的多分类算法。
  • 模型实现,基于集团机器学习平台实现模型搭建及相关算法工程,做到自动化训练与部署。
  • 接口提供,模型对外提供预测识别服务以及结果反馈服务。
    屏幕快照 2020-02-14 下午1.14.56.png

总体功能

所在分层

如下图所示,我们的业务模块识别服务位于物料识别层,为视觉稿导出的 DSL 提供进一步的业务定制化的识别能力,在后续代码生成的过程中渗透到字段绑定、业务逻辑等功能之中。

屏幕快照 2020-02-14 下午1.16.10.png

D2C 功能分层

样本构造

机器学习是基于大量真实数据的训练过程,一个好的样本库可以让你的模型训练事半功倍。我们的样本来源是视觉稿(Sketch),但同一个模块的 Sketch 视觉稿可能只有寥寥几张,可获取的样本数量过少。因此首先要解决量的问题。

▐ 数据增强
为解决样本数量问题,我们采用了数据增强的方法。数据增强有一套默认的规则,同时也是可配置的。用户可自行根据视觉稿上各个元素在真实场景中可能发生的变化,如“是否可隐藏”,“文本字数可变范围”等维度来调整属性,产出自定义的配置项。因此样本制作者可以清晰的知道自己所造样本侧重的差异点在哪里。

我们根据这些配置项对属性进行发散、组合,生成大量不同的视觉稿 DSL。这些 DSL 之间随机而有规律地彼此相异,据此我们可以获得大数量的样本。

增强配置的界面如下图所示,左侧与中部是 DSL 树及渲染区域,右侧就是增强配置的区域。配置项由以下 2 部分组成:

增强属性:尺寸、位置、隐藏、前景背景色、内容
增强方式:连续范围、指定枚举值

屏幕快照 2020-02-14 下午1.17.35.png

样本生成的界面

▐ 数特征提取
得到大量增强后的视觉 DSL 后,如何生成样本呢?首先明确我们所需的样本格式应该是表格型数据,以配合传统机器学习方法的输入格式:一条样本数据即一个特征向量。因此我们要对 DSL 进行特征提取。

基于此前的模型训练经验,我们发现某些视觉信息对于模块的类别判断尤为重要。因此我们对 UI 信息进行抽象,自定义并提取为特征维度,如 DSL 的宽、高、布局方向、包含图片数量、包含文本数量等。通过各种视觉信息的抽象,我们得到 40 多维的视觉特征。

除了视觉特征维度以外,我们还增加了自定义的业务特征。即根据一定的“业务规则”,将某些元素块定义为具有业务含义的元素,如“价格”、“人气”等,并抽象出 10 个维度的业务特征。在这一过程中同样支持用户自定义业务规则,可通过正则匹配等方式实现。

视觉抽象特征加上业务特征,组成一个特征向量。特征向量加上分类 label,即一个样本。

算法与模型

首先我们的输入是 Sketch 设计稿提取出的标准化 DSL,目标是认出该 DSL 是哪个业务模块,可以归结为一个多分类问题。沿着这一思路,前文我们从大量增强后的 DSL 中提取特征值、生成数据集以供训练。我们使用的多分类模型基于算法平台提供的各种组件进行搭建。

▐ 随机森林

模型搭建

最初我们选择随机森林模型作为多分类模型,因为随机森林的执行速度快、自动化流程顺畅,几乎无需额外操作就满足了我们算法工程的需求;并且对特征值处理的要求较低,会自行处理连续和离散变量,规则如下表所示。

屏幕快照 2020-02-14 下午1.18.42.png

随机森林变量类型自动解析规则

因此可以迅速的搭建出十分简洁的模型,如下图所示。

屏幕快照 2020-02-14 下午1.19.54.png

线上使用的随机森林模型

调参过程

我们发现随机森林对于样本库内的数据,偶尔会有不自信的情况发生,即 positive true 的置信度较低,被置信阈值卡住。尤其是视觉非常相似的样本,如图所示的两个相似模块就给我们的分类结果带来误差。

屏幕快照 2020-02-14 下午1.20.38.png

相似模块

为优化这种“不自信”的问题,我们对随机森林进行了调参,包括单棵树随机样本数、单棵树最大深度、ID3/Cart/C4.5 树的种类配比等参数,也预接入特征选择组件,效果均不理想。最终在特征值重要性评估后手动反馈到特征选择并重新训练这一链路中取得了较好的结果,如下图所示。但这一过程无法融入到自动化训练流程中,最终被我们放弃。

屏幕快照 2020-02-14 下午1.21.24.png

调参过程中使用过的随机森林模型

离散特征问题

随机森林虽然可以自动处理离散变量,但是如果测试集中出现了训练集以外的离散值,算法无法处理这样的情况。要解决这一问题,需确保每个离散特征的全部取值都出现在训练集中。由于有多个离散特征,也无法通过简单的分层采样来解决。这也是随机森林模型应用中的痛点之一。

综上是我们在随机森林模型上做的工作,随机森林简单易上手、快速出结果,并且在大多数业务场景下都能满足识别需求,成为模块识别功能的 1.0 版本算法。但由于其算法缺陷,我们后来引入了另一种模型 XGBoost。

▐ XGBoost 多分类

模型搭建

XGBoost 通过 Boosting 的方法提升树的“准确率”,相较于随机森林算法在我们的数据集上表现更优越。但是算法平台的 XGBoost 模型有许多流程不标准的地方,因此为了实现自动化链路,我们搭建了如图所示模型。

1.png

XGBoost 模型

预处理

XGBoost 模型需要更多的预处理方法来实现,包括:

Label Encoding:预处理过程。XGBoost 仅支持从 0 开始到(分类数-1)的 label 数值。但为了映射方便,我们存储的 label 值对应的是平台的分类 ID,并不是 0~N 的,甚至可能不是连续整数。因此需要用 Label Encoding 组件编码到符合 XGBoost 需求的数值。

存储 Label 映射表:数据转存,因为预测接口会用到这一映射表来转义平台分类,因此要额外保存。

数据重整:预处理过程,为防止随机拆分算法将训练集的 label 拆分为不完备的数据集,把训练集 label 的缺失数据捞回来。对模型会有一定干扰,但是在数据极少的极端情况下才会发挥作用。

XGBoost 在测试数据上的表现颇为自信,降低了阈值划分的困难,预测结果也能够很好的满足我们“识别正确组件”的业务需求,并且也可以支持自动化流程,因此成为后续我们主推的传统训练模型。

▐ 难点问题:Out Of Distributio

值得一提的是,我们无法对当前模块库以外的所有视觉样本进行全面的收集,这样的工程就如同为了做一个阿里内部的面部识别系统,而去收集 70 亿人类的面部照片一样。样本库以外的数据缺失导致我们其实是少了一个隐藏的分类——负样本分类。也就引发了 Out-of-Distribution 问题,即样本库以外数据带来的预测失准问题,其本质是分类结果中 false positive 过多。

在我们的场景下,这是一个很难解决的问题,因为收集全部负样本的困难性。目前我们是如何应对这一问题的呢?

阈值设定

我们将分类模型输出的置信度 prob 作为确定分类结果的参考依据,高于某一阈值则认为匹配到某个分类。这一方法具有经验意义,实践中有效的屏蔽了大部分 OOD 错误。

逻辑控制

对于算法模型的部分 OOD 误判,我们可以通过逻辑关系来辨别。如我们认为 DSL 树的同一条路径上不可能有多个相同组件(否则形成自嵌套),如果该路径上识别出多个相同组件,那么我们通过置信度大小来选择识别结果。此类逻辑帮我们筛选了大部分误判。

负样本录入

我们提供的反馈服务,允许用户将识别错误的 DSL 上传,上传后增强为一定数量的负样本并存储。在此基础上重新训练,可以解决 OOD 问题。

目前 OOD 问题还是依赖逻辑和反馈的方法来规避,算法层面仍然没有解决该问题,这是我们下一阶段计划去做的事。

▐ 模型部署

算法平台支持将模型部署为线上接口,即预测服务,通过 imgcook 平台可一键调用部署。为了实现自动化训练、部署的流程,我们还做了一系列算法工程的工作,在此不作详述。

预测与反馈

预测服务,输入为设计稿提取的 DSL(JSON),输出为业务模块信息,包括 ID、在设计稿上的位置等。

在调用算法平台的预测接口之前,我们加入了逻辑上的过滤,包括:
尺寸过滤:对于模块尺寸偏差较大的,不进入预测逻辑,直接认为不匹配
层级过滤:对于叶子节点(即纯文本、纯图片),我们不认为该节点具有业务含义,因此也过滤不用。

结果反馈链路包括自动结果检测和用户手动反馈,目前仅提供了预测结果错误的样本上传功能。

我们的业务模块识别功能最终在 99 大促中首次在线上使用。上述的模型、前置逻辑、以及 OOD 规避等环节,最终带来的效果是:业务场景内的识别准确率可达 100%(纯模型的实际准确率未统计)。

未来工作

▐ 算法优化

难点问题解决

如前所述,OOD 问题是一个难点,目前仍没有很好的解决。针对这一问题我们有一些解决思路,计划在后续工作中进行尝试。

基于 DNN 的 loss function 优化:仍基于手动 UI 特征值搭建 DNN 网络,通过 loss function 的优化,扩大不同类别之间的距离、压缩同类别内部的距离,在优化后的模型上设定距离阈值来鉴别 OOD 数据。

负样本自动生成的优化:在 XGBoost 算法基础上,增加一个前置的二分类模型,用于区分集合内和集合外数据,并据此对负样本生成的随机范围进行优化。具体方案待调研。

深度学习

手动特征提取的方法虽然快速有效,但是在泛化能力上无法与 CNN 之类的深度学习方法相比。因此后续我们会尝试基于图片的算法,使用 CNN 模型提取 UI 特征向量,再通过向量距离计算或二分类模型比对输入数据与各个 UI 组件的相似度。

在深度学习领域还可以有更多尝试,不限于以上算法设想。

▐ 样本平台

目前我们的样本生成功能存在配置效率低、支持算法类型少等问题,因此在后续工作中,我们计划将样本生成进行更丰富的产品化设计。样本平台的功能大致如图所示。

屏幕快照 2020-02-14 下午1.27.25.png

样本平台产品功能

来源扩展:目前我们的样本生成链路是从 Sketch 到 ODPS 表格数据,在后续的业务场景中我们还希望能支持从 HTML、前端代码生成样本。不论何种来源,在数据增强这一层都会有许多相通之处,我们将抽象出通用的增强算法服务,开放调用。

算法扩展:最终生成的样本,可以是特征值表格数据,用于多分类;也可以是 PASCAL、COCO 等格式的图片与标注数据,提供给目标检测模型使用。

增强智能化:目前用户在使用样本生成功能时感到配置复杂、难上手,甚至常因为误操作而导致样本不可用。因此我们期望能通过数据增强的“智能化”,来尽量减少用户操作,迅速生成有效样本。

综上,算法优化与样本平台产品化是我们下一期的核心工作。

We are hiring

淘系技术部依托淘系丰富的业务形态和海量的用户,我们持续以技术驱动产品和商业创新,不断探索和衍生颠覆型互联网新技术,以更加智能、友好、普惠的科技深度重塑产业和用户体验,打造新商业。我们不断吸引用户增长、机器学习、视觉算法、音视频通信、数字媒体、移动技术、端侧智能等领域全球顶尖专业人才加入,让科技引领面向未来的商业创新和进步。
请投递简历至邮箱:ruoqi.zlj@taobao.com

更多技术干货关注「淘系技术」微信公众号!
屏幕快照 2020-02-07 下午3.57.54.png

相关文章
|
24天前
|
JavaScript 前端开发 Docker
前端全栈之路Deno篇(二):几行代码打包后接近100M?别慌,带你掌握Deno2.0的安装到项目构建全流程、剖析构建物并了解其好处
在使用 Deno 构建项目时,生成的可执行文件体积较大,通常接近 100 MB,而 Node.js 构建的项目体积则要小得多。这是由于 Deno 包含了完整的 V8 引擎和运行时,使其能够在目标设备上独立运行,无需额外安装依赖。尽管体积较大,但 Deno 提供了更好的安全性和部署便利性。通过裁剪功能、使用压缩工具等方法,可以优化可执行文件的体积。
100 3
前端全栈之路Deno篇(二):几行代码打包后接近100M?别慌,带你掌握Deno2.0的安装到项目构建全流程、剖析构建物并了解其好处
|
6天前
|
前端开发 JavaScript
前端界的革命:掌握这些新技术,让你的代码简洁到让人惊叹!
前端技术的快速发展带来了许多令人惊叹的新特性。ES6及其后续版本引入了箭头函数、模板字符串等简洁语法,极大减少了代码冗余。React通过虚拟DOM和组件化思想,提高了代码的可维护性和效率。Webpack等构建工具通过模块化和代码分割,优化了应用性能和加载速度。这些新技术正引领前端开发的革命,使代码更加简洁、高效、可维护。
11 2
|
6天前
|
前端开发 JavaScript 测试技术
前端工程师的必修课:如何写出优雅、可维护的代码?
前端工程作为数字世界的门面,编写优雅、可维护的代码至关重要。本文从命名规范、模块化设计、注释与文档、遵循最佳实践四个方面,提供了提升代码质量的方法。通过清晰的命名、合理的模块划分、详细的注释和持续的学习,前端工程师可以写出高效且易于维护的代码,为项目的成功打下坚实基础。
15 2
|
12天前
|
监控 前端开发 JavaScript
前端开发的终极奥义:如何让你的代码既快又美,还不易出错?
【10月更文挑战第31天】前端开发是一个充满挑战与机遇的领域,本文从性能优化、代码美化和错误处理三个方面,探讨了如何提升代码的效率、可读性和健壮性。通过减少DOM操作、懒加载、使用Web Workers等方法提升性能;遵循命名规范、保持一致的缩进与空行、添加注释与文档,让代码更易读;通过输入验证、try-catch捕获异常、日志与监控,增强代码的健壮性。追求代码的“快、美、稳”,是每个前端开发者的目标。
28 3
|
13天前
|
设计模式 前端开发 JavaScript
揭秘!前端大牛们如何巧妙利用JavaScript,打造智能交互体验!
【10月更文挑战第30天】前端开发领域充满了无限可能与创意,JavaScript作为核心语言,凭借强大的功能和灵活性,成为打造智能交互体验的重要工具。本文介绍前端大牛如何利用JavaScript实现平滑滚动、复杂动画、实时数据更新和智能表单验证等效果,展示了JavaScript的多样性和强大能力。
31 4
|
13天前
|
自然语言处理 前端开发 搜索推荐
前端界的黑科技:掌握这些技术,让你的网站秒变智能助手!
【10月更文挑战第30天】随着前端技术的发展,网站正逐渐变成智能助手。本文探讨了四大关键技术:自然语言处理(NLP)使网站理解用户输入;机器学习实现个性化推荐;Web Notifications API发送重要提醒;Web Speech API实现语音交互。通过这些技术,网站不仅能更好地理解用户,还能提供更智能、个性化的服务,提升用户体验。
28 3
|
13天前
|
前端开发 JavaScript 开发者
前端开发的终极技巧:如何让你的代码既简洁又高效,还能减少bug?
【10月更文挑战第30天】前端开发充满挑战与创新,如何编写简洁高效且少bug的代码是开发者关注的重点。本文介绍五大技巧:1. 模块化,提高代码复用性;2. 组件化,降低代码耦合度;3. 使用现代框架,提高开发效率;4. 统一代码规范,降低沟通成本;5. 利用工具,优化代码质量。掌握这些技巧,让前端开发更高效。
29 1
|
20天前
|
前端开发 JavaScript 开发者
揭秘前端高手的秘密武器:深度解析递归组件与动态组件的奥妙,让你代码效率翻倍!
【10月更文挑战第23天】在Web开发中,组件化已成为主流。本文深入探讨了递归组件与动态组件的概念、应用及实现方式。递归组件通过在组件内部调用自身,适用于处理层级结构数据,如菜单和树形控件。动态组件则根据数据变化动态切换组件显示,适用于不同业务逻辑下的组件展示。通过示例,展示了这两种组件的实现方法及其在实际开发中的应用价值。
28 1
|
1月前
|
前端开发 JavaScript 开发者
利用代码分割优化前端性能:高级技巧与实践
【10月更文挑战第2天】在现代Web开发中,代码分割是优化前端性能的关键技术,可显著减少页面加载时间。本文详细探讨了代码分割的基本原理及其实现方法,包括自动与手动分割、预加载与预取、动态导入及按需加载CSS等高级技巧,旨在帮助开发者提升Web应用性能,改善用户体验。
|
1月前
|
前端开发 小程序 JavaScript
信前端里的循环显示如何编写代码?
信前端里的循环显示如何编写代码?
69 5