基於CNN的新詞發現演算法
作者簡介:mczhao,攜程高階研發經理,關注自然語言處理技術領域。
概覽
隨著消費熱點和網紅新梗的不斷湧現,在電商平臺的NLP任務中,經常會出現一些之前沒有見過的詞。這些詞不在系統已有的詞庫中,被稱為"未登入詞"。
一方面,詞庫中詞的缺失影響了一些基於詞庫的分詞器的分詞質量,間接影響了文字召回質量和高亮提示的質量,即使用者文字搜尋的準確性和搜尋結果的可解釋性。
另一方面,在主流NLP深度學習演算法BERT/Transformer等等中,對中文處理時經常使用字向量來代替詞向量。理論上使用詞向量的效果應當是更好的,但是由於未登入詞的原因,在實踐過程中使用字向量的效果更好。如果詞庫更加完善,那麼使用詞向量的效果將優於使用字向量的效果。
綜上,新詞發現是我們當下需要解決的問題。
一、傳統無監督的方法
中文新詞發現這個問題,在業界已經有了較為成熟的解法。輸入是一些語料,將這些文字做NGram切分以後,產生候選片段。計算這些片段的一些統計特徵,再根據這些特徵判斷這個片段是不是一個詞。
業界主流的做法是統計和觀察這三個方面的指標:熱度、內聚度、左右鄰字豐富度。描述這三個指標的文章網上也有很多,這裡簡單介紹一下,細節可以參考Hello NLP和Smooth NLP的兩篇新詞發現文章。
1.1 熱度
使用詞頻來表示熱度。統計所有語料的所有片段的出現次數,那些高頻的片段往往就是一個詞。
1.2 內聚度
使用點互資訊衡量內聚度:
例如,我們判斷漢庭是不是一個詞,log(P("漢庭")/P("漢")P("庭"))。漢庭成詞的機率,和"漢庭"的熱度成正比,和"漢"、"庭"的單字熱度成反比。這個很好理解,像是漢字中最常出現的字"的",隨便一個漢字和"的"搭配的機率非常高,但是並不意味這"x的"或者"的x"就是一個詞,這裡"的"的單字熱度就起了一個抑制的作用。
1.3 左右鄰字豐富度
左右鄰接熵來表示左右字的豐富程度。左右鄰接熵就是候選詞片段左邊或者右邊出現的字的分佈的隨機性。可以拆開看左邊的熵和右邊的熵,也可以把兩個熵合併為一個指標。
例如,"香格里拉"這個片段其熱度和內聚度都非常高,對應其子片段"香格里"的熱度和內聚度也很高,但是因為"香格里"後面大部分情況都出現"拉"字,它的右鄰接熵很低,對其成詞起抑制作用,可以判斷出"香格里"三字不能單獨成詞。
二、經典方法的侷限性
經典方法的問題在於需要人工設定閾值引數。一個NLP專家在瞭解當前語料中片段的機率分佈以後,將這些指標透過公式組合或者獨立使用,然後設定閾值來作為判斷標準,使用這個標準判斷的結果也可以做到很高的準確度。
但機率分佈或者說詞頻並不是一成不變的,隨著語料庫越來越豐富,或者語料的加權熱度(通常是對應的商品熱度)波動變化,專家設定的公式中的引數和閾值也需要不斷調整。這就浪費了很多人力,使人工智慧工程師淪為調參俠。
三、基於深度學習的新詞發現
3.1 詞頻機率分佈圖
上述業界已有演算法的三個指標,根本來源的特徵只有一個,就是詞頻。在統計學的方法中,通常會把一些簡單又關鍵的統計量以圖片的方式展示,比如直方圖、箱線圖等等,即使沒有模型介入,光憑人看,還是能夠一眼做出正確的判斷。可以把語料切出所有長度限定的片段,把片段的詞頻歸一化為0-255,對映為二維矩陣,行表示起始的字元,列表示終止的字元,一個畫素點就是一個片段,畫素點的明暗程度就是這個候選詞片段的熱度。
上圖是"浦東機場華美達酒店"這個短句的詞頻機率分佈圖,我們驚喜地發現,光憑我們的肉眼,也大致可以分出一些較為明亮的、等腰直角三角形的區塊,比如:"浦東"、"浦東機場"、"機場"、"華美達酒店"等等。這些區塊可以判斷出對應的片段正是我們需要的詞。
3.2 經典影像分割演算法
透過觀察詞頻機率分佈圖,我們可以把一個短句分詞問題轉變為一個影像分割問題。早期的影像分割演算法,和上述的新詞發現演算法差不多,也是基於閾值的檢測邊緣灰度變化的演算法,隨著技術發展,現在一般使用深度學習演算法,其中比較著名的是U-Net影像分割演算法。
U-Net的前半部分使用卷積下采樣,提取多層不同粒度的特徵,後半部分上取樣,將這些特徵在同一解析度下concat起來,最後透過全連線層+Softmax得到畫素級別的分類結果。
3.3 基於卷積網路的新詞發現演算法
對詞頻機率分佈圖的切分和對圖的切分類似,都是將位置相鄰並且灰度相近的部分切出來。所以對短句的切分,也可以參考影像分割演算法,使用全卷積網路來做。使用卷積來做的原因是,無論我們在切割短句或者影像的時候,都更多的關注區域性資訊,就是靠近切割邊緣那些畫素點。使用多層網路的原因,多層的池化可以表現出對不同層特徵的閾值判斷,例如我們對地圖地形切割的時候既要考慮坡度(一階導/差分)還需要考慮坡度的變化(二階導/差分),兩者分別取閾值並且組合方式不僅僅是簡單的線性加權而是序列的網路。
對於新詞發現場景我們設計如下的演算法:
1)先把短句的詞頻分佈圖用0填充到24x24;
2)先有兩個3x3的卷積層,並輸出4通道;
3)把兩個卷積層concat起來,再做一次3x3的卷積,並且輸出單通道;
4)損失函式使用logistic=T,所以最後一層不用做softmax輸出即可用於分類;
相比於U-Net,有如下差異:
1)放棄了下采樣和上取樣,原因是一般用來分割的短句比較短,詞頻分佈圖的解析度本就不高,所以模型也隨之簡化了。
2)U-Net是三分類(分塊1、分塊2、在邊緣上),此演算法只需要二分類(畫素點是否是一個詞)。所以最後輸出的結果也是不一樣的,U-Net輸出一些連續的分塊和分割線,而我們只需要某個點是不是陽性的。
下圖是訓練完模型以後,用模型預測的結果。我們可以看到輸出結果中,"上海"(上這一行、海這一列)、"虹橋"、"商務區"這三個詞對應的畫素點被識別了出來。
使用訓練好的模型,輸入攜程地標庫中的地標名稱,可以自動切分和發現出一些新詞,如下圖,雖然有個別badcase,總體上準確率還可以。
將這些詞匯入到詞庫以後,搜尋分詞的準確率上升,分詞結果的詞庫覆蓋率上升。因為搜尋分詞中一般傾向過召回而杜絕漏召回,業界有更激進的按字分詞召回的做法,而準確率一般透過後續的排序解決。所以分詞準確率提升了,在使用者看來搜尋結果準確率並沒有明顯提升。但是可以解決部分因分詞錯誤導致的高亮提示不正確的問題。
四、模型內部分析
如果想探究模型是怎麼生效的,可以檢視中間層的卷積核。我們先將模型卷積層的卷積核個數從4簡化到1,訓練以後,透過TensorFlow的API檢視中間層:model.get_layer('Conv2').__dict__。我們發現Conv2層的卷積核如下:
可以看到第一行和第二行對模型的效果是相反的,對應了該畫素點的上一行減掉當前行的差分(帶權重),如果灰度差異越大,這個畫素點代表的字串越有可能成詞。
還可以看到第一行第二列0.04505884的絕對值比較小,可能是因為第一行減第二行的正向引數和第三列減第二列的負向引數相互抵消。
五、最佳化空間
本文描述的是一個結構非常簡單的全卷積網路模型,還有很大的提升空間。
一是擴充套件特徵選取範圍。比如,本文中輸入特徵只有詞頻,如果把左右鄰接熵也納入輸入特徵,切分的效果會更加精準。
二是增加網路深度。透過模型分析,發現第一層卷積主要是為了應對那些用0填充的畫素點產生的case,實際關注真實熱度的卷積只有一層,如果是3x3的卷積核只能看到一階差分結果,當前畫素的的前後第二行和第二列就沒有考慮到。可以適當擴大卷積核大小或者加深網路,來使模型的視野更大。但加深網路也會帶來過擬合的問題。
最後,這個模型不僅僅可以用來補充詞庫以提高分詞效果,並且可以直接用作分詞的參考,在分詞流程的候選詞召回和分詞路徑打分這兩個步驟中都可以應用這個模型的預測結果。
來自 “ 攜程技術 ”, 原文作者:mczhao;原文連結:https://mp.weixin.qq.com/s/0PGkxZn_XoTF5s_jmeVPNw,如有侵權,請聯絡管理員刪除。
相關文章
- 用python實現基於凝固度和自由度的新詞發現程式Python
- 基於PHP + TRIE樹實現敏感詞過濾演算法PHP演算法
- 雙向最大匹配演算法——基於詞典規則的中文分詞(Java實現)演算法中文分詞Java
- 基於OT與CRDT協同演算法的文件劃詞評論能力實現演算法
- 基於Tensorflow + Opencv 實現CNN自定義影像分類OpenCVCNN
- 深度學習基礎-基於Numpy的卷積神經網路(CNN)實現深度學習卷積神經網路CNN
- jieba 基於 TF-IDF 演算法的關鍵詞提取Jieba演算法
- MapReduce實現與自定義詞典檔案基於hanLP的中文分詞詳解HanLP中文分詞
- 怎樣實現基於Trie樹和字典的分詞功能分詞
- 基於 CNN 的驗證碼破解實戰專案CNN
- 基於CNN的閱讀理解式問答模型:DGCNNCNN模型GC
- 分詞工具Hanlp基於感知機的中文分詞框架HanLP中文分詞框架
- 基於BKDRhash實現Hash演算法演算法
- 基於 Tire 樹的敏感詞檢測
- 基於hanlp的es分詞外掛HanLP分詞
- 基於結構化平均感知機的分詞器Java實現分詞Java
- 基於 RecyclerView 實現的歌詞滾動自定義控制元件View控制元件
- 基於TP3.2和Bootstrap開發的歌詞類網站boot網站
- 中文分詞工具之基於字標註法的分詞中文分詞
- ES 筆記十六:基於詞項和基於全文的搜尋筆記
- 如何基於TensorFlow使用LSTM和CNN實現時序分類任務CNN
- 基於 HanLP 的 ES 中文分詞外掛HanLP中文分詞
- ES 入門 - 基於詞項的查詢
- 基於 keras-js 快速實現瀏覽器內的 CNN 手寫數字識別KerasJS瀏覽器CNN
- K均值演算法基於CUDA環境的實現演算法
- 支援中文的基於詞為基本粒度的字首樹(prefix trie)python實現Python
- 編譯器前端之如何實現基於DFA的詞法分析器編譯前端詞法分析
- 排序演算法總結(基於Java實現)排序演算法Java
- 基於 Redis 實現基本搶紅包演算法Redis演算法
- [Python] 基於 jieba 的中文分詞總結PythonJieba中文分詞
- 【目標檢測】Fast R-CNN演算法實現ASTCNN演算法
- 基於MeanShift的目標跟蹤演算法、實現演算法
- NeuSomatic:基於深度CNN的腫瘤體細胞突變檢測工具CNN
- 基於redis實現的鎖(用於控制nodejs的併發)RedisNodeJS
- 詞嵌入系列部落格Part1:基於語言建模的詞嵌入模型模型
- 基於RDD的Spark應用程式開發案列講解(詞頻統計)Spark
- 【NLP】TensorFlow實現CNN用於文字分類(譯)CNN文字分類
- IM敏感詞演算法原理和實現演算法