1. 程式人生 > >中文分詞工具

中文分詞工具

THULAC

四款python中中文分詞的嘗試。嘗試的有:jieba、SnowNLP(MIT)、pynlpir(大資料搜尋挖掘實驗室(北京市海量語言資訊處理與雲端計算應用工程技術研究中心))、thulac(清華大學自然語言處理與社會人文計算實驗室)
四款都有分詞功能,本部落格只介紹作者比較感興趣、每個模組的內容。jieba在這不做介紹,可見部落格:
python+gensim︱jieba分詞、詞袋doc2bow、TFIDF文字挖掘

這裡寫圖片描述
.

一、SnowNLP

只處理的unicode編碼,所以使用時請自行decode成unicode。來源:https://github.com/isnowfy/snownlp


以下功能都是筆者比較感興趣的:

情感分析(現在訓練資料主要是買賣東西時的評價,所以對其他的一些可能效果不是很好,待解決)

  • 文字分類(Naive Bayes)
  • 轉換成拼音(Trie樹實現的最大匹配)
  • 繁體轉簡體(Trie樹實現的最大匹配)
  • 提取文字關鍵詞(TextRank演算法)
  • 提取文字摘要(TextRank演算法)
  • Tokenization(分割成句子)
  • 文字相似(BM25)
# 轉化為拼音
from snownlp import SnowNLP
s = SnowNLP("杭州西湖風景很好,是旅遊勝地!")
s.pinyin
  • 1
  • 2
  • 3
  • 4
['hang',
 'zhou',
 'xi',
 'hu',
 'feng',
 'jing',
 'hen',
 'hao',
 ',',
 'shi',
 'lv',
 'you',
 'sheng',
 'di',
 '!']
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
# 繁體轉為簡體
s = SnowNLP(u'「繁體字」「繁體中文」的叫法在臺灣亦很常見。')
s.han
  • 1
  • 2
  • 3
'「繁體字」「繁體中文」的叫法在臺灣亦很常見。'
  • 1
  • 2
# 自動摘要
text = u'''自然語言處理是電腦科學領域與人工智慧領域中的一個重要方向。它研究能實現人與計算機之間用自然語言進行有效通訊的各種理論和方法。自然語言處理是一門融語言學、電腦科學、數學於一體的科學。因此,這一領域的研究將涉及自然語言,即人們日常使用的語言,所以它與語言學的研究有著密切的聯絡,但又有重要的區別。自然語言處理並不是一般地研究自然語言,而在於研製能有效地實現自然語言通訊的計算機系統,特別是其中的軟體系統。因而它是電腦科學的一部分。
'''
s = SnowNLP(text) s.summary(5)
  • 1
  • 2
  • 3
  • 4
  • 5
['因而它是電腦科學的一部分',
 '自然語言處理是電腦科學領域與人工智慧領域中的一個重要方向',
 '自然語言處理是一門融語言學、電腦科學、數學於一體的科學',
 '所以它與語言學的研究有著密切的聯絡',
 '這一領域的研究將涉及自然語言']
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
# 計算BM2.5 相似性
s = SnowNLP([[u'這篇', u'文章',u'非常好'],
             [u'那篇', u'文章',u'一般般'],
             [u'這個']])
#s.tf
s.idf
s.sim([u'這篇', u'文章',u'非常好'])# [0.3756070762985226, 0, 0]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
[0.45263029953948547, -0.45263029953948547, 0]
  • 1
  • 2

參考《文字相似度-bm25演算法原理及實現》
BM25是通過q和s中的公共詞彙進行相似度計算的演算法,BM25演算法的相關性得分公式可總結為:

本篇部落格自己寫了一個bm2.5實現的軟體。
.

二、thulac

設定比較一般,內容也可能不夠多樣性。不過有:c++ java so,僅處理UTF8編碼中文文字,之後會逐漸增加支援其他編碼的功能,敬請期待,也有三個版本的分詞模型:

  • (1)簡單的分詞模型Model_1,僅支援分詞功能。該模型由人民日報分詞語料庫訓練得到。
  • (2)分詞和詞性標註聯合模型Model_2,支援同時分詞和詞性標註功能。該模型由人民日報分詞和詞性標註語料庫訓練得到。
  • (3)我們還提供更復雜、完善和精確的分詞和詞性標註聯合模型Model_3和分詞詞表。該模型是由多語料聯合訓練訓練得到(語料包括來自多文體的標註文字和人民日報標註文字等)。由於模型較大,如有機構或個人需要,通過稽核後我們會將相關資源傳送給聯絡人。
