整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

深度学习自动前端开发:从草图到HTML只需5秒

人们的不断探索下,「使用人工智能自动生成网页」的方法已经变得越来越接近实用化了。本文介绍的这种名为 SketchCode 的卷积神经网络能够把网站图形用户界面的设计草图直接转译成代码行,为前端开发者们分担部分设计流程。目前,该模型在训练后的 BLEU 得分已达 0.76。

你可以在 GitHub 上找到这个项目的代码:https://github.com/ashnkumar/sketch-code

为用户创造直观、富有吸引力的网站是各家公司的重要目标,而且这是个快速进行原型、设计、用户测试循环的过程。像 Facebook 这样的大公司有着让整个团队专注于设计流程的人力,改动可能需要几周的时间,并涉及到多种利益相关者;而小型企业就没有这样的资源,因此其用户界面可能受到一些影响。

我在 Insight 当中的目标是使用现代深度学习算法大大简化设计工作流程,并使得任何规模的公司都能快速地创造并测试网页。

现有的设计工作流程

现有工作流程涉及多个利益相关者

一个典型的设计工作流程如下所示:

  • 产品经理进行用户研究,从而制定技术参数表

  • 设计人员将接受这些要求并尝试创建低保真原型,最终创建高保真原型

  • 工程师将这些设计转化为代码并最终将产品交付给用户

