入門科普:一文看懂NLP和中文分詞算法(附代碼舉例)

導讀:在人類社會中,語言扮演着重要的角色,語言是人類區別於其他動物的根本標誌,沒有語言,人類的思維無從談起,溝通交流更是無源之水。

所謂“自然”乃是寓意自然進化形成,是爲了區分一些人造語言,類似C++、Java等人爲設計的語言。

NLP的目的是讓計算機能夠處理、理解以及運用人類語言,達到人與計算機之間的有效通訊。

作者:塗銘 劉祥 劉樹春

本文摘編自《Python自然語言處理實戰:核心技術與算法》,如需轉載請聯繫我們

01 什麼是NLP

1. NLP的概念

NLP(Natural Language Processing,自然語言處理)是計算機科學領域以及人工智能領域的一個重要的研究方向,它研究用計算機來處理、理解以及運用人類語言(如中文、英文等),達到人與計算機之間進行有效通訊。

在一般情況下,用戶可能不熟悉機器語言,所以自然語言處理技術可以幫助這樣的用戶使用自然語言和機器交流。從建模的角度看,爲了方便計算機處理,自然語言可以被定義爲一組規則或符號的集合,我們組合集合中的符號來傳遞各種信息。

這些年,NLP研究取得了長足的進步,逐漸發展成爲一門獨立的學科,從自然語言的角度出發,NLP基本可以分爲兩個部分:自然語言處理以及自然語言生成,演化爲理解和生成文本的任務,如圖所示。

▲NLP的基本分類

自然語言的理解是個綜合的系統工程,它又包含了很多細分學科,有代表聲音的音系學,代表構詞法的詞態學,代表語句結構的句法學,代表理解的語義句法學和語用學。

  • 音系學:指代語言中發音的系統化組織。
  • 詞態學:研究單詞構成以及相互之間的關係。
  • 句法學:給定文本的哪部分是語法正確的。
  • 語義學:給定文本的含義是什麼?
  • 語用學:文本的目的是什麼?

語言理解涉及語言、語境和各種語言形式的學科。而自然語言生成(Natural Language Generation,NLG)恰恰相反,從結構化數據中以讀取的方式自動生成文本。該過程主要包含三個階段:

  • 文本規劃:完成結構化數據中的基礎內容規劃
  • 語句規劃:從結構化數據中組合語句來表達信息流
  • 實現:產生語法通順的語句來表達文本

2. NLP的研究任務

NLP可以被應用於很多領域,這裏大概總結出以下幾種通用的應用:

  • 機器翻譯:計算機具備將一種語言翻譯成另一種語言的能力。
  • 情感分析:計算機能夠判斷用戶評論是否積極。
  • 智能問答:計算機能夠正確回答輸入的問題。
  • 文摘生成:計算機能夠準確歸納、總結併產生文本摘要。
  • 文本分類:計算機能夠採集各種文章,進行主題分析,從而進行自動分類。
  • 輿論分析:計算機能夠判斷目前輿論的導向。
  • 知識圖譜:知識點相互連接而成的語義網絡。

機器翻譯是自然語言處理中最爲人所熟知的場景,國內外有很多比較成熟的機器翻譯產品,比如百度翻譯、Google翻譯等,還有提供支持語音輸入的多國語言互譯的產品。

情感分析在一些評論網站比較有用,比如某餐飲網站的評論中會有非常多拔草的客人的評價,如果一眼掃過去滿眼都是又貴又難吃,那誰還想去呢?另外有些商家爲了獲取大量的客戶不惜僱傭水軍灌水,那就可以通過自然語言處理來做水軍識別,情感分析來分析總體用戶評價是積極還是消極。

智能問答在一些電商網站有非常實際的價值,比如代替人工充當客服角色,有很多基本而且重複的問題,其實並不需要人工客服來解決,通過智能問答系統可以篩選掉大量重複的問題,使得人工座席能更好地服務客戶。