thulac(user_dict=None, model_path=None, T2S=False, seg_only=False, filt=False, deli='_')初始化程式,進行自定義設定
  • 1

user_dict 設定使用者詞典,使用者詞典中的詞會被打上uw標籤。詞典中每一個詞一行,UTF8編碼
T2S 預設False, 是否將句子從繁體轉化為簡體
seg_only 預設False, 時候只進行分詞,不進行詞性標註
filt 預設False, 是否使用過濾器去除一些沒有意義的詞語,例如“可以”。
model_path 設定模型檔案所在資料夾,預設為models/
deli 預設為‘_’, 設定詞與詞性之間的分隔符
rm_space 預設為True, 是否去掉原文字中的空格後再進行分詞

初始化設定

thulac(user_dict=None, model_path=None, T2S=False, seg_only=False, filt=False, deli=’_’)

user_dict 設定使用者詞典,使用者詞典中的詞會被打上uw標籤。詞典中每一個詞一行,UTF8編碼
T2S 預設False, 是否將句子從繁體轉化為簡體
seg_only 預設False, 時候只進行分詞,不進行詞性標註
filt 預設False, 是否使用過濾器去除一些沒有意義的詞語,例如“可以”。
model_path 設定模型檔案所在資料夾,預設為models/
deli 預設為‘_’, 設定詞與詞性之間的分隔符
rm_space 預設為True, 是否去掉原文字中的空格後再進行分詞

分詞結果

cut(文字, text=False) 對一句話進行分詞
cut_f(輸入檔案, 輸出檔案) 對檔案進行分詞
cut和cut_f

命令列模式

python -m thulac input.txt output.txt
  • 1

從input.txt讀入,並將分詞和詞性標註結果輸出到ouptut.txt中
如果只需要分詞功能,可在增加引數”seg_only”
python -m thulac input.txt output.txt seg_only

詞性解釋

n/名詞 np/人名 ns/地名 ni/機構名 nz/其它專名
m/數詞 q/量詞 mq/數量詞 t/時間詞 f/方位詞 s/處所詞
v/動詞 a/形容詞 d/副詞 h/前接成分 k/後接成分
i/習語 j/簡稱 r/代詞 c/連詞 p/介詞 u/助詞 y/語氣助詞
e/嘆詞 o/擬聲詞 g/語素 w/標點 x/其它

thu1 = thulac.thulac(model_path = '/usr/local/lib/python3.5/dist-packages/thulac/models')  #預設模式
text = thu1.cut("杭州西湖風景很好,是旅遊勝地!", text=False)  #進行一句話分詞
print(text)
  • 1
  • 2
  • 3
Model loaded succeed
[['杭州', 'ns'], ['西湖', 'ns'], ['風景', 'n'], ['很', 'd'], ['好', 'a'], [',', 'w'], ['是', 'v'], ['旅遊', 'v'], ['勝地', 'n'], ['!', 'w']]
  • 1
  • 2
  • 3
# 與Jieba對比一下
import jieba
seg_list = jieba.cut("杭州西湖風景很好,是旅遊勝地!",
                     cut_all=False)
print("Full Mode: " + "/ ".join(seg_list))  # 全模式
  • 1
  • 2
  • 3
  • 4
  • 5
Full Mode: 杭州/ 西湖/ 風景/ 很/ 好/ ,/ 是/ 旅遊勝地/ !
  • 1
  • 2

.

三、pynlpir

載入之後就遇到了報錯:

RuntimeError: NLPIR function ‘NLPIR_Init’ failed.
  • 1

License 這是授權資料夾,存放了十一個元件的授權檔案 license for 7 days: 授權期限為7天 license for one month: 授權期限為一個月。
也就是說,要不斷更新license,開源的真不徹底,之後就沒嘗試其中的功能了。

import pynlpir
s = 'NLPIR分詞系統前身為2000年釋出的ICTCLAS詞法分析系統,從2009年開始,為了和以前工作進行大的區隔,並推廣NLPIR自然語言處理與資訊檢索共享平臺,調整命名為NLPIR分詞系統。'
pynlpir.segment(s)
  • 1
  • 2
  • 3

.

四、CoreNLP3.8.0——多功能

