为什么中文分词比英文分词更难?有哪些常用算法?(附代码)
導讀:人類文明的重要標志之一是語言文字的誕生。數千年來,幾乎人類所有知識的傳播都是以語言和文字作為媒介。
自然語言處理是使用計算機科學與人工智能技術分析和理解人類語言的一門學科。在人工智能的諸多范疇中,自然語言的理解以其復雜性、多義性成為難度最大也是最有價值的領域之一。
隨著機器學習、統計學、深度學習的飛速進步,自然語言處理方面的研究取得了許多突破性的進展。本文將以文本分析中最基本的分詞操作為入口,介紹人工智能處理自然語言的基本工具和方法,為讀者打開語言分析和認知的大門。
作者:朱晨光
來源:大數據DT(ID:hzdashuju)
00 文本分詞
單詞是語言中重要的基本元素。一個單詞可以代表一個信息單元,有著指代名稱、功能、動作、性質等作用。在語言的進化史中,不斷有新的單詞涌現,也有許多單詞隨著時代的變遷而邊緣化直至消失。根據統計,《漢語詞典》中包含的漢語單詞數目在37萬左右,《牛津英語詞典》中的詞匯約有17萬。
理解單詞對于分析語言結構和語義具有重要的作用。因此,在機器閱讀理解算法中,模型通常需要首先對語句和文本進行單詞分拆和解析。
分詞(tokenization)的任務是將文本以單詞為基本單元進行劃分。由于許多詞語存在詞型的重疊,以及組合詞的運用,解決歧義性是分詞任務中的一個挑戰。不同的分拆方式可能表示完全不同的語義。如在以下例子中,兩種分拆方式代表的語義都有可能:
南京市|長江|大橋
南京|市長|江大橋
為了解決分詞中的歧義性,許多相關算法被提出并在實踐中取得了很好的效果。下面將對中文分詞和英文分詞進行介紹。
01 中文分詞
在漢語中,句子是單詞的組合。除標點符號外,單詞之間并不存在分隔符。這就給中文分詞帶來了挑戰。
分詞的第一步是獲得詞匯表。由于許多中文詞匯存在部分重疊現象,詞匯表越大,分詞歧義性出現的可能性就越大。因此,需要在詞匯表的規模和最終分詞的質量之間尋找平衡點。這里介紹一種主流的中文分詞方式——基于匹配的分詞。
這種分詞方式采用固定的匹配規則對輸入文本進行分割,使得每部分都是一個詞表中的單詞。正向最大匹配算法是其中一種常用算法,它的出發點是,文本中出現的詞一般是可以匹配的最長候選詞。
例如,對于文本“鞭炮聲響徹夜空”,鞭炮和鞭炮聲都是合理的單詞,這里選擇更長的鞭炮聲,并最終分割成“鞭炮聲|響徹|夜空”。
具體來說,正向最大匹配算法從第一個漢字開始,每次嘗試匹配存在于詞表中的最長的詞,然后繼續處理下一個詞。這一過程無須每次在詞表中查找單詞,可以使用哈希表(hash table)或字母樹(trie)進行高效匹配。
但是,正向最大匹配算法也經常會產生不符合邏輯的語句,如“為人民服務”,因為為人也是一個單詞,所以算法會給出“為人|民|服務”的錯誤結果。
另一種改進的算法改變了匹配的順序,即從后往前進行最大匹配。這種逆向最大匹配算法從文本末尾開始尋找在詞表中最長的單詞。讀者可以發現,這種改進的算法能將“為人民服務”正確分詞。統計結果表明,逆向最大匹配算法的錯誤率為1/245,低于正向最大匹配算法的錯誤率1/169。
下面給出逆向最大匹配算法的一個Python語言實現樣例:
''' 逆向最大匹配算法 輸入語句s和詞表vocab,輸出分詞列表。 例子:? 輸入:s=‘今天天氣真不錯’,vocab=[‘天氣’,‘今天’,‘昨天’,‘真’,‘不錯’,‘真實’,‘天天’] 輸出:[‘今天’,‘天氣’,‘真’,‘不錯’] ''' def?backward_maximal_matching(s,?vocab):result?=?[]end_pos?=?len(s)while?end_pos?>?0:found?=?Falsefor?start_pos?in?range(end_pos):if?s[start_pos:end_pos]?in?vocab:#找到最長匹配的單詞,放在分詞結果最前面result?=?[s[start_pos:end_pos]]?+?resultfound?=?Truebreakif?found:end_pos?=?start_poselse:#未找到匹配的單詞,將單字作為詞分出result?=?[s[end_pos?-?1]]?+?resultend_pos?-=?1return?result此外,中文分詞還有基于統計的方法。
02 英文分詞
相比于中文分詞,英文分詞的難度要小得多,因為英文的書寫要求單詞之間用空格分開。因此,最簡單的方法就是去除所有標點符號之后,按空格將句子分成單詞。但是,使用這種方法有以下弊端:
標點符號有時需要作為詞的一部分保留。
例如:Ph.D.、http://www.stanford.edu;
英文中千分位的逗號表示。
例如:123,456.78;
英文中縮寫需要展開。
例如:you're表示you are、we'll表示we will;
一些專有名詞需要多個單詞一起組成。
例如:New York、 San Francisco。
對于這些特例,可以使用正則表達式(regular expression)進行識別和特殊處理。此外,英文中很多詞有常見變體,如動詞的過去式加-ed,名詞的復數加-s等。
為了使后續處理能識別同個單詞的不同變體,一般要對分詞結果提取詞干(stemming),即提取出單詞的基本形式。比如do、does、done這3個詞統一轉化成為詞干do。提取詞干可以利用規則處理,比如著名的Porter Stemmer就是采用一系列復雜的規則提取詞干,如下所示。
Porter Stemmer提取詞干示例:
sses→ss:classes→class
ies→i:ponies→poni
ative→ :informative→inform
在Python語言中,中文分詞功能可以用jieba軟件包實現:
#?安裝Jieba #?pip?install?jieba import?jieba seg_list?=?jieba.cut(‘我來到北京清華大學’) print('/?'.join(seg_list))運行結果如下:
我/?來到/?北京/?清華大學英文分詞功能可以通過spaCy軟件包完成:
#?安裝spaCy #?pip?install?spacy #?python?-m?spacy?download?en_core_web_sm import?spacy nlp?=?spacy.load('en_core_web_sm') text?=?('Today?is?very?special.?I?just?got?my?Ph.D.?degree.') doc?=?nlp(text) print([e.text?for?e?in?doc])運行結果如下:
['Today',?'is',?'very',?'special',?'.',?'I',?'just',?'got',?'my',?'Ph.D.',?'degree',?'.']一般來說,中文分詞的難度遠大于英文分詞。在英文閱讀理解任務中,即使只采用最簡單的空格分詞也可以取得不錯的效果。而在中文語言處理中,準確的分詞模塊是后續處理的關鍵。
03 字節對編碼BPE
前文中提到的分詞方法均依賴預先準備的詞表。一方面,如果詞表規模很大,分詞效率將會下降;另一方面,無論詞表大小,都難免文本中出現OOV(Out-of-Vocabulary,詞表之外的詞)。
例如,在許多閱讀理解文章中會出現一些新的人名、地名、專有名詞等。一種簡單的處理辦法是將這些OOV單詞全部以特殊符號<OOV>代替,但是這會造成單詞中重要信息的丟失,影響機器閱讀理解算法的準確性。
在下面的案例中,人名Hongtao和網站名Weibo并不在詞表中,如果用<OOV>來表示就完全失去了相關信息。而采用不依賴于詞表的分詞,可以最大程度保留原有的單詞信息。
使用詞表和不依賴于詞表的分詞:
原句:Hongtao is visiting Weibo website.
使用詞表分詞:<OOV> | is | visiting | <OOV> | website | .
不依賴于詞表分詞:Hong | #tao | is | visit | #ing | Wei | #bo | website | .
其中#表示該子詞和前面的子詞共同組成一個單詞
字節對編碼(Byte Pair Encoder,BPE)就是一種常用的不依賴于詞表的分詞方法。BPE的原理是,找到常見的可以組成單詞的子字符串,又稱子詞(subword),然后將每個詞用這些子詞來表示。
最基本的子詞就是所有字符的集合,如{a, b, …, z, A, B, …, Z}。之后,BPE算法在訓練文本中統計所有相鄰子詞出現的次數,選出出現次數最多的一對子詞。將這一對子詞合并形成新的子詞加入集合,這稱為一次合并(merge)操作,而原來的兩個子詞仍保留在集合中。
在若干次合并之后,得到常見的子詞集合。然后,對于一個新詞,可以按照之前的合并順序得到新詞的BPE表示。而從BPE表示變回原詞可以按照合并的反向順序實現。以下是構造字符對編碼的程序示例:
//訓練文本 wonder?ponder?toner //按照當前子詞分 w?o?n?d?e?r p?o?n?d?e?r t?o?n?e?r統計相鄰子詞出現的次數,e r出現3次,出現次數最多。因此組成新子詞er。
//按照當前子詞分 w?o?n?d?er p?o?n?d?er t?o?n?er統計相鄰子詞出現次數,o n出現3次,出現次數最多。因此組成新子詞on:
//按照當前子詞分 w?on?d?er p?on?d?er t?on?er統計相鄰子詞出現次數,on d出現2次,出現次數最多。因此組成新子詞ond:
w?ond?er p?ond?er t?on?er合并3次后,子詞集合為{a, b, …, z, er, on, ond}:
//解碼新詞fond 合并e?r:?f?o?n?d 合并o?n:?f?on?d 合并on d:f ond使用字節對編碼分詞有以下優點。
第一,由于BPE的子詞表里含有所有單個字符,所以任何單詞都可以分拆成BPE的子詞,即沒有OOV問題。
第二,BPE可以通過調整合并次數動態控制詞表大小。
因此,BPE常被運用在機器翻譯、語言模型等諸多自然語言處理算法中。例如,著名的BERT算法就使用了BPE作為分詞單元。但是,BPE也存在著一定的缺陷,例如在不同訓練文本上可能得到不一樣的子詞表,使得對應的模型無法對接。此外,BPE生成的子詞是完全基于頻率的,可能并不符合語言中詞根的劃分。
在實際工程應用中,如果需要生成自然語言(如生成閱讀理解問題的答案文本),一般推薦使用BPE等不依賴于詞表的分詞方法;如果任務不涉及文本生成(如在文章中劃出答案),可以使用既有詞表,例如GloVe或Word2vec等。
關于作者:朱晨光,微軟公司自然語言處理高級研究員、斯坦福大學計算機系博士。負責自然語言處理研究與開發、對話機器人的語義理解、機器閱讀理解研究等,精通人工智能、深度學習與自然語言處理,尤其擅長機器閱讀理解、文本總結、對話處理等方向。
作者朱晨光跨越半個地球為正在閱讀本文的你送上平安符????
本文摘編自《機器閱讀理解:算法與實踐》,經出版方授權發布。
延伸閱讀《機器閱讀理解》
點擊上圖了解及購買
轉載請聯系微信:DoctorData
推薦語:微軟人工智能首席技術官黃學東、中國計算機學會秘書長杜子德聯袂推薦!微軟高級研究員、斯坦福大學計算機系博士、2屆全球閱讀理解競賽冠軍朱晨光撰寫。讓你深刻認識機器閱讀理解并直接進行相關模型開發、實驗和部署。
有話要說????
Q:?關于中文分詞算法,你還有哪些思路?
歡迎留言與大家分享
猜你想看????
73頁PPT,教你從0到1構建用戶畫像系統(附下載)
零基礎入門量子計算:從一個神奇的概念進入量子世界
什么是云原生?有哪些發展方向?終于有人講明白了
7本書,讀懂未來5年最火的數據分析、智能芯片、量子計算、中臺(文末有福利)
更多精彩????
在公眾號對話框輸入以下關鍵詞
查看更多優質內容!
PPT?|?讀書?|?書單?|?硬核?|?干貨?
大數據?|?揭秘?|?Python?|?可視化
AI?|?人工智能?|?5G?|?中臺
機器學習?|?深度學習?|?神經網絡
合伙人?|?1024?|?大神?|?數學
據統計,99%的大咖都完成了這個神操作
????
總結
以上是生活随笔為你收集整理的为什么中文分词比英文分词更难?有哪些常用算法?(附代码)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 盘点谷歌、Facebook和IBM的重磅
- 下一篇: 使用了 23 年的 Java 不再免费!