文摘生成利用計算機自動地從原始文獻中摘取文摘,全面準確地反映某一文獻的中心內容。這個技術可以幫助人們節省大量的時間成本,而且效率更高。

文本分類是機器對文本按照一定的分類體系自動標註類別的過程。舉一個例子,垃圾郵件是一種令人頭痛的頑症,困擾着非常多的互聯網用戶。2002年,Paul Graham提出使用“貝葉斯推斷”來過濾垃圾郵件,1000封垃圾郵件中可以過濾掉995封並且沒有一個是誤判,另外這種過濾器還具有自我學習功能,會根據新收到的郵件,不斷調整。也就是說收到的垃圾郵件越多,相對應的判斷垃圾郵件的準確率就越高。

輿論分析可以幫助分析哪些話題是目前的熱點,分析傳播路徑以及發展趨勢,對於不好的輿論導向可以進行有效的控制。

知識圖譜(Knowledge Graph/Vault)又稱科學知識圖譜,在圖書情報界稱爲知識域可視化或知識領域映射地圖,是顯示知識發展進程與結構關係的一系列各種不同的圖形,用可視化技術描述知識資源及其載體,挖掘、分析、構建、繪製和顯示知識及它們之間的相互聯繫。知識圖譜的一般表現形式如圖所示。

▲知識圖譜圖示

3. NLP相關知識的構成

3.1 基本術語

爲了幫助讀者更好地學習NLP,這裏會一一介紹NLP領域的一些基礎專業詞彙。

(1)分詞(segment)

詞是最小的能夠獨立活動的有意義的語言成分,英文單詞之間是以空格作爲自然分界符的,而漢語是以字爲基本的書寫單位,詞語之間沒有明顯的區分標記,因此,中文詞語分析是中文分詞的基礎與關鍵。

中文和英文都存在分詞的需求,不過相較而言,英文單詞本來就有空格進行分割,所以處理起來相對方便。但是,由於中文是沒有分隔符的,所以分詞的問題就比較重要。

分詞常用的手段是基於字典的最長串匹配,據說可以解決85%的問題,但是歧義分詞很難。舉個例子,“美國會通過對臺售武法案”,我們既可以切分爲“美國/會/通過對臺售武法案”,又可以切分成“美/國會/通過對臺售武法案”。

(2)詞性標註(part-of-speech tagging)

基於機器學習的方法裏,往往需要對詞的詞性進行標註。詞性一般是指動詞、名詞、形容詞等。標註的目的是表徵詞的一種隱藏狀態,隱藏狀態構成的轉移就構成了狀態轉移序列。例如:我/r愛/v北京/ns天安門/ns。其中,ns代表名詞,v代表動詞,ns、v都是標註,以此類推。

(3)命名實體識別(NER,Named Entity Recognition)

命名實體是指從文本中識別具有特定類別的實體(通常是名詞),例如人名、地名、機構名、專有名詞等。

(4)句法分析(syntax parsing)

句法分析往往是一種基於規則的專家系統。當然也不是說它不能用統計學的方法進行構建,不過最初的時候,還是利用語言學專家的知識來構建的。句法分析的目的是解析句子中各個成分的依賴關係。

所以,往往最終生成的結果是一棵句法分析樹。句法分析可以解決傳統詞袋模型不考慮上下文的問題。比如,“小李是小楊的班長”和“小楊是小李的班長”,這兩句話,用詞袋模型是完全相同的,但是句法分析可以分析出其中的主從關係,真正理清句子的關係。

(5)指代消解(anaphora resolution)

中文中代詞出現的頻率很高,它的作用的是用來表徵前文出現過的人名、地名等。

例如,清華大學坐落於北京,這家大學是目前中國最好的大學之一。在這句話中,其實“清華大學”這個詞出現了兩次,“這家大學”指代的就是清華大學。但是出於中文的習慣,我們不會把“清華大學”再重複一遍。

