天然語言處理基礎技術之分詞、向量化、詞性標註

歡迎你們前往騰訊雲社區,獲取更多騰訊海量技術實踐乾貨哦~git

做者:段石石github

前言

前段時間,由於項目需求, 開始接觸了NLP,有感本身不是科班出身,不少東西理解不深,因而花時間再讀了一些NLP的經典教程的部分章節,這裏是第一部分,主要包括三小塊:中文分詞、詞向量、詞性標註, 這三塊是前段時間項目上有用到過,因此稍作總結與你們分享下,只有更極致地深刻了解才能學習得更多。數組

分詞

分詞多是天然語言處理中最基本的問題,在英文中,自然地使用空格來對句子作分詞工做,而中文就不行了,沒有特色符號來標誌某個詞的開始或者結尾,而分詞一般對語義的理解是特別重要的,這裏舉個栗子:網絡

下雨天留客天留我不留==>下雨天 留客天 留我不留 
                    ==>下雨 天留客 天留我不留

不一樣的分詞,會形成徹底不一樣的語義理解,其重要性不明而喻,那麼如何把詞從句子中正確地切分出來呢?數據結構

我愛北京天安門

分紅我 愛 北京天安門 而不是 我愛 北 京天安門? 對於計算機而已,天安門和京天安門都是二進制存儲在硬盤或者內存中,沒有其餘差異,那麼咱們如何讓計算機知道切分爲天安門而不是京天安門呢? 這裏咱們須要提到詞典的幫助,作過NLP的小夥伴一般都知道在一些基礎任務上,詞典的好壞決定最後的性能指標,那麼詞典是如何對分詞起做用的呢?函數

分詞詞典

最簡單的一個想法,是構造一個經常使用詞的候選集合,如我、愛、天安門、北京這些詞,而後從句子頭到尾遍歷,如何詞在候選集合中出現過則切分該詞,那麼很容易將我愛天安門分詞爲我 愛 天安門,這樣的邏輯很容易理解,因此接下來就是如何去設計這個候選集合的數據結構,經常使用的list,固然是能夠的,可是很明顯,將一個海量詞的詞典載入,詞典元素的查找還有存儲,若是使用list必然會存在很嚴重的性能問題,若是高效地存儲詞典,還有高效地查詢詞或者短語在詞典中,是這部分分詞最重要的工做,Trie樹在天然語言處理詞庫的存儲和查找上使用的比較廣泛。性能

Trie樹存儲及最長匹配法

Wikipedia上對於Trie樹是這樣解釋的:在計算機科學中,trie,又稱前綴樹或字典樹,是一種有序樹,用於保存關聯數組,其中的鍵一般是字符串。與二叉查找樹不一樣,鍵不是直接保存在節點中,而是由節點在樹中的位置決定。一個節點的全部子孫都有相同的前綴,也就是這個節點對應的字符串,而根節點對應空字符串。通常狀況下,不是全部的節點都有對應的值,只有葉子節點和部份內部節點所對應的鍵纔有相關的值。學習

圖中主要包括三種節點:開始節點、中間節點、和結束節點,利用Trie樹存儲後,根據一條路徑上來存儲一個詞典的詞如上海大學、固然中間節點也能夠作爲一個詞的結尾來保存如上海,經常使用的中文字不到5000,大概只須要一個一層分支爲2^12的Trie樹來保存全部的中文詞庫信息,樹形的結構,保證了高效的存儲和查找方法,遍歷sentence時,只須要依次向樹下一層訪問,若是沒法訪問到下一節點,則切分,如到葉子節點,也切分便可,這就是基於Tire樹的最長匹配法,分詞性能的好壞徹底依賴於詞庫。 具體的實現能夠讀下cppjieba的MPSEGMENT的部分https://github.com/yanyiwu/cp... ,這裏主要關注下Calc和CutByDag便可比較好的理解。 Trie樹的更高效的實現方式包括三數組Trie和二數組Trie,三數組Trie結構包括三個數組結:base,next和check;二數組Trie包含base和check兩個數組,base的每一個元素表示一個Trie節點,而check數組表示某個狀態的前驅狀態,高效Trie樹的實現,你們有興趣能夠拿源碼來讀讀,這裏我先略過。優化

基於HMM的分詞方法

基於Trie Tree的分詞方法,主要依賴詞典,一般能知足大部分場景,可是不少時候也會效果很差,一般會引入機率模型來作分詞,隱性馬爾科夫模型經過引入狀態見的機率轉換,來提升分詞的效果,尤爲是對未登陸詞效果要好不少。 相信你們在不少場景下聽過HMM,HMM的基本部分包括狀態值集合、觀察值集合、狀態轉移矩陣、條件機率矩陣、初始化機率。 編碼