分詞、詞性標註(Part-Of-Speech tag, POS-tag)、命名實體識別(Named Entity Recognition, NER)、句法分析(Syntactic Parse)等各項 NLP 領域的功能。
stanfordcorenlp是一個對Stanford CoreNLP進行了封裝的Python工具包,GitHub地址,使用非常方便。

4.1安裝(Ubuntu)

依賴,需求:
1.Java 1.8+ (Check with command: java -version)
2.Stanford CoreNLP 3.8.0(主模組,.rar的解壓包,安裝路徑
3.語言模型,這裡是中文模型,安裝路徑),其他還有的語言有:
阿拉伯語、漢語、英語、法語、德語、西班牙語(5大類,.jar格式)

下載完,解壓Stanford CoreNLP 3.8.0,然後把語言模型放在解壓目錄下就ok了!!

# sudo pip install stanfordcorenlp
  • 1

簡單使用,記得引數lang=’zh’

from stanfordcorenlp import StanfordCoreNLP
nlp = StanfordCoreNLP(r'/home/gld/stanford-corenlp-full-2016-10-31/', lang='zh')
sentence = '清華大學位於北京。'
print nlp.word_tokenize(sentence)
print nlp.pos_tag(sentence)
print nlp.ner(sentence)
print nlp.parse(sentence)
print nlp.dependency_parse(sentence)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

輸出:

[清華, 大學, 位於, 北京, 。]
[(清華, NR), (大學, NN), (位於, VV), (北京, NR), (。, PU)]
[(清華, ORGANIZATION), (大學, ORGANIZATION), (位於, O), (北京, GPE), (。, O)]
...
  • 1
  • 2
  • 3
  • 4

4.2案例:

from stanfordcorenlp import StanfordCoreNLP
nlp = StanfordCoreNLP(r'/.../corenlp/stanford-corenlp-full-2017-06-09/', lang='zh')
  • 1
  • 2

lang=’zh’代表中文,然後就會自動去搜索中文的語言模型的.jar檔案。

sentence =  '元芳你怎麼看?我就趴視窗上看唄!'
print ('Tokenize:', nlp.word_tokenize(sentence))
print ('Part of Speech:', nlp.pos_tag(sentence))
print ('Named Entities:', nlp.ner(sentence))
print ('Constituency Parsing:', nlp.parse(sentence))
print ('Dependency Parsing:', nlp.dependency_parse(sentence))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

現在這個版本非常簡潔,比用ltp要好不少,不過從筆者自己的實踐來看,分詞模組還只是一般,而且沒看到有可以新加入詞典,畢竟不是本土研究機構。

現在的輸出結果如下:

Tokenize: ['元芳', '你', '怎麼', '看', '?', '我', '就', '趴', '視窗', '上看唄', '!']
Part of Speech: [('元芳', 'NR'), ('你', 'PN'), ('怎麼', 'AD'), ('看', 'VV'), ('?', 'PU'), ('我', 'PN'), ('就', 'AD'), ('趴', 'VV'), ('視窗', 'NN'), ('上看唄', 'NN'), ('!', 'PU')]
Named Entities: [('元芳', 'O'), ('你', 'O'), ('怎麼', 'O'), ('看', 'O'), ('?', 'O'), ('我', 'O'), ('就', 'O'), ('趴', 'O'), ('視窗', 'O'), ('上看唄', 'O'), ('!', 'O')]
Constituency Parsing: (ROOT
  (IP
    (IP
      (NP (NR 元芳))
      (IP
        (NP (PN 你))
        (VP
          (ADVP (AD 怎麼))
          (VP (VV 看))))
      (PU ?))
    (NP (PN 我))
    (VP
      (ADVP (AD 就))
      (VP (VV 趴)
        (NP (NN 視窗) (NN 上看唄))))
    (PU !)))
Dependency Parsing: [('ROOT', 0, 4), ('nmod:topic', 4, 1), ('nsubj', 4, 2), ('advmod', 4, 3), ('punct', 4, 5), ('nsubj', 8, 6), ('advmod', 8, 7), ('conj', 4, 8), ('compound:nn', 10, 9), ('dobj', 8, 10), ('punct', 4, 11)]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

貼一下之前版本的一些實驗結果圖:

這裡寫圖片描述

這裡寫圖片描述

這裡寫圖片描述

這裡寫圖片描述

這裡寫圖片描述

4.3 詞性、句法分析、依存關係的符號解釋

詞性解釋