(6)情感識別(emotion recognition)

所謂情感識別,本質上是分類問題,經常被應用在輿情分析等領域。情感一般可以分爲兩類,即正面、負面,也可以是三類,在前面的基礎上,再加上中性類別。

一般來說,在電商企業,情感識別可以分析商品評價的好壞,以此作爲下一個環節的評判依據。通常可以基於詞袋模型+分類器,或者現在流行的詞向量模型+RNN。經過測試發現,後者比前者準確率略有提升。

(7)糾錯(correction)

自動糾錯在搜索技術以及輸入法中利用得很多。由於用戶的輸入出錯的可能性比較大,出錯的場景也比較多。所以,我們需要一個糾錯系統。具體做法有很多,可以基於N-Gram進行糾錯,也可以通過字典樹、有限狀態機等方法進行糾錯。

(8)問答系統(QA system)

這是一種類似機器人的人工智能系統。比較著名的有:蘋果Siri、IBM Watson、微軟小冰等。問答系統往往需要語音識別、合成,自然語言理解、知識圖譜等多項技術的配合纔會實現得比較好。

3.2 知識結構

作爲一門綜合學科,NLP是研究人與機器之間用自然語言進行有效通信的理論和方法。這需要很多跨學科的知識,需要語言學、統計學、最優化理論、機器學習、深度學習以及自然語言處理相關理論模型知識做基礎。

作爲一門雜學,NLP可謂是包羅萬象,體系化與特殊化並存,這裏簡單羅列其知識體系,知識結構結構圖如圖所示。

▲知識結構圖示

自然語言的學習,需要有以下幾個前置知識體系:

  • 目前主流的自然語言處理技術使用python來編寫。
  • 統計學以及線性代數入門。

02 中文分詞技術

1. 中文分詞簡介

“詞”這個概念一直是漢語語言學界糾纏不清而又繞不開的問題。“詞是什麼”(詞的抽象定義)和“什麼是詞”(詞的具體界定),這兩個基本問題迄今爲止也未能有一個權威、明確的表述,更無法拿出令大衆認同的詞表來。主要難點在於漢語結構與印歐體系語種差異甚大,對詞的構成邊界方面很難進行界定。

比如,在英語中,單詞本身就是“詞”的表達,一篇英文文章就是“單詞”加分隔符(空格)來表示的,而在漢語中,詞以字爲基本單位的,但是一篇文章的語義表達卻仍然是以詞來劃分的。

因此,在處理中文文本時,需要進行分詞處理,將句子轉化爲詞的表示。這個切詞處理過程就是中文分詞,它通過計算機自動識別出句子的詞,在詞間加入邊界標記符,分隔出各個詞彙。

整個過程看似簡單,然而實踐起來卻很複雜,主要的困難在於分詞歧義。以NLP分詞的經典語句舉例,“結婚的和尚未結婚的”,應該分詞爲“結婚/的/和/尚未/結婚/的”,還是“結婚/的/和尚/未/結婚/的”?這個由人來判定都是問題,機器就更難處理了。

此外,像未登錄詞、分詞粒度粗細等都是影響分詞效果的重要因素。

自中文自動分詞被提出以來,歷經將近30年的探索,提出了很多方法,可主要歸納爲“規則分詞”“統計分詞”和“混合分詞(規則+統計)”這三個主要流派。

  • 規則分詞是最早興起的方法,主要是通過人工設立詞庫,按照一定方式進行匹配切分,其實現簡單高效,但對新詞很難進行處理。
  • 隨後統計機器學習技術的興起,應用於分詞任務上後,就有了統計分詞,能夠較好應對新詞發現等特殊場景。
  • 然而實踐中,單純的統計分詞也有缺陷,那就是太過於依賴語料的質量,因此實踐中多是採用這兩種方法的結合,即混合分詞

