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

avatar
阿里巴巴集团 @大淘宝技术,服务9亿用户,赋能各行业1000万商家,作为核心技术团队保障14次双十一购物狂欢节成功

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

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

概述

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

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

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

1、样本构造,根据用户配置和自定义的数据增强规则对视觉稿进行 UI 层的增强,以得到视觉多样化的样本。然后在定义好业务字段的基础上,进行特征值抽取并存储。 2、算法选择,目前提供的都是传统机器学习方法中的多分类算法。

3、模型实现,基于集团机器学习平台实现模型搭建及相关算法工程,做到自动化训练与部署。

4、接口提供,模型对外提供预测识别服务以及结果反馈服务。

总体功能见下图:

所在分层

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

样本构造

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

数据增强

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

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

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

1、增强属性:尺寸、位置、隐藏、前景背景色、内容

2、增强方式:连续范围、指定枚举值

样本生成的界面见下图:

数特征提取

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

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

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

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

算法与模型

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

随机森林

模型搭建

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

随机森林变量类型自动解析规则见下图:

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

线上使用的随机森林模型见下图:

调参过程

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

相似模块见下图:

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

调参过程中使用过的随机森林模型见下图:

离散特征问题

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

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

XGBoost 多分类

模型搭建

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

XGBoost 模型见下图:

预处理

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

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

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

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

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

难点问题:Out Of Distributio

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

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

阈值设定

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

逻辑控制

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

负样本录入

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

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

模型部署

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

预测与反馈

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

在调用算法平台的预测接口之前,我们加入了逻辑上的过滤,包括:

1、尺寸过滤:对于模块尺寸偏差较大的,不进入预测逻辑,直接认为不匹配

2、层级过滤:对于叶子节点(即纯文本、纯图片),我们不认为该节点具有业务含义,因此也过滤不用。

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

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

未来工作

算法优化

难点问题解决

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

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

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

深度学习

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

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

样本平台

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

样本平台产品功能见下图:

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

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

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

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