vivo前端智能化實(shí)踐:機(jī)器學(xué)習(xí)在自動(dòng)網(wǎng)頁布局中的應(yīng)用
作者:vivo 互聯(lián)網(wǎng)前端團(tuán)隊(duì)- Su Ning
在設(shè)計(jì)稿轉(zhuǎn)網(wǎng)頁中運(yùn)用基于self-attention機(jī)制設(shè)計(jì)的機(jī)器學(xué)習(xí)模型進(jìn)行設(shè)計(jì)稿的布局,能夠結(jié)合dom節(jié)點(diǎn)的上下文得出合理的方案。
一、背景
切圖作為前端的傳統(tǒng)手藝卻是大多數(shù)前端開發(fā)者都不愿面對(duì)的工作。
為了解決切圖的各種問題,人們絞盡腦汁開發(fā)了各種各樣的設(shè)計(jì)稿轉(zhuǎn)代碼(D2C)工具,這些D2C工具隨著設(shè)計(jì)師使用的軟件的變更又在不斷地迭代。
從Photoshop時(shí)代,前端需要手動(dòng)標(biāo)記節(jié)點(diǎn)進(jìn)行單獨(dú)的樣式導(dǎo)出(如圖1),到sketch measure,可以整體頁面輸出(如圖2),其效率、結(jié)果都已經(jīng)有了一個(gè)質(zhì)的提升。
但是還是未能徹底解決切圖的問題,因?yàn)樵O(shè)計(jì)稿所包含的信息只負(fù)責(zé)輸出樣式,而沒有辦法輸出網(wǎng)頁布局,我們還是沒有辦法直接copy生成的代碼到我們的項(xiàng)目中直接使用。
圖1
圖2
在學(xué)習(xí)現(xiàn)有的D2C案例的過程中,我們發(fā)現(xiàn)很多成熟的方案中引用了機(jī)器學(xué)習(xí)輔助代碼的生成,其中絕大多數(shù)的工作是用于視覺識(shí)別和語義識(shí)別,于是我們想,機(jī)器學(xué)習(xí)是否能夠應(yīng)用到網(wǎng)頁的布局中呢?
為了驗(yàn)證我們的猜想,也為了解決我們工作中的實(shí)際痛點(diǎn),我們決定自己開發(fā)一個(gè)D2C工具,希望能夠通過機(jī)器幫我們實(shí)現(xiàn)網(wǎng)頁布局的過程,整體工作流程大致如圖3,首先獲取設(shè)計(jì)稿的元數(shù)據(jù),然后對(duì)設(shè)計(jì)稿的數(shù)據(jù)進(jìn)行一系列的處理導(dǎo)出自由的dsl,然后根據(jù)這個(gè)dsl生成相應(yīng)端的代碼。
圖3
二、頁面布局
要處理網(wǎng)頁的布局需要解決兩個(gè)問題,節(jié)點(diǎn)的父子關(guān)系以及節(jié)點(diǎn)之間的位置關(guān)系。
2.1 節(jié)點(diǎn)的父子關(guān)系
節(jié)點(diǎn)的父子關(guān)系指的是一個(gè)節(jié)點(diǎn)包含了哪些子節(jié)點(diǎn),又被哪個(gè)節(jié)點(diǎn)所包含。這部分的內(nèi)容可以直接使用規(guī)則處理,通過節(jié)點(diǎn)的頂點(diǎn)位置和中心點(diǎn)的位置信息判斷一個(gè)節(jié)點(diǎn)是否是另一個(gè)節(jié)點(diǎn)的子節(jié)點(diǎn)。這里我們就不展開討論了。
同一層級(jí)節(jié)點(diǎn)之間的位置關(guān)系,才是我們這次著重需要解決的問題。
2.2 節(jié)點(diǎn)之間的位置關(guān)系
網(wǎng)頁的布局有很多種,線性布局,流式布局,網(wǎng)格布局,還有隨意定位的絕對(duì)定位等等,而我們?cè)趯?dǎo)出樣式的時(shí)候,無非需要確認(rèn)兩件事情,節(jié)點(diǎn)的定位方式(relative、absolute、fixed)和節(jié)點(diǎn)的布局方向(縱向、橫向)。
?線性布局
流式布局
網(wǎng)格布局
按照平時(shí)切圖的習(xí)慣,我們會(huì)首先識(shí)別一組平級(jí)節(jié)點(diǎn)之間有沒有明顯的上下或者左右的位置關(guān)系,然后將他們放入到網(wǎng)格中,最后獨(dú)立在這些節(jié)點(diǎn)外面的節(jié)點(diǎn)就是絕對(duì)定位。
讓機(jī)器識(shí)別節(jié)點(diǎn)之間的位置關(guān)系,就成了解決問題的關(guān)鍵一環(huán)。
判斷節(jié)點(diǎn)之間的位置關(guān)系只需要節(jié)點(diǎn)的位置和寬高信息,因此我們的輸入數(shù)據(jù)設(shè)計(jì)如下:
[
{
width:200,
height:50,
x:0,
y:0
},
{
width:200,
height:100,
x:0,
y:60
},
{
width:200,
height:100,
x:210,
y:60
}
]
同時(shí)我們希望獲得的輸出結(jié)果是每一個(gè)節(jié)點(diǎn)是上下排列,左右排列,還是絕對(duì)定位的,輸出的數(shù)據(jù)設(shè)計(jì)如下:
[
{
layout:'col'
},
{
layout:'row'
},
{
layout:'absolute'
}
]
起初我們是希望通過書寫一定的規(guī)則進(jìn)行布局的判斷,通過判斷前后兩個(gè)節(jié)點(diǎn)的位置關(guān)系是上下還是左右來進(jìn)行布局,然而這樣只關(guān)注兩個(gè)節(jié)點(diǎn)位置關(guān)系的規(guī)則卻很難判斷絕對(duì)定位的節(jié)點(diǎn),并且固定的規(guī)則總是不夠靈活。于是我們想到了善于處理分類問題的機(jī)器學(xué)習(xí)。
很顯然通過大量數(shù)據(jù)訓(xùn)練的機(jī)器學(xué)習(xí)模型可以很好的模仿我們平時(shí)切圖的習(xí)慣,在處理各種邊緣場(chǎng)景的時(shí)候也能夠更加的靈活。只要進(jìn)行合理的模型設(shè)計(jì),就可以輔助我們進(jìn)行布局的處理。
三、為什么是self-attetion?
從上文我們可以看出,我們需要訓(xùn)練一個(gè)模型,輸入一個(gè)節(jié)點(diǎn)的列表,輸出一個(gè)節(jié)點(diǎn)的布局信息,是不是有點(diǎn)像文本識(shí)別里面的詞性翻譯呢?
對(duì)于具體的一個(gè)節(jié)點(diǎn),我們是沒有辦法判斷其真正的布局的,只有將其放到文檔流中結(jié)合上下文來看才能體現(xiàn)出其實(shí)際的意義。
在處理詞性標(biāo)記這塊,RNN(循環(huán)神經(jīng)網(wǎng)絡(luò))、LSTM(長(zhǎng)短期記憶網(wǎng)絡(luò))都比較合適此類場(chǎng)景,RNN作為經(jīng)典的神經(jīng)網(wǎng)絡(luò)模型通過將前一次訓(xùn)練的權(quán)重帶入到下一次訓(xùn)練中建立上下文的關(guān)聯(lián),LSTM作為RNN的一種變體解決了RNN難以解決的長(zhǎng)期依賴問題,用來訓(xùn)練網(wǎng)頁布局看起來是一個(gè)不錯(cuò)的選擇。
RNN(循環(huán)神經(jīng)網(wǎng)絡(luò))
LS期記憶網(wǎng)絡(luò))
使用LSTM的確可以解決我們的問題,但是由于此類神經(jīng)網(wǎng)絡(luò)對(duì)于時(shí)序的依賴導(dǎo)致上下文的數(shù)據(jù)沒有辦法進(jìn)行并行運(yùn)算,這使得我們的計(jì)算機(jī)沒有辦法更高效的訓(xùn)練模型,并且網(wǎng)頁布局只需要獲取不同節(jié)點(diǎn)的定位信息,對(duì)于裝載的順序并沒有強(qiáng)要求。
隨著2017年的一篇文章《Attention is All you Need》的橫空出世,整個(gè)機(jī)器學(xué)習(xí)領(lǐng)域迎來了新一輪的革命,目前最主流的框架transformer、BERT、GPT全是在attetion的基礎(chǔ)上發(fā)展起來的。
self-attetion自注意力機(jī)制是attention機(jī)制的變體,通過全局關(guān)聯(lián)權(quán)重得出單個(gè)向量在全局中的加權(quán)信息,因?yàn)槊恳粋€(gè)節(jié)點(diǎn)都采用相同的運(yùn)算方式,所以同一個(gè)序列中的節(jié)點(diǎn)可以同時(shí)進(jìn)行上下文計(jì)算,極大地提升了模型訓(xùn)練的效率,也更方便我們優(yōu)化和回歸模型。
self-attention
綜上,考慮到attention對(duì)于上下文更好的關(guān)聯(lián)和更好的并行性能,我們決定基于此進(jìn)行建模。
四、模型設(shè)計(jì)
我們起初設(shè)計(jì)了一個(gè)輸出的向量用于識(shí)別數(shù)據(jù)處理的結(jié)果,[1,0,0,0]代表是正常的豎向排列,[0,1,0,0]代表了橫向排列,以此類推依次代表了absolute和fixed定位方式,但是后來我們發(fā)現(xiàn)fixed由于是相對(duì)于整個(gè)頁面的定位方式,所以在單一層級(jí)下很難做標(biāo)記,所以我們將輸出值精簡(jiǎn)成了豎向排列,橫向排列和絕對(duì)定位三種情況。
模型的整體設(shè)計(jì)如下,通過self-attention將節(jié)點(diǎn)轉(zhuǎn)化為上下文信息,再通過前饋神經(jīng)網(wǎng)絡(luò)將上下文信息訓(xùn)練成具體的布局。
(1)在獲取到一組數(shù)據(jù)后,為了去掉數(shù)值的大小的影響,我們首先對(duì)數(shù)據(jù)進(jìn)行一次歸一處理,將輸入數(shù)據(jù)的每一個(gè)值分別除以這一組數(shù)據(jù)中的最大值。
(2)將每一組數(shù)據(jù)分別進(jìn)行三次線性變換, 得到每組數(shù)據(jù)相應(yīng)的Q,K,V,接下來我們就可以進(jìn)行self-attention運(yùn)算了。
(3)我們以node1為例,如果需要計(jì)算node1和其他節(jié)點(diǎn)的相關(guān)性,則需要使用Q1分別和每一個(gè)節(jié)點(diǎn)的key進(jìn)行點(diǎn)積操作,將他們的和與V1相乘,為了防止權(quán)重值相乘以后過大,最后進(jìn)行一次softmax計(jì)算,就得到了node1和其他節(jié)點(diǎn)的上下文信息。
我們將一組數(shù)據(jù)中所有QKV看成三個(gè)矩陣,得到的上下文context的集合就可以看成一個(gè)矩陣計(jì)算。
(4)為了提升訓(xùn)練的效果,每個(gè)節(jié)點(diǎn)的上下文信息輸入到前饋神經(jīng)網(wǎng)絡(luò)進(jìn)行最后的布局結(jié)果的訓(xùn)練,將得到的結(jié)果進(jìn)行softmax計(jì)算就可以得到單個(gè)節(jié)點(diǎn)在一組數(shù)據(jù)中布局的概率分布了,由于同一組節(jié)點(diǎn)的運(yùn)算沒有前后順序,故單個(gè)節(jié)點(diǎn)的運(yùn)算可以同時(shí)進(jìn)行,配合GPU加速極大地提升了訓(xùn)練的效率。
五、數(shù)據(jù)準(zhǔn)備
由于機(jī)器學(xué)習(xí)需要海量的數(shù)據(jù),數(shù)據(jù)的數(shù)量和質(zhì)量都會(huì)極大地影響模型最終的訓(xùn)練效果,所以數(shù)據(jù)的數(shù)量和質(zhì)量都非常重要,我們采用了三種數(shù)據(jù)源用于數(shù)據(jù)的訓(xùn)練,分別是標(biāo)記過的設(shè)計(jì)稿,抓取的真實(shí)網(wǎng)頁數(shù)據(jù),以及自動(dòng)生成的數(shù)據(jù)。
5.1 設(shè)計(jì)稿的標(biāo)記
在獲取到設(shè)計(jì)稿數(shù)據(jù)以后只取每個(gè)節(jié)點(diǎn)的定位和寬高數(shù)據(jù),通過上文的父子關(guān)系處理后獲取每一層的節(jié)點(diǎn)數(shù)據(jù),為了防止出現(xiàn)過擬合的情況我們?nèi)サ艄?jié)點(diǎn)數(shù)量相對(duì)較少的層級(jí),并對(duì)每一層的布局進(jìn)行手動(dòng)標(biāo)記。設(shè)計(jì)稿標(biāo)記數(shù)據(jù)是質(zhì)量最好,但也是最費(fèi)時(shí)費(fèi)力的工作,所以需要其他的數(shù)據(jù)源進(jìn)行數(shù)量的補(bǔ)充。
5.2 真實(shí)網(wǎng)頁的抓取
作為標(biāo)記設(shè)計(jì)稿的補(bǔ)充,網(wǎng)頁中的真實(shí)數(shù)據(jù)也是可靠的數(shù)據(jù)源,但是抓取網(wǎng)頁的過程中最大的難點(diǎn)在于判斷頁面中的節(jié)點(diǎn)屬于橫向還是縱向。
由于實(shí)現(xiàn)橫向排列的方式千奇百怪,可以通過float,inline-block,flex等等方法,我們?nèi)绻猾@取網(wǎng)頁中節(jié)點(diǎn)的定位和寬高信息,還是需要手動(dòng)標(biāo)記他的布局,所以還是要從節(jié)點(diǎn)的css入手,在批量獲取之后進(jìn)行手動(dòng)篩選,去掉低質(zhì)量的數(shù)據(jù)。相對(duì)于標(biāo)記的設(shè)計(jì)稿是一個(gè)有效的補(bǔ)充。
5.3 網(wǎng)頁生成器
為了更快的生成大量的數(shù)據(jù),我們寫了一個(gè)網(wǎng)頁生成的算法,在一開始就決定節(jié)點(diǎn)的定位方式,然后將節(jié)點(diǎn)渲染成網(wǎng)頁,最后在抓取節(jié)點(diǎn)的定位信息,但是隨機(jī)生成的數(shù)據(jù)存在一些不穩(wěn)定的邊界場(chǎng)景,譬如生成的絕對(duì)定位的節(jié)點(diǎn)會(huì)正好定位到橫向布局的右邊。這時(shí)就需要手動(dòng)進(jìn)行甄別。
我們最終收集了大約兩萬多條數(shù)據(jù),經(jīng)過反復(fù)的訓(xùn)練與調(diào)試,最終準(zhǔn)確率穩(wěn)定在99.4%左右,達(dá)到一個(gè)相對(duì)可用的水平。
使用真實(shí)的dom進(jìn)行回歸驗(yàn)證,可以看出準(zhǔn)確的識(shí)別出了網(wǎng)頁的橫向豎向布局以及絕對(duì)定位的節(jié)點(diǎn)。
六、優(yōu)化方向
6.1 元素?fù)Q行
設(shè)計(jì)稿中會(huì)出現(xiàn)列表一行放不下然后換行的情況,這些節(jié)點(diǎn)應(yīng)該是屬于橫向的位置關(guān)系,但是機(jī)器面對(duì)兩行會(huì)將每一行的首個(gè)元素識(shí)別成縱向排布,這就需要對(duì)重復(fù)節(jié)點(diǎn)進(jìn)行相似度檢測(cè),對(duì)相似節(jié)點(diǎn)采用相同的布局策略。
6.2 分組問題
基于規(guī)則的分組會(huì)導(dǎo)致兩個(gè)不相交的節(jié)點(diǎn)不會(huì)分配到一個(gè)組里面,比如網(wǎng)格中的圖標(biāo)和文字,導(dǎo)致布局的時(shí)候會(huì)分成兩個(gè)獨(dú)立的組,可以通過訓(xùn)練常見的布局結(jié)合內(nèi)容識(shí)別進(jìn)行更精準(zhǔn)的分組。
6.3 通用布局
通過self-attention機(jī)制我們不僅可以判斷單個(gè)節(jié)點(diǎn)在其層級(jí)的布局信息,我們也可以進(jìn)行發(fā)散,通過訓(xùn)練整個(gè)層級(jí)的節(jié)點(diǎn)數(shù)據(jù)得出當(dāng)前節(jié)點(diǎn)屬于卡片流,標(biāo)簽,個(gè)人信息頁等功能性的標(biāo)記,進(jìn)一步推導(dǎo)出每個(gè)節(jié)點(diǎn)的功能,再結(jié)合節(jié)點(diǎn)具體的布局信息,不僅可以更好的實(shí)現(xiàn)網(wǎng)頁的排布,還可以節(jié)點(diǎn)的功能推到實(shí)現(xiàn)標(biāo)簽的語義化。
6.4 數(shù)據(jù)生成
為了解決更多的網(wǎng)頁布局問題,同時(shí)減少我們?nèi)斯?biāo)記的工作量,可以運(yùn)用強(qiáng)化學(xué)習(xí)模型開發(fā)一套網(wǎng)頁生成工具,讓我們的數(shù)據(jù)更接近真實(shí)的網(wǎng)頁布局,從而使布局模型訓(xùn)練的結(jié)果更加貼近生產(chǎn)的場(chǎng)景。
七、總結(jié)
機(jī)器學(xué)習(xí)非常擅長(zhǎng)處理分類問題,相比于傳統(tǒng)的手寫規(guī)則布局,機(jī)器學(xué)習(xí)是基于我們現(xiàn)有的開發(fā)習(xí)慣進(jìn)行訓(xùn)練,最終生成的代碼也更加貼近我們平時(shí)的切圖習(xí)慣,代碼的可讀性和可維護(hù)性都更上一層樓。
而機(jī)器生成的靜態(tài)頁面相較于不同的人手寫的靜態(tài)頁面,遵循一致的代碼規(guī)范,代碼風(fēng)格也更加統(tǒng)一。
在模型搭建的過程中可以將具體的使用場(chǎng)景類比為文本或者圖像領(lǐng)域的內(nèi)容,便于尋找現(xiàn)有的模型進(jìn)行遷移學(xué)習(xí)。
運(yùn)用機(jī)器學(xué)習(xí)解決網(wǎng)頁布局問題的核心在于建立節(jié)點(diǎn)的上下文的關(guān)聯(lián),通過了解各種經(jīng)典的神經(jīng)網(wǎng)絡(luò)模型的運(yùn)行原理我們選出了循環(huán)神經(jīng)網(wǎng)絡(luò)和自注意力機(jī)制這種能夠建立上下文關(guān)聯(lián)的模型,而通過對(duì)于其運(yùn)行原理的進(jìn)一步了解我們選擇了更貼近網(wǎng)頁布局場(chǎng)景以及運(yùn)行效率更高的self-attention模型,由此也可以看出了解模型的運(yùn)行機(jī)制可以更好的幫助我們解決實(shí)際的應(yīng)用場(chǎng)景。