下面將詳細介紹這些方法的代表性算法。

2. 規則分詞

基於規則的分詞是一種機械分詞方法,主要是通過維護詞典,在切分語句時,將語句的每個字符串與詞表中的詞進行逐一匹配,找到則切分,否則不予切分。

按照匹配切分的方式,主要有正向最大匹配法、逆向最大匹配法以及雙向最大匹配法三種方法。

2.1 正向最大匹配法

正向最大匹配(Maximum Match Method,MM法)的基本思想爲:假定分詞詞典中的最長詞有i個漢字字符,則用被處理文檔的當前字串中的前i個字作爲匹配字段,查找字典。若字典中存在這樣的一個i字詞,則匹配成功,匹配字段被作爲一個詞切分出來。如果詞典中找不到這樣的一個i字詞,則匹配失敗,將匹配字段中的最後一個字去掉,對剩下的字串重新進行匹配處理。

如此進行下去,直到匹配成功,即切分出一個詞或剩餘字串的長度爲零爲止。這樣就完成了一輪匹配,然後取下一個i字字串進行匹配處理,直到文檔被掃描完爲止。

其算法描述如下:

  • 從左向右取待切分漢語句的m個字符作爲匹配字段,m爲機器詞典中最長詞條的字符數。
  • 查找機器詞典並進行匹配。若匹配成功,則將這個匹配字段作爲一個詞切分出來。若匹配不成功,則將這個匹配字段的最後一個字去掉,剩下的字符串作爲新的匹配字段,進行再次匹配,重複以上過程,直到切分出所有詞爲止。

比如我們現在有個詞典,最長詞的長度爲5,詞典中存在“南京市長”和“長江大橋”兩個詞。

現採用正向最大匹配對句子“南京市長江大橋”進行分詞,那麼首先從句子中取出前五個字“南京市長江”,發現詞典中沒有該詞,於是縮小長度,取前4個字“南京市長”,詞典中存在該詞,於是該詞被確認切分。再將剩下的“江大橋”按照同樣方式切分,得到“江”“大橋”,最終分爲“南京市長”“江”“大橋”3個詞。

顯然,這種結果還不是我們想要的。

2.2 逆向最大匹配法

逆向最大匹配(Reverse Maximum Match Method,RMM法)的基本原理與MM法相同,不同的是分詞切分的方向與MM法相反。逆向最大匹配法從被處理文檔的末端開始匹配掃描,每次取最末端的i個字符(i爲詞典中最長詞數)作爲匹配字段,若匹配失敗,則去掉匹配字段最前面的一個字,繼續匹配。相應地,它使用的分詞詞典是逆序詞典,其中的每個詞條都將按逆序方式存放。

在實際處理時,先將文檔進行倒排處理,生成逆序文檔。然後,根據逆序詞典,對逆序文檔用正向最大匹配法處理即可。

由於漢語中偏正結構較多,若從後向前匹配,可以適當提高精確度。所以,逆向最大匹配法比正向最大匹配法的誤差要小。統計結果表明,單純使用正向最大匹配的錯誤率爲1/169,單純使用逆向最大匹配的錯誤率爲1/245。

比如之前的“南京市長江大橋”,按照逆向最大匹配,最終得到“南京市”“長江大橋”。當然,如此切分並不代表完全正確,可能有個叫“江大橋”的“南京市長”也說不定。

2.3 雙向最大匹配法

雙向最大匹配法(Bi-directction Matching method)是將正向最大匹配法得到的分詞結果和逆向最大匹配法得到的結果進行比較,然後按照最大匹配原則,選取詞數切分最少的作爲結果。

