天天看点

前端智能化漫谈 (4) - pix2code结果编辑距离分析前端智能化漫谈 (4) - pix2code结果编辑距离分析

前端智能化漫谈 (4) - pix2code结果编辑距离分析

Levenshtein距离分析

从实用的角度,我们先采用莱文斯坦距离,也就是编辑距离来分析一下pix2code的结果。因为Levenshtein距离是从DSL角度来看,需要人工修改时的最小编辑次数,所以从这个角度来分析是有其意义的。

我们分别用greedy和beam 3两种方法对于datasets/android/eval_set下面的png都生成一遍gui,分别存放于../android_greedy和../android_beam3目录。

可以用这样的命令:

python3 ./generate.py ../bin pix2code ../datasets/android/eval_set/ ../android_greedy/ greedy
python3 ./generate.py ../bin pix2code ../datasets/android/eval_set/ ../android_beam3/ 3           

然后我们就可以写一个pix2code_levenshtein函数来比较它们之间的差别,记得安装python_levenshtein库:

def pix2code_levenshtein(path1, path2):
    count = 0
    score = 0
    average_score = 0
    for f in os.listdir(path2):
        if f.find(".gui") != -1:
            f1 = os.path.join(path1,f)
            f2 = os.path.join(path2,f)
            print(f)
            if os.path.exists(f1) and os.path.exists(f2):
                print(f1)
                txt1 = open(f1).read()
                txt1 = txt1.replace(" ","")
                print(txt1)
                print(f2)
                txt2 = open(f2).read()
                txt2 = txt2.replace(" ","")
                print(txt2)
                this_score = Levenshtein.distance(txt1,txt2)
                print('This score:',this_score)
                print(Levenshtein.ratio(txt1,txt2))
                count = count + 1
                score = score + this_score
                average_score = score / count
                print('Current score:',average_score)           

样例分析

我们随机挑选10个文件分析一下

greedy和beam 3都能100%正确识别

例子:

完全正确的例子就不分析了。

以greedy获取的结果为例:

stack{
row{
switch
}
row{
switch
}
row{
radio
}
row{
label,slider,label
}
}
footer{
btn-home,btn-dashboard,btn-home
}           

greedy和beam 3同样识别错误

10个样例中有4例是这样的情况。

102D9F19-4FAB-4144-9996-589C22991D61

标准答案如下:

../datasets/android/eval_set/102D9F19-4FAB-4144-9996-589C22991D61.gui
stack{
row{
switch
}
row{
label,btn
}
row{
switch,switch
}
}
footer{
btn-search,btn-dashboard,btn-notifications
}           

不管是greedy还是beam 3,都错了两处,将footer中间的btn-dashboard和右边的btn-notifications给识别成了btn-home。

../android_greedy/102D9F19-4FAB-4144-9996-589C22991D61.gui
stack{
row{
switch
}
row{
label,btn
}
row{
switch,switch
}
}
footer{
btn-search,btn-home,btn-home
}           

48CCC704-865B-48FC-B64C-C9DA057E5F61

这个case两种算法都只错了一处,与上例第二处错误一样,将btn-notifications给识别成了btn-home。

stack{
row{
switch
}
row{
label,btn,btn
}
}
footer{
btn-dashboard,btn-notifications
}

../android_greedy/48CCC704-865B-48FC-B64C-C9DA057E5F61.gui
stack{
row{
switch
}
row{
label,btn,btn
}
}
footer{
btn-dashboard,btn-home
}           

54BC253F-DA31-4904-BC18-233CC0083E2F

这个比较复杂,不管greedy还是beam 3下都不能正确认别。标准答案如下:

stack{
row{
radio
}
row{
label,btn
}
row{
radio
}
row{
check
}
row{
label,slider,label
}
row{
switch
}
row{
check
}
row{
label,btn
}
}
footer{
btn-dashboard,btn-home,btn-dashboard
}           

不管是在greedy识别中还是beam 3识别中,第三行和第四行的check和radio识别反了。

第6行和第7行没识别出来,在第8行后多识别出一行。

另外,footer上的三个都识别错了。

stack{
row{
radio
}
row{
label,btn
}
row{
check
}
row{
radio
}
row{
label,slider,label
}
row{
label,btn
}
row{
radio
}
}
footer{
btn-home,btn-dashboard,btn-notifications
}           

CCF7369F-FCE4-4801-8936-E251EE90038C

这个case也相对简单,标准答案如下:

stack{
row{
switch
}
row{
switch
}
row{
check
}
row{
switch
}
}
footer{
btn-notifications,btn-home,btn-home
}           

greedy和beam 3都是两处错误,一处是switch识别成了radio;另一处是footer上最左边的的btn-notifications被识别成了btn-home。