CC: conjunction, coordinatin 表示連詞
CD: numeral, cardinal 表示基數詞
DT: determiner 表示限定詞
EX: existential there 存在句
FW: foreign word 外來詞
IN: preposition or conjunction, subordinating 介詞或從屬連詞
JJ: adjective or numeral, ordinal 形容詞或序數詞
JJR: adjective, comparative 形容詞比較級
JJS: adjective, superlative 形容詞最高階
LS: list item marker 列表標識
MD: modal auxiliary 情態助動詞
NN: noun, common, singular or mass
NNS: noun, common, plural
NNP: noun, proper, singular
NNPS: noun, proper, plural
PDT: pre-determiner 前位限定詞
POS: genitive marker 所有格標記
PRP: pronoun, personal 人稱代詞
PRP:pronoun,possessiveRB:adverbRBR:adverb,comparativeRBS:adverb,superlativeRP:particleSYM:symbolTO:toasprepositionorinfinitivemarkerUH:interjectionVB:verb,baseformVBD:verb,pasttenseVBG:verb,presentparticipleorgerundVBN:verb,pastparticipleVBP:verb,presenttense,not3rdpersonsingularVBZ:verb,presenttense,3rdpersonsingularWDT:WHdeterminerWHWP:WHpronounWHWP: pronoun, possessive 所有格代詞 RB: adverb 副詞 RBR: adverb, comparative 副詞比較級 RBS: adverb, superlative 副詞最高階 RP: particle 小品詞 SYM: symbol 符號 TO:”to” as preposition or infinitive marker 作為介詞或不定式標記 UH: interjection 插入語 VB: verb, base form VBD: verb, past tense VBG: verb, present participle or gerund VBN: verb, past participle VBP: verb, present tense, not 3rd person singular VBZ: verb, present tense,3rd person singular WDT: WH-determiner WH限定詞 WP: WH-pronoun WH代詞 : WH-pronoun, possessive WH所有格代詞
WRB:Wh-adverb WH副詞

句法分析(句法樹)

ROOT:要處理文字的語句
IP:簡單從句
NP:名詞短語
VP:動詞短語
PU:斷句符,通常是句號、問號、感嘆號等標點符號
LCP:方位詞短語
PP:介詞短語
CP:由‘的’構成的表示修飾性關係的短語
DNP:由‘的’構成的表示所屬關係的短語
ADVP:副詞短語
ADJP:形容詞短語
DP:限定詞短語
QP:量詞短語
NN:常用名詞
NR:固有名詞:表示僅適用於該項事物的名詞,含地名,人名,國名,書名,團體名稱以及一事件的名稱等。
NT:時間名詞
PN:代詞
VV:動詞
VC:是
CC:表示連詞
VE:有
VA:表語形容詞
AS:內容標記(如:了)
VRD:動補複合詞
CD: 表示基數詞
DT: determiner 表示限定詞
EX: existential there 存在句
FW: foreign word 外來詞
IN: preposition or conjunction, subordinating 介詞或從屬連詞
JJ: adjective or numeral, ordinal 形容詞或序數詞
JJR: adjective, comparative 形容詞比較級
JJS: adjective, superlative 形容詞最高階
LS: list item marker 列表標識
MD: modal auxiliary 情態助動詞
PDT: pre-determiner 前位限定詞
POS: genitive marker 所有格標記
PRP: pronoun, personal 人稱代詞
RB: adverb 副詞
RBR: adverb, comparative 副詞比較級
RBS: adverb, superlative 副詞最高階
RP: particle 小品詞
SYM: symbol 符號
TO:”to” as preposition or infinitive marker 作為介詞或不定式標記
WDT: WH-determiner WH限定詞
WP: WH-pronoun WH代詞
WP$: WH-pronoun, possessive WH所有格代詞
WRB:Wh-adverb WH副詞

關係表示