這裏稍微解釋下這五個術語在分詞中是啥意思:

  • 狀態值序列,這裏通常有四種狀態:B:Begin, M:Middel, E:End, S:single,對於一個待分詞序列:你們都愛北京天安門對應的狀態序列爲BESSBEBME,這樣就很容易切分爲:BE S S BE BME。
  • 觀察值序列,指的就是待切分的詞,如:我愛北京天安門;
  • 初始化機率,指的是BMES這四種狀態在第一個字的機率分佈狀況;
  • 狀態轉移矩陣,在馬爾科夫模型裏面十分重要,在HMM中,假設當前狀態只與上一個狀態有關,而這個關係咱們可使用轉移矩陣來表示,在這裏咱們是一個44的矩陣;
  • 條件機率矩陣,HMM中,觀察值只取決於當前狀態值(假設條件),條件機率矩陣主要建模在BMES下各個詞的不一樣機率,和初始化機率、狀態轉移矩陣同樣,咱們須要在語料中計算獲得對應的數據。

舉個例子來講明下: 如你們都愛北京天安門,咱們初始化一個weight4,則數組第一列值爲初始化機率條件機率集,依次爲:P(B)P(大|B),P(E)P(大|E),P(M)P(大|M),P(E)*P(大|E)。而後根據轉移機率計算下一個字的狀態機率分佈:weightk + _transProbk +_emitProbj],依次到最後便可,便可計算句子中全部詞的狀態分佈,而後肯定好邊界對比條件,便可計算出對應狀態序列。 HMM是中文分詞中一種很常見的分詞方法,由上述描述咱們知道,其分詞狀態主要依賴於語料的標註,經過語料初始化機率、狀態轉移矩陣、條件機率矩陣的計算,對須要分詞的句子來進行計算,簡單來講,是經過模型學習到對應詞的歷史狀態經驗,而後在新的矩陣中取使用。HMM的模型計算簡單,且一般很是有效,對詞典中未出現詞有比較好的效果。

更復雜的機率分詞模型:CRF

這裏咱們提到的CRF,不是廣義的CRF,而是線性鏈式CRF,和HMM同樣,CRF的分詞問題,一樣是一個序列標註問題,將BEMS標註到句子中的不一樣詞上,相對與HMM,CRF可以利用更多特徵,數學原理不講啦,都是圖加機率模型的解釋,有興趣的能夠去看下

和HMM不一樣的是,HMM描述的是已知量和未知量的一個聯合機率分佈,屬於generative model,而CRF則是建模條件機率,屬於discriminative model。另外CRF特徵更加豐富,可經過自定義特徵函數來增長特徵信息,一般CRF能建模的信息應該包括HMM的狀態轉移、數據初始化的特徵,CRF理論和實踐上一般都優於HMM,CRF主要包括兩部分特徵:一,簡單特徵,只涉及當前狀態的特徵;二,轉移特徵,涉及到兩種狀態之間的特徵;特徵模板的說明能夠看下 https://taku910.github.io/crfpp/

深度學習在分詞上的嘗試: bi-lstm+crf

基本作法包括:首先,訓練字向量,使用word2vec對語料的字訓練50維的向量,而後接入一個bi-lstm,用來建模整個句子自己的語義信息,最後接入一個crf完成序列標註工做,bi-lstm+crf能夠用來完成分詞、詞性標註這類的工做。 這個我會在以後作一些相關的嘗試。

詞向量

詞向量是在NLP中比較基礎的一個工做,相對計算機而言,人要聰明的多,人很容易明白幸福和開心是兩個比較近的詞,而計算機要想了解,實際上是很難的,而在現代計算機中,對語言的理解顯得愈來愈重要,如何去表示一個詞,也成爲了理解語言的基礎。

one-hot編碼

One-hot編碼多是最簡單的一種編碼方法,每一個詞只在對應的index置1,其餘位置都是0,One-hot編碼的問題在於很難作類似度計算,在大規模語料上時,One-hot編碼的長度可能爲幾十萬、幾百萬甚至更大,One-hot編碼顯然不行;

矩陣分解方法(LSA)

"You shall know a word by the company it keeps" --Firth, J. R

針對一個詞來講,它的語義由其上下文決定。 LSA使用詞-文檔矩陣,矩陣一般是一個稀疏矩陣,其行表明詞語、其列表明文檔。詞-文檔矩陣表示中的值表示詞在該文章出現的次數,一般,咱們能夠簡單地經過文檔的出現次數分佈來表示對應的詞,可是因爲這個矩陣一般是比較稀疏的,咱們能夠利用矩陣分解,學習到對應詞的低秩表示,這個表示建模了文檔中詞的共現關係,讓類似度的計算變得更加容易。 同理,能夠也能夠在更小粒度上計算矩陣的構建,如設定指定窗口大小,若在該窗口內出現,則數值加一,構建好詞-詞共現矩陣,最終使用如svd這類的矩陣分解方法便可。 這類方法明顯的弊病在於當copur過大時,計算很消耗資源,且對於未出現詞或者新文檔不友好。