stack{
row{
switch
}
row{
switch
}
row{
radio
}
row{
switch
}
}
footer{
btn-home,btn-home,btn-home
}           

greedy模式与beam 3模式下表现不同的

DBC890B4-0490-4A9B-88F6-8625F518F269

这个case中,greedy错了6处,beam 3错了4处。

stack{
row{
switch
}
row{
radio
}
row{
label,slider,label
}
row{
switch
}
row{
switch
}
}
footer{
btn-home,btn-dashboard,btn-dashboard
}           

greedy下对第三行的识别基本失败。

第四行和第五行的switch,greedy下只识别成一个radio。

另外,footer上错了两个。

stack{
row{
switch
}
row{
radio
}
row{
switch,switch,btn,btn
}
row{
radio
}
}
footer{
btn-dashboard,btn-notifications,btn-dashboard
}           

beam 3搜索对于第三行的支持很好。第4行第5行的switch还是没识别出来。

最后,footer的错误与greedy时一样。

stack{
row{
switch
}
row{
radio
}
row{
label,slider,label
}
row{
radio
}
}
footer{
btn-dashboard,btn-notifications,btn-dashboard
}           

68F022A8-0C01-4684-A9B2-27E586C2D918

stack{
row{
switch
}
row{
check
}
row{
label,slider,label
}
row{
check
}
}
footer{
btn-search,btn-search,btn-notifications
}           

在greedy模式下,check被识别成了radio

stack{
row{
switch
}
row{
check
}
row{
label,slider,label
}
row{
radio
}
}
footer{
btn-search,btn-search,btn-notifications
}           

而在beam 3模式下,有3处识别错误,第2行没识别出来,另外footer上错了两个:

stack{
row{
switch
}
row{


}
row{
label,slider,label
}
row{
radio
}
}
footer{
btn-notifications,btn-search,btn-notifications
}           

7C656D6E-0402-4D53-9450-CC948F07A8D4

stack{
row{
switch
}
row{
switch
}
row{
btn,btn,switch,switch
}
row{
label,btn
}
row{
label,slider,label
}
row{
switch
}
row{
label,btn,btn,btn
}
row{
switch,btn,btn
}
}
footer{
btn-home,btn-search,btn-search,btn-search
}           

到这么复杂的情况下,不管是greedy和beam 3都乱了套,各有十几处错误。

greedy的情况:

stack{
row{
switch
}
row{
switch
}
row{
btn,switch,switch
}
row{
label,btn,btn,btn
}
row{
switch
}
row{
label,slider,label
}
row{
label,btn
}
row{
switch
}
row{
label,btn
}
}
footer{
btn-home,btn-search,btn-search,btn-search
}           

beam 3的情况:

stack{
row{
switch
}
row{
switch
}
row{
btn,switch,}
row{
label,btn,btn,btn
}
row{
label,slider,label
}
row{
switch
}
row{
label,btn
}
row{
label,slider,btn,btn
}
}
footer{
btn-search,btn-search,btn-search,btn-home
}           

8B5AF397-CBD8-4B2C-B8A6-3E9D036B4F2F

我们再来看一个复杂点的例子,标准答案如下:

stack{
row{
btn,switch,btn
}
row{
switch
}
row{
btn,btn,btn,btn
}
row{
label,slider,label
}
row{
radio
}
row{
check
}
row{
check
}
}
footer{
btn-notifications,btn-home,btn-notifications,btn-notifications
}           

greedy算法在第一行识别就把中间的switch识别成了btn。

stack{
row{
btn,btn,btn
}
row{
switch
}
row{
label,slider,label
}
row{
check
}
row{
label,slider,label
}
row{
btn
}
row{
radio
}
}
footer{
btn-home,btn-home,btn-home,btn-home
}           

beam 3的表现要好一些,但是在row中识别出了row,,,,是个败笔:

stack{
row{
btn,btn,btn
}
row{
switch
}
row{


row,,,,


row{
label,slider,label
}
row{
check
}
row{
check
}
}
footer{
btn-search,btn-notifications,btn-home,btn-home
}           

beam 3可正确识别而greedy不能正确识别的case

9DB2E273-687B-4C00-952C-354C1AE1BF99

greedy对于同一行较多控件情况下的识别能力不如beam 3,在第1行第4个控件识别上出了问题,标准答案如下:

stack{
row{
btn,switch,switch,btn
}
row{
check
}
row{
switch
}
}
footer{
btn-dashboard,btn-home
}           

greedy时最后一个btn识别成了switch

stack{
row{
btn,switch,switch,switch
}
row{
check
}
row{
switch
}
}
footer{
btn-dashboard,btn-home
}           

样例总结

这10个case中,greedy模式下的平均Levenshtein距离32.1,beam 3模式下为28.

250张Android测试集,greedy平均编辑距离为27.9,beam 3模式下32.

继续阅读