开发周期的时间长度很快就会变成瓶颈,像 Airbnb 这样的公司已经开始使用机器学习来提高这个过程的效率了。(参见:https://airbnb.design/sketching-interfaces/)

Airbnb 内部 AI 工具演示:从草图到代码

虽然这种工具很有希望成为机器辅助设计的例子,但是尚不清楚这种模型在端到端的情况下能完全训练到什么程度,也不清楚它在多大程度上依赖于手工制作的图像特征。这肯定是无法知道的,因为它目前还是 Airbnb 专有的非开源方案。我想创造一个「从绘图到代码」技术的开源版本,可供更多开发者和设计者使用。

理想情况下,我的模型可以采用简单的网站设计手绘原型,并立即从该图像生成一个可用的 HTML 网站:

SketchCode 模型需要绘制好的网站线框图并能生成 HTML 代码

实际上,上面的例子是一个从我模型测试集图像生成的实际网站!你可以在我的 Github 页面中查看它:https://github.com/ashnkumar/sketch-code

从图像标注中获取灵感

我正在解决的问题属于程序综合(https://en.wikipedia.org/wiki/Program_synthesis)这个广义任务范畴,即工作源代码的自动生成。尽管很多程序综合能处理从自然语言要求或执行轨迹所生成的代码,但在我这个案例中,我可以从一个源图像(手绘线框图)开始,自动获得想要的代码。

机器学习领域中,有一个名为图像字幕生成的领域(https://cs.stanford.edu/people/karpathy/deepimagesent/),该领域有着充分的研究,旨在学习将图像和文本相连的模型,特别是生成关于源图片内容的描述。

图像标注模型生成源图片的描述

我从最近一篇名为 pix2code 的论文和 Emil Wallner 使用该方法的一个相关项目获得了灵感(参见:前端慌不慌?用深度学习自动生成 HTML 代码),并决定将我的任务重构成图像字幕生成问题的一部分,即将线框图作为输入图像,将对应的 HTML 代码作为输出文本。

获取正确的数据集

考虑到图像标注的方法,我心中理想的训练数据集是成千上万对手绘线框图和它们 HTML 代码的等价物。不出所料,我无法找到这种数据集,因此我不得不为该任务创建自己的数据。

我从 pix2code 论文中提到的一个开源数据集(https://github.com/tonybeltramelli/pix2code)入手,它由 1750 张人工生成的网页截图和其对应源代码构成。

pix2code 中生成的网站图像及其源代码数据集

这个数据集对我而言是个很好的开始,其中有一些有趣的地方:

  • 数据集中每个生成的网站都包含几个简单的 Bootstrap 元素例如按钮、文本框和 DIV。虽然这意味着我的模型将会因把这几个元素作为「词汇」(模型可选择用于生成网站的元素)而受限制,这种方法应该很容易推广到更大的元素词汇表中。

  • 每个示例的源代码包含领域专用语言(DSL)的标记,这些符号是由论文作者创建的。每个标记对应于 HTML 和 CSS 的片段,且有一个编译器将 DSL 转化为工作使用的 HTML 代码。

让图片更像手绘的

将网站的多彩主题切换成手写主题。

为了调整数据集以适应我的任务,我得把网站的图片弄得像是手绘的。对图片的手绘化都得益于 OpenCV 和 PIL library 的灰度转换和轮廓检测功能。

最终,我决定直接通过一系列操作来直接修改原网站的 CSS 样式表:

  • 通过改变页面元素的边框半径实现按钮和 div 的圆润化

  • 调整边框的粗细以模仿手绘素描,并添加阴影

  • 将字体改为类手写字体

我的最终版本又增加了一个步骤,通过加入倾斜,偏移和旋转来进行数据增强,以模仿实际绘制的素描的不确定性。

使用图像标注模型架构

现在我已经准备好我的数据了,我可以把它输入模型进行训练了!

我用的这个用于图像标注的模型包括三个主要部分:

  • 一个卷积神经网路(CNN)视觉模型用于提取源图片特征

  • 一种由编码源代码标记序列的门控循环单元(GRU)组成的语言模型

  • 一个解码器模型(也是一个 GRU),它以前两个步的输出作为输入,预测序列中的下一个标记

使用标记序列作为输入来训练模型

为了训练这个模型,我把源代码分成标记序列。其中一个序列及其源图像是模型的单个输入,其标签是文档中的下一个标记。该模型使用交叉熵成本(cross-entropy cost)作为其损失函数,将模型预测的下一个标记与实际的标记进行比较。

在模型从头开始生成代码的推理阶段,该过程稍有不同。该图像仍然通过 CNN 网络进行处理,但文本处理仅提供一个开始序列。在每一步中,模型对序列中下一个标记的预测将返回到当前输入序列,同时作为新的输入序列输入到模型中。重复此操作直到模型预测出 <END> 标记或进程达到每个文档的标记数的预定义上限。

一旦从模型中生成了一组预测标记,编译器就会将 DSL 标记转换为 HTML,这些 HTML 可以在任何浏览器中展示出来。

用 BLEU 得分评估模型

我决定用 BLEU 评分(https://machinelearningmastery.com/calculate-bleu-score-for-text-python/)来评估模型。这是机器翻译任务中经常会用到的评估标准,它试图在给定相同输入的情况下,评估机器生成的文本与人类可能写的文本的近似程度。

实质上,BLEU 通过比较生成文本和参考文本的 n-元 序列,生成精修改后的文本。它非常适合这个项目,因为它会影响生成的 HTML 中的实际元素,以及它们之间的相互关系。

然后这是最棒的——我完全可以通过检查生成的网站来理解 BLEU 得分!

BLEU 得分可视化

一个完美的 1.0 的 BLEU 分数将在正确的位置生成源图像的正确元素,而较低的得分可以预测错误的元素和/或将它们放在相对于彼此错误的位置。最终我的模型能够在测试集上得到 0.76 的 BLEU 分数。

福利 - 定制样式

我觉察到的一个额外福利是,由于模型只生成页面的骨架(文档的标记),我可以在编译过程中添加一个自定义的 CSS 层,并且可以即时看到网站的不同风格。

一次转换 => 同时生成多种样式

将样式与模型生成过程分离,给使用模型带来了很多好处:

  • 想要将 SketchCode 模型应用到自己公司产品中的前端工程师可以按原样使用该模型,只需更改一个 CSS 文件以符合其公司的样式要求

  • 可扩展性已内置 - 使用一张源图像,模型输出可立即编译为 5、10 或 50 种不同的预定义样式,因此用户可以看到他们网站的多个版本,并在浏览器中浏览这些网站

总结与展望

通过利用图像标注的研究成果,SketchCode 能够在几秒钟内将手绘网站线框图转换为可用的 HTML 网站。

该模型有些局限性,大概包括以下几点:

  • 由于这个模型是用一个只有 16 个元素的词汇进行训练的,它不能预测训练数据之外的标记。下一步可能是使用更多元素(如图像,下拉菜单和表单)生成其他样例网站——Bootstrap components 是个练手的好网站:https://getbootstrap.com/docs/4.0/components/buttons/

  • 实际生产环境中,网站有很多变化。创建一个更能反映这种变化的训练数据集的好方法是去爬取实际的网站,捕获他们的 HTML / CSS 代码以及网站内容的截图

  • 手绘素描也有很多变化,CSS 修改技巧没有被模型完全学会。在手绘素描上生成更多变化的一种好方法是使用生成对抗网络来创建逼真的绘制网站图像

我很期待看到项目的进一步发展!

何在前端JavaScript开发中使用ES新特性?babel是什么?.babelrc文件又是干什么用的?文件中的presets和plugins又是什么鬼?本文将解答上述疑问。

babel是什么

babel是一个JavaScript编译器

为什么要babel

ES规范今年来更新较为频繁,近几个版本推出很多新的特性,而用户的浏览器版本众多,很多用户用的是老版本浏览器,老版本浏览器不支持ES新特(nodejs也存在同样问题,参见),babel就是用来让你可以使用ES新特性,又可以使代码运行在老版本浏览器上。

Babel 通过语法转换器支持最新版本的 JavaScript 。 语法转换插件允许你立刻使用新语法,无需等待浏览器支持。

babel工作流程简介

解析-->转换-->生成代码
  • 解析生成AST语法树
  • 根据插件对AST树进行遍历转译并得到新的AST树(新特性转译)
  • 生成代码

babel使用

1.在构建工具中(以webpack为例)使用:

// 在webpack.config.js中增加babel-loader,如下所示
module: {
 rules: [
 { test: /\.js$/, exclude: /node_modules/, loader: "babel-loader" }
 ]
}

2.在babel-cli中使用

npm install -g babel-cli
babel src -d lib // 将src中的代码转译并将生成的文件放到lib目录下
复制代码

babel的配置

babel的配置是要告诉babel工具使用哪些插件转译代码,主要作用于babel工作的第二阶段(转译)

babel工作前会从.babelrc文件读取配置,根据配置对JavaScript进行转译。

下面以.babelrc文件的配置方式为例介绍,配置项主要有两个,presets,plugins;

{
 "presets": ["env"],
 "plugins": ["babel-plugin-transform-object-assign"]
}

plugins配置具体插件,而对于ES新特性需要配置的插件多达几十个,如果一一配置就太麻烦来,于是babel给我们提供一些插件集,插件集配置在presets配置项中,目前官方提供的插件集有:

  1. env
  2. react
  3. flow

其中 env(babel-preset-env)相当于 es2015 ,es2016 ,es2017 及最新版本。

4. stage-X

Stage-x preset 中的任何转换都是对未被批准为 JavaScript 版本一部分的语言的变化(如 es6 / es2015 ),其分为以下5各阶段:

Stage 0 - 稻草人: 只是一个想法,可能是 babel 插件。
Stage 1 - 提案: 初步尝试。
Stage 2 - 初稿: 完成初步规范。
Stage 3 - 候选: 完成规范和浏览器初步实现。
Stage 4 - 完成: 将被添加到下一年度发布。

上述配置的插件和插件集也是需要通过npm安装的

npm install babel-preset-env --save-dev
npm install babel-plugin-transform-object-assign --save-dev

babel presets(转换插件集)配置

"presets": ["env"] // 默认将运行所有transfrom和集成所有的polyfill

也可以仅仅配置项目所支持浏览器所需的polyfill和transform。只编译所需的代码会使你的代码包更小。如下所示,该转换只支持每个浏览器最后两个版本和safari大于等于7的版本所需的polyfill和代码转换。

揭秘九大前沿编程语言A

如今,对于编程语言而言,提供一个丰富的开放式源代码,函数库以及框架为基础语言是用户关注的重点。在一些特定项目情况下,市场主流编程语言尽管有大量资源提供,但并不能有效解决用户的特定问题,用户不得不去寻找适合的语言。通过一些编程语言可以提供额外的功能,帮助代码运行速度更快,摈弃无休止的调整和优化。

以下九种语言应该是每个程序员所关注的技术。它们并不是最好的编程语言,有些甚至仅仅在专门项目应用上提供帮助。但这九种编程语言具备上升空间,是值得每一个开发人员研究和学习,或许有一天这些语言成为你的项目必不可少的。

Erlang语言:提供实时系统功能

Erlang是由瑞典电信设备制造商爱立信所辖的计算机科学研究室开发,目的是可以应付大规模开发活动的程序设计语言和运行环境。Erlang于1987年发布正式版本,erlang是函数式语言,提供了9个9的稳定性和超高并发并发性能,于1998年发表开放源代码版本。

Erlang是运作于虚拟机的解释型语言,在程序设计范型上,Erlang属于多重范型编程语言,涵盖函数式、并行及分布式。循序运行的Erlang是一个及早求值,单次赋值和动态类型的函数式编程语言。特别是在实时系统应用上,如移动电话交换机计费系统。

GO语言:简单、动态

Go语言是谷歌2009发布源编程语言,专门针对多处理器系统应用程序的编程进行了优化,使用Go编译的程序可以媲美C或C++代码的速度,而且更加安全、支持并行进程。

编译后Go代码的运行速度与C语言非常接近,而且编译速度非常快,就像在使用一个交互式语言。现有编程语言均未专门对多核处理器进行优化。Go就是谷歌工程师为这类程序编写的一种语言。它不是针对编程初学者设计的,但学习使用它也不是非常困难。Go支持面向对象,而且具有真正的封装和反射 等功能,可以被用于网络服务器、存储系统和数据库中。

Groovy语言: Java编程的精华

Groovy是用于Java虚拟机的一种敏捷的动态语言,作为一种成熟的面向对象编程语言,既可以用于面向对象编程,又可以用作纯粹的脚本语言。Groovy语言提供程序员来编写简单的程序,充分利用现有的Java代码的能力。

构建在强大的Java语言之上并添加了从Python,Ruby和Smalltalk等语言中诸多特征,例如动态类型转换、闭包和元编程支持。不仅如此,紧密联系到Java JAR文件,Groovy的代码运行像一个动态类型的脚本语言,可全面进入到静态类型的Java对象的数据。

Ocaml语言:复杂数据层次“魔术师”

OCaml最早称为Objective Caml,是Caml编程语言的主要实现,开发工具包含交互式顶层解释器,字节码编译器以及最优本地代码编译器。Ocaml有一个巨大标准库,使得可以像Python或者Perl语言一样可以方便地开发各种应用程序。

对于程序员来说,OCaml由编程语言社区努力推广,并提供有目标的支持,自动内存管理和设备的便携性。目前可从苹果的App Store获下载OCaml应用程序。通过OCaml语言的应用特性,可以建立一个教代数的网站。

2揭秘九大前沿编程语言B

CoffeeScript:JS转译语言

CoffeeScript并非一种语言,受到Ruby、Python与Haskell等语言的启发,增强了JavaScript的简洁性与可读性的转译器。同时新增更复杂的功能,例如列表内涵、模式匹配等。使用CoffeeScript可以体会编程泛型的表达方式,减少逗号、括弧这些只是增强表达能力的一些副作用。

Scala语言:运行JVM上函数程序

Scala运行在JVM上,兼容现有的Java程序,集成面向对象编程和函数式编程的各种特性。Scala也是一种函数式语言,其函数也能当成值来使用。Scala提供了轻量级的语法用以定义匿名函数,支持高阶函数,允许嵌套多层函数,并支持柯里化。Scala的case class及其内置的模式匹配相当于函数式编程语言中常用的代数类型。

Scala还包含了若干函数式语言的关键概念,包括高阶函数(Higher-Order Function)、局部套用(Currying)、嵌套函数(Nested Function)、序列解读(Sequence Comprehensions)等。Scala是静态类型的,这就允许它提供泛型类、内部类、甚至多态方法(Polymorphic Method)。另外值得一提的是,Scala被特意设计成能够与Java和.NET互操作。

Dart语言:非JS的JavaScript

Dart从设计之初就为配合现代web整体运作而考虑,开发团队也在持续改进Dart向JavaScript转换的快速编译器。JavaScript适用于为网页新增基本的交互性,但如果面对成千上万行代码弱点显而易见。谷歌设计Dart这门新语言的缘由,Dart与 JavaScipt双管齐下,用于优化Web编程开发。

Dart与JavaScript相似,用到了类似于C语言的语法和关键词。最明显的区别在于JavaScript是一种基于原型的编程语言,而Dart和C++、Java类似,需要使用类和接口来声明对象。开发人员可以选用Dart来声明静态类型的变量,与JavaScript相比,HTML5开发者们尝试一下Dart语言在WEB编写代码的速度上更胜一筹。

Haskell语言:简单纯粹的函数编程

对于有20年的发展,Haskell语言是一种标准化的,通用纯函数式编程语言,有非限定性语义和强静态类型。作为函数式编程语言,主要控制结构是函数,具有“证明即程序、命题为类型”的特征。社区在宣传时一直是将其定位为一门通用程序设计语言的。Haskell是一种程序语言。特别是多态类型,懒惰的,纯的函数式语言,与大多数其它编程语言不同。 该语言被命名为Haskell Brooks Curry。它是以数学逻辑为基础的函数式语言,基于lambda演算。

Julia语言

Julia语言:更快速度的Python

科学计算传统上需要最高的性能,但是领域内的专家们在日常工作中更多的会选择慢一些的动态语言。现代语言设计和编译器技术使目标成为可能:最大化的消除性能抉择和为原型设计(prototyping)提供一个富有成效的单一环境并且足够有效率的来运用性能加强的应用。面向科学计算的高性能动态高级程序设计语言,像Python般通用Julia编程语言扮演这个角色:灵活的动态语言,科学和数值计算方面的优异表现,以及比得上传统静态类型语言的优异性能。

Julia的特性包括可选的输入,多重分派(Multiple dispatch)和优异性能,实现了使用类型推断和JIT(just-in-time)编译,使用LLVM执行。它采用多范式的,命令式的特征组合,函数化的并且面向对象的编程方式。同时Julia保持了MATLAB在高水平数值计算方面的轻松表现,但突破在一般编程上的局限,不仅建立在数学编程语言上的血统,而且借鉴了流行的动态语言如Lisp, Perl, Python, Lua和Ruby的优点。