Word2Vec

關於Word2vec有不少很好的學習資料,大體包括CBOW和Skip-gram模型,其中CBOW的輸入就是上下文的表示,而後對目標詞進行預測;skip-gram每次從目標詞w的上下文c中選擇一個詞,將其詞向量做爲模型的輸入。以前有寫Word2vec的文章能夠簡單看看Stanford CS224d筆記之Word2Vec.


其中skip-gram主要由包括如下幾塊:

  • 輸入one-hot編碼;
  • 隱層大小爲次維度大小;
  • 對於常見詞或者詞組,咱們將其做爲單個word處理;
  • 對高頻詞進行抽樣減小訓練樣本數目;
  • 對優化目標採用negative sampling,每一個樣本訓練時,只更新部分網絡權重。

Glove

Glove其實是結合了矩陣分解方法和Window-based method的一種方法,具體看下中公式2-7的推導,Glove的優點主要在於:

  • skip-gram利用local context,可是沒有考慮大量詞共現的信息,而文中認爲詞共現信息能夠在必定程度上解釋詞的語義,經過修改目標函數,z
  • 做者認爲相對於原始的額條件機率,條件機率的比值更好地反映出詞之間的相關性,以下圖:

  • 爲保證神經網絡建模線性結構關係(神經網絡容易建模非線性關係,容易歡笑線性關係),對詞差值建模,而且增長一個權重函數;

  • 使用AdaGrad:根據參數的歷史梯度信息更新每一個參數的學習率;
  • 爲減小模型複雜度,增長假設詞符合冪率分佈,可爲模型找下界限,減小參數空間;

NNLM

如上圖,早在2001年,Bengio就使用神經網絡學習語言模型,中間可輸出詞向量,NNLM和傳統的方法不一樣,不經過計數的方法對n元條件機率估計,而是直接經過神經網絡結構對模型求解,傳統的語言模型一般已知序列,來預測接下來的出現詞的可能性,Bengio提出的nnlm經過將各詞的表示拼接,而後接入剩下兩層神經網絡,依次獲得隱藏層h和輸出層y,其中涉及到一些網絡優化的工做,如直連邊的引入,最終的輸出節點有|V|個元素,依次對應此表中某個詞的可能性,經過正向傳播、反向反饋,輸入層的e就會更新使得語言模型最後的性能最好,e就是咱們可拿來的向量化的一種表示。

知識表示

知識表示是最近開始火起來的一種表示方式,結合知識圖譜,實體之間的關係,來建模某個實體的表示,和NLP裏的很相似,上下文一般能表徵詞的關係,這裏也是同樣,結合知識圖譜的知識表示,不只考慮實體間連接關係,還能夠經過引入更多的如text、image信息來表徵實體,這裏能夠關注下清華劉知遠老師的相關工做。

詞性標註

詞性標註的相關學習路線,基本能夠重搬下分詞相關的工做,也是一個詞性標註的工做

  • 基於最大熵的詞性標註
  • 基於統計最大機率輸出詞性
  • 基於HMM詞性標註
  • 基於CRF的詞性標註 能夠稍微多聊一點的是Transformation-based learning,這裏主要參考曼寧那本經典的NLP教材 Transformation-based learning of Tags, Transformation 主要包括兩個部分:a triggering environment, rewrite rule,經過不停統計語料中的頻繁項,若知足須要更改的閾值,則增長詞性標註的規則。

總結

歷來都認爲基礎不牢、地動山搖,後面會繼續努力,從源碼、文章上更深瞭解天然語言處理相關的工做,雖然如今仍是半調子水平,可是必定會努力,過去一段時間因爲工做相對比較忙,主要還沉淪了一段時間打農藥,後面會多花點時間在技術上的積澱,刷課、讀paper、讀源碼。另外,爲了增強本身的coding能力,已經開始用cpp啦(週六寫了500+行代碼),想一想都刺激,哈哈哈!!!我這智商夠不夠呀,anyway,加油吧!!!


2017-10-22: 我的博客,出了點問題,貌似是由於七牛圖牀須要再搞個啥備案,看來之後博客要費啦!!!

哎, 真麻煩

閱讀推薦

一站式知足電商節雲計算需求的祕訣
LSF-SCNN:一種基於 CNN 的短文本表達模型及類似度計算的全新優化模型
循環神經網絡(Recurrent Neural Networks)簡介

此文已由做者受權騰訊雲技術社區發佈,轉載請註明文章出處
原文連接:
https://cloud.tencent.com/com...

相關文章
相關標籤/搜索