據SunM.S.和Benjamin K.T.(1995)的研究表明,中文中90.0%左右的句子,正向最大匹配法和逆向最大匹配法完全重合且正確,只有大概9.0%的句子兩種切分方法得到的結果不一樣,但其中必有一個是正確的(歧義檢測成功),只有不到1.0%的句子,使用正向最大匹配法和逆向最大匹配法的切分雖重合卻是錯的,或者正向最大匹配法和逆向最大匹配法切分不同但兩個都不對(歧義檢測失敗)。這正是雙向最大匹配法在實用中文信息處理系統中得以廣泛使用的原因。

前面舉例的“南京市長江大橋”,採用該方法,中間產生“南京市/長江/大橋”和“南京市/長江大橋”兩種結果,最終選取詞數較少的“南京市/長江大橋”這一結果。

下面是一段實現逆向最大匹配的代碼。

#逆向最大匹配
class IMM(object):
    def __init__(self, dic_path):
        self.dictionary = set()
        self.maximum = 0
        #讀取詞典
        with open(dic_path, 'r', encoding='utf8') as f:
            for line in f:
                line = line.strip()
                if not line:
                    continue
                self.dictionary.add(line)
                self.maximum = len(line)
    def cut(self, text):
        result = []
        index = len(text)
        while index > 0:
            word = None
            for size in range(self.maximum, 0, -1):
                if index - size < 0:
                    continue
                piece = text[(index - size):index]
                if piece in self.dictionary:
                    word = piece
                    result.append(word)
                    index -= size
                    break
            if word is None:
                index -= 1
        return result[::-1]

def main():
    text = "南京市長江大橋"

    tokenizer = IMM('./data/imm_dic.utf8')
    print(tokenizer.cut(text))

運行main函數,結果爲:

['南京市', '長江大橋']

基於規則的分詞,一般都較爲簡單高效,但是詞典的維護是一個很龐大的工程。在網絡發達的今天,網絡新詞層出不窮,很難通過詞典覆蓋到所有詞。

3. 統計分詞

隨着大規模語料庫的建立,統計機器學習方法的研究和發展,基於統計的中文分詞算法漸漸成爲主流。

其主要思想是把每個詞看做是由詞的最小單位的各個字組成的,如果相連的字在不同的文本中出現的次數越多,就證明這相連的字很可能就是一個詞。

因此我們就可以利用字與字相鄰出現的頻率來反應成詞的可靠度,統計語料中相鄰共現的各個字的組合的頻度,當組合頻度高於某一個臨界值時,我們便可認爲此字組可能會構成一個詞語。

基於統計的分詞,一般要做如下兩步操作:

  • 建立統計語言模型。
  • 對句子進行單詞劃分,然後對劃分結果進行概率計算,獲得概率最大的分詞方式。這裏就用到了統計學習算法,如隱含馬爾可夫(HMM)、條件隨機場(CRF)等。

限於篇幅,本文只對統計分詞相關技術做簡要介紹。更多詳細內容請參考《Python自然語言處理實戰:核心技術與算法》一書第3章第3.3節。

4. 混合分詞

事實上,目前不管是基於規則的算法、還是基於HMM、CRF或者deep learning等的方法,其分詞效果在具體任務中,其實差距並沒有那麼明顯。在實際工程應用中,多是基於一種分詞算法,然後用其他分詞算法加以輔助。

最常用的方式就是先基於詞典的方式進行分詞,然後再用統計分詞方法進行輔助。如此,能在保證詞典分詞準確率的基礎上,對未登錄詞和歧義詞有較好的識別。

關於作者:塗銘,阿里巴巴數據架構師,對大數據、自然語言處理、Python、Java相關技術有深入的研究,積累了豐富的實踐經驗。

劉祥,百鍊智能自然語言處理專家,主要研究知識圖譜、NLG等前沿技術,參與機器自動寫作產品的研發與設計。

劉樹春,七牛雲高級算法專家,七牛AI實驗室NLP&OCR方向負責人,主要負責七牛NLP以及OCR相關項目的研究與落地。

本文摘編自《Python自然語言處理實戰:核心技術與算法》,經出版方授權發佈。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章