基于CNN的新詞發(fā)現(xiàn)算法
?作者 | mczhao,攜程高級研發(fā)經(jīng)理,關(guān)注自然語言處理技術(shù)領(lǐng)域。
概覽
隨著消費熱點和網(wǎng)紅新梗的不斷涌現(xiàn),在電商平臺的NLP任務(wù)中,經(jīng)常會出現(xiàn)一些之前沒有見過的詞。這些詞不在系統(tǒng)已有的詞庫中,被稱為"未登錄詞"。
一方面,詞庫中詞的缺失影響了一些基于詞庫的分詞器的分詞質(zhì)量,間接影響了文本召回質(zhì)量和高亮提示的質(zhì)量,即用戶文本搜索的準確性和搜索結(jié)果的可解釋性。
另一方面,在主流NLP深度學習算法BERT/Transformer等等中,對中文處理時經(jīng)常使用字向量來代替詞向量。理論上使用詞向量的效果應(yīng)當是更好的,但是由于未登錄詞的原因,在實踐過程中使用字向量的效果更好。如果詞庫更加完善,那么使用詞向量的效果將優(yōu)于使用字向量的效果。
綜上,新詞發(fā)現(xiàn)是我們當下需要解決的問題。
一、傳統(tǒng)無監(jiān)督的方法
中文新詞發(fā)現(xiàn)這個問題,在業(yè)界已經(jīng)有了較為成熟的解法。輸入是一些語料,將這些文本做NGram切分以后,產(chǎn)生候選片段。計算這些片段的一些統(tǒng)計特征,再根據(jù)這些特征判斷這個片段是不是一個詞。
業(yè)界主流的做法是統(tǒng)計和觀察這三個方面的指標:熱度、內(nèi)聚度、左右鄰字豐富度。描述這三個指標的文章網(wǎng)上也有很多,這里簡單介紹一下,細節(jié)可以參考Hello NLP和Smooth NLP的兩篇新詞發(fā)現(xiàn)文章。
1.1 熱度
使用詞頻來表示熱度。統(tǒng)計所有語料的所有片段的出現(xiàn)次數(shù),那些高頻的片段往往就是一個詞。
1.2 內(nèi)聚度
使用點互信息衡量內(nèi)聚度:
例如,我們判斷漢庭是不是一個詞,log(P("漢庭")/P("漢")P("庭"))。漢庭成詞的概率,和"漢庭"的熱度成正比,和"漢"、"庭"的單字熱度成反比。這個很好理解,像是漢字中最常出現(xiàn)的字"的",隨便一個漢字和"的"搭配的概率非常高,但是并不意味這"x的"或者"的x"就是一個詞,這里"的"的單字熱度就起了一個抑制的作用。
1.3 左右鄰字豐富度
左右鄰接熵來表示左右字的豐富程度。左右鄰接熵就是候選詞片段左邊或者右邊出現(xiàn)的字的分布的隨機性。可以拆開看左邊的熵和右邊的熵,也可以把兩個熵合并為一個指標。
例如,"香格里拉"這個片段其熱度和內(nèi)聚度都非常高,對應(yīng)其子片段"香格里"的熱度和內(nèi)聚度也很高,但是因為"香格里"后面大部分情況都出現(xiàn)"拉"字,它的右鄰接熵很低,對其成詞起抑制作用,可以判斷出"香格里"三字不能單獨成詞。
二、經(jīng)典方法的局限性
經(jīng)典方法的問題在于需要人工設(shè)置閾值參數(shù)。一個NLP專家在了解當前語料中片段的概率分布以后,將這些指標通過公式組合或者獨立使用,然后設(shè)定閾值來作為判斷標準,使用這個標準判斷的結(jié)果也可以做到很高的準確度。
但概率分布或者說詞頻并不是一成不變的,隨著語料庫越來越豐富,或者語料的加權(quán)熱度(通常是對應(yīng)的商品熱度)波動變化,專家設(shè)定的公式中的參數(shù)和閾值也需要不斷調(diào)整。這就浪費了很多人力,使人工智能工程師淪為調(diào)參俠。
三、基于深度學習的新詞發(fā)現(xiàn)
3.1 詞頻概率分布圖
上述業(yè)界已有算法的三個指標,根本來源的特征只有一個,就是詞頻。在統(tǒng)計學的方法中,通常會把一些簡單又關(guān)鍵的統(tǒng)計量以圖片的方式展示,比如直方圖、箱線圖等等,即使沒有模型介入,光憑人看,還是能夠一眼做出正確的判斷??梢园颜Z料切出所有長度限定的片段,把片段的詞頻歸一化為0-255,映射為二維矩陣,行表示起始的字符,列表示終止的字符,一個像素點就是一個片段,像素點的明暗程度就是這個候選詞片段的熱度。
上圖是"浦東機場華美達酒店"這個短句的詞頻概率分布圖,我們驚喜地發(fā)現(xiàn),光憑我們的肉眼,也大致可以分出一些較為明亮的、等腰直角三角形的區(qū)塊,比如:"浦東"、"浦東機場"、"機場"、"華美達酒店"等等。這些區(qū)塊可以判斷出對應(yīng)的片段正是我們需要的詞。
3.2 經(jīng)典圖像分割算法
通過觀察詞頻概率分布圖,我們可以把一個短句分詞問題轉(zhuǎn)變?yōu)橐粋€圖像分割問題。早期的圖像分割算法,和上述的新詞發(fā)現(xiàn)算法差不多,也是基于閾值的檢測邊緣灰度變化的算法,隨著技術(shù)發(fā)展,現(xiàn)在一般使用深度學習算法,其中比較著名的是U-Net圖像分割算法。
U-Net的前半部分使用卷積下采樣,提取多層不同粒度的特征,后半部分上采樣,將這些特征在同一分辨率下concat起來,最后通過全連接層+Softmax得到像素級別的分類結(jié)果。
3.3 基于卷積網(wǎng)絡(luò)的新詞發(fā)現(xiàn)算法
對詞頻概率分布圖的切分和對圖的切分類似,都是將位置相鄰并且灰度相近的部分切出來。所以對短句的切分,也可以參考圖像分割算法,使用全卷積網(wǎng)絡(luò)來做。使用卷積來做的原因是,無論我們在切割短句或者圖像的時候,都更多的關(guān)注局部信息,就是靠近切割邊緣那些像素點。使用多層網(wǎng)絡(luò)的原因,多層的池化可以表現(xiàn)出對不同層特征的閾值判斷,例如我們對地圖地形切割的時候既要考慮坡度(一階導/差分)還需要考慮坡度的變化(二階導/差分),兩者分別取閾值并且組合方式不僅僅是簡單的線性加權(quán)而是串行的網(wǎng)絡(luò)。
對于新詞發(fā)現(xiàn)場景我們設(shè)計如下的算法:
- 先把短句的詞頻分布圖用0填充到24x24;
- 先有兩個3x3的卷積層,并輸出4通道;
- 把兩個卷積層concat起來,再做一次3x3的卷積,并且輸出單通道;
- 損失函數(shù)使用logistic=T,所以最后一層不用做softmax輸出即可用于分類;
相比于U-Net,有如下差異:
1)放棄了下采樣和上采樣,原因是一般用來分割的短句比較短,詞頻分布圖的分辨率本就不高,所以模型也隨之簡化了。
2)U-Net是三分類(分塊1、分塊2、在邊緣上),此算法只需要二分類(像素點是否是一個詞)。所以最后輸出的結(jié)果也是不一樣的,U-Net輸出一些連續(xù)的分塊和分割線,而我們只需要某個點是不是陽性的。
下圖是訓練完模型以后,用模型預(yù)測的結(jié)果。我們可以看到輸出結(jié)果中,"上海"(上這一行、海這一列)、"虹橋"、"商務(wù)區(qū)"這三個詞對應(yīng)的像素點被識別了出來。
使用訓練好的模型,輸入攜程地標庫中的地標名稱,可以自動切分和發(fā)現(xiàn)出一些新詞,如下圖,雖然有個別badcase,總體上準確率還可以。
將這些詞導入到詞庫以后,搜索分詞的準確率上升,分詞結(jié)果的詞庫覆蓋率上升。因為搜索分詞中一般傾向過召回而杜絕漏召回,業(yè)界有更激進的按字分詞召回的做法,而準確率一般通過后續(xù)的排序解決。所以分詞準確率提升了,在用戶看來搜索結(jié)果準確率并沒有明顯提升。但是可以解決部分因分詞錯誤導致的高亮提示不正確的問題。
四、模型內(nèi)部分析
如果想探究模型是怎么生效的,可以查看中間層的卷積核。我們先將模型卷積層的卷積核個數(shù)從4簡化到1,訓練以后,通過TensorFlow的API查看中間層:model.get_layer('Conv2').__dict__。我們發(fā)現(xiàn)Conv2層的卷積核如下:
可以看到第一行和第二行對模型的效果是相反的,對應(yīng)了該像素點的上一行減掉當前行的差分(帶權(quán)重),如果灰度差異越大,這個像素點代表的字符串越有可能成詞。
還可以看到第一行第二列0.04505884的絕對值比較小,可能是因為第一行減第二行的正向參數(shù)和第三列減第二列的負向參數(shù)相互抵消。
五、優(yōu)化空間
本文描述的是一個結(jié)構(gòu)非常簡單的全卷積網(wǎng)絡(luò)模型,還有很大的提升空間。
一是擴展特征選取范圍。比如,本文中輸入特征只有詞頻,如果把左右鄰接熵也納入輸入特征,切分的效果會更加精準。
二是增加網(wǎng)絡(luò)深度。通過模型分析,發(fā)現(xiàn)第一層卷積主要是為了應(yīng)對那些用0填充的像素點產(chǎn)生的case,實際關(guān)注真實熱度的卷積只有一層,如果是3x3的卷積核只能看到一階差分結(jié)果,當前像素的的前后第二行和第二列就沒有考慮到??梢赃m當擴大卷積核大小或者加深網(wǎng)絡(luò),來使模型的視野更大。但加深網(wǎng)絡(luò)也會帶來過擬合的問題。
最后,這個模型不僅僅可以用來補充詞庫以提高分詞效果,并且可以直接用作分詞的參考,在分詞流程的候選詞召回和分詞路徑打分這兩個步驟中都可以應(yīng)用這個模型的預(yù)測結(jié)果。