abbrev: abbreviation modifier,縮寫
acomp: adjectival complement,形容詞的補充;
advcl : adverbial clause modifier,狀語從句修飾詞
advmod: adverbial modifier狀語
agent: agent,代理,一般有by的時候會出現這個
amod: adjectival modifier形容詞
appos: appositional modifier,同位詞
attr: attributive,屬性
aux: auxiliary,非主要動詞和助詞,如BE,HAVE SHOULD/COULD等到
auxpass: passive auxiliary 被動詞
cc: coordination,並列關係,一般取第一個詞
ccomp: clausal complement從句補充
complm: complementizer,引導從句的詞好重聚中的主要動詞
conj : conjunct,連線兩個並列的詞。
cop: copula。系動詞(如be,seem,appear等),(命題主詞與謂詞間的)連繫
csubj : clausal subject,從主關係
csubjpass: clausal passive subject 主從被動關係
dep: dependent依賴關係
det: determiner決定詞,如冠詞等
dobj : direct object直接賓語
expl: expletive,主要是抓取there
infmod: infinitival modifier,動詞不定式
iobj : indirect object,非直接賓語,也就是所以的間接賓語;
mark: marker,主要出現在有“that” or “whether”“because”, “when”,
mwe: multi-word expression,多個詞的表示
neg: negation modifier否定詞
nn: noun compound modifier名詞組合形式
npadvmod: noun phrase as adverbial modifier名詞作狀語
nsubj : nominal subject,名詞主語
nsubjpass: passive nominal subject,被動的名詞主語
num: numeric modifier,數值修飾
number: element of compound number,組合數字
parataxis: parataxis: parataxis,並列關係
partmod: participial modifier動詞形式的修飾
pcomp: prepositional complement,介詞補充
pobj : object of a preposition,介詞的賓語
poss: possession modifier,所有形式,所有格,所屬
possessive: possessive modifier,這個表示所有者和那個’S的關係
preconj : preconjunct,常常是出現在 “either”, “both”, “neither”的情況下
predet: predeterminer,字首決定,常常是表示所有
prep: prepositional modifier
prepc: prepositional clausal modifier
prt: phrasal verb particle,動詞短語
punct: punctuation,這個很少見,但是保留下來了,結果當中不會出現這個
purpcl : purpose clause modifier,目的從句
quantmod: quantifier phrase modifier,數量短語
rcmod: relative clause modifier相關關係
ref : referent,指示物,指代
rel : relative
root: root,最重要的詞,從它開始,根節點
tmod: temporal modifier
xcomp: open clausal complement
xsubj : controlling subject 掌控者

參考:

五、 pyltp

“語言云” 以哈工大社會計算與資訊檢索研究中心研發的 “語言技術平臺(LTP)” 為基礎,為使用者提供高效精準的中文自然語言處理雲服務。
pyltp 是 LTP 的 Python 封裝,提供了分詞,詞性標註,命名實體識別,依存句法分析,語義角色標註的功能。

需要先載入他們訓練好的模型,下載地址

1.分詞

# -*- coding: utf-8 -*-
from pyltp import SentenceSplitter
sents = SentenceSplitter.split('元芳你怎麼看?我就趴視窗上看唄!')  # 分句
print '\n'.join(sents)
im
port os
LTP_DATA_DIR = '/path/to/your/ltp_data'  # ltp模型目錄的路徑
cws_model_path = os.path.join(LTP_DATA_DIR, 'cws.model')  # 分詞模型路徑,模型名稱為`cws.model`

from pyltp import Segmentor
segmentor = Segmentor()  # 初始化例項
segmentor.load(cws_model_path)  # 載入模型
words = segmentor.segment('元芳你怎麼看')  # 分詞
print '\t'.join(words)
segmentor.release()  # 釋放模型
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

SentenceSplitter分句子,把段落拆分成句子;segmentor.segment分詞

如果要使用外部詞典,需要,載入模型的時候,指定新的字典集:

segmentor = Segmentor()  # 初始化例項
segmentor.load_with_lexicon(cws_model_path, '/path/to/your/lexicon') # 載入模型,第二個引數是您的外部詞典檔案路徑
  • 1
  • 2

2.詞性標註

import os
LTP_DATA_DIR = '/path/to/your/ltp_data'  # ltp模型目錄的路徑
pos_model_path = os.path.join(LTP_DATA_DIR, 'pos.model')  # 詞性標註模型路徑,模型名稱為`pos.model`

from pyltp import Postagger
postagger = Postagger() # 初始化例項
postagger.load(pos_model_path)  # 載入模型

words = ['元芳', '你', '怎麼', '看']  # 分詞結果
postags = postagger.postag(words)  # 詞性標註

print '\t'.join(postags)
postagger.release()  # 釋放模型
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

3.命名實體識別

# -*- coding: utf-8 -*-
import os
LTP_DATA_DIR = '/path/to/your/ltp_data'  # ltp模型目錄的路徑
ner_model_path = os.path.join(LTP_DATA_DIR, 'ner.model')  # 命名實體識別模型路徑,模型名稱為`pos.model`

from pyltp