平時常常用Python寫些小程序。在作文本分析相關的事情時免不了進行中文分詞,因而就遇到了用Python實現的結巴中文分詞。jieba使用起來很是簡單,同時分詞的結果也使人印象深入,有興趣的能夠到它的在線演示站點體驗下(注意第三行文字)。html
.NET平臺上常見的分詞組件是盤古分詞,可是已經很久沒有更新了。最明顯的是內置詞典,jieba的詞典有50萬個詞條,而盤古的詞典是17萬,這樣會形成明顯不一樣的分詞效果。另外,對於未登陸詞,jieba「採用了基於漢字成詞能力的HMM模型,使用了Viterbi算法」,效果看起來也不錯。git
基於以上兩點,加上對於中文分詞的興趣,就嘗試將jieba移植到.NET平臺上,已經把代碼放在了github上:jieba.NET。在試用jieba.NET以前,先簡單介紹下jieba的實現思路。github
jieba自己提供的文檔較少,但咱們能夠在《對Python中文分詞模塊結巴分詞算法過程的理解和分析》、《jieba 分詞源代碼研讀(1)》這一系列文章中一窺jieba實現的總體思路。簡言之,它的核心模塊和分詞過程大體是:算法
這個過程與人的分詞過程很相似。好比看到這句話:「語言學家參加學術會議」,咱們會把它劃分爲:「語言學家 參加 學術會議」。儘管這個過程是瞬間完成的,可是它確實包含了上述過程的前三步:分詞以前,大腦中已有一個「前綴詞典」,它包括語言、語言學、語言學家等等各個詞條;大腦知道這句話確實存在多種分詞的可能;但它最後仍是選出了那個最可能的結果,捨棄了諸如「語言學 家 參加 學術 會議」這樣的結果。小程序
前面這句話僅包含了已登陸詞,再來看另外一句話:「他來到了網易杭研大廈」。通常人能夠迅速作出劃分:「他 來到 了 網易 (杭研)? 大廈」,除了「杭研」這兩個字,其它的都屬於已登陸詞,容易劃分出來。對於「杭研」,咱們要想想它們是兩個單字呢,仍是一個新詞。最後,可能會伴隨着這樣一個過程:我知道網易是有研發中心或研究院之類的在杭州的,那麼「杭研」多是與此相關的一個縮寫,嗯,又知道了一個新詞。儘管這個過程與HMM不一樣,但咱們至少了解到,jieba確實是經過某種方式去嘗試尋找未登陸詞。網絡
不過能夠想象的是,基於狀態轉移機率的HMM模型(建議參考文章《中文分詞之HMM模型詳解》)可以發現的詞應該也是比較天然或正常的詞,對於新的人名、機構名或網絡詞(喜大普奔之類的),效果不會很好。函數
jieba.NET當前版本是0.37.1,與jieba保持一致,能夠經過NuGet安裝:post
PM> Install-Package jieba.NET
安裝以後,把Resources目錄copy到程序集所在目錄便可。下面分別是分詞、詞性標註和關鍵詞提取的示例。
ui
var segmenter = new JiebaSegmenter(); var segments = segmenter.Cut("我來到北京清華大學", cutAll: true); Console.WriteLine("【全模式】:{0}", string.Join("/ ", segments)); segments = segmenter.Cut("我來到北京清華大學"); // 默認爲精確模式 Console.WriteLine("【精確模式】:{0}", string.Join("/ ", segments)); segments = segmenter.Cut("他來到了網易杭研大廈"); // 默認爲精確模式,同時也使用HMM模型 Console.WriteLine("【新詞識別】:{0}", string.Join("/ ", segments)); segments = segmenter.CutForSearch("小明碩士畢業於中國科學院計算所,後在日本京都大學深造"); // 搜索引擎模式 Console.WriteLine("【搜索引擎模式】:{0}", string.Join("/ ", segments)); segments = segmenter.Cut("結過婚的和還沒有結過婚的"); Console.WriteLine("【歧義消除】:{0}", string.Join("/ ", segments));
運行結果爲:搜索引擎
【全模式】:我/ 來到/ 北京/ 清華/ 清華大學/ 華大/ 大學
【精確模式】:我/ 來到/ 北京/ 清華大學 【新詞識別】:他/ 來到/ 了/ 網易/ 杭研/ 大廈 【搜索引擎模式】:小明/ 碩士/ 畢業/ 於/ 中國/ 科學/ 學院/ 科學院/ 中國科學院/ 計算/ 計算所/ ,/ 後/ 在/ 日本/ 京都/ 大學/ 日本京都大學/ 深造 【歧義消除】:結過婚/ 的/ 和/ 還沒有/ 結過婚/ 的
JiebaSegmenter.Cut方法可經過cutAll來支持兩種模式,精確模式和全模式。精確模式是最基礎和天然的模式,試圖將句子最精確地切開,適合文本分析;而全模式,把句子中全部的能夠成詞的詞語都掃描出來, 速度更快,可是不能解決歧義,由於它不會掃描最大機率路徑,也不會經過HMM去發現未登陸詞。
CutForSearch採用的是搜索引擎模式,在精確模式的基礎上對長詞再次切分,提升召回率,適合用於搜索引擎分詞。
詞性標註採用和ictclas兼容的標記法,關於ictclas和jieba中使用的標記法列表,請參考:詞性標記。
var posSeg = new PosSegmenter(); var s = "一團碩大無朋的高能離子云,在遙遠而神祕的太空中迅疾地飄移"; var tokens = posSeg.Cut(s); Console.WriteLine(string.Join(" ", tokens.Select(token => string.Format("{0}/{1}", token.Word, token.Flag))));
運行結果
一團/m 碩大無朋/i 的/uj 高能/n 離子/n 雲/ns ,/x 在/p 遙遠/a 而/c 神祕/a 的/uj 太空/n 中/f 迅疾/z 地/uv 飄移/v
看下面來自維基百科的關於算法的文字:
在數學和計算機科學/算學之中,算法/算則法(Algorithm)爲一個計算的具體步驟,經常使用於計算、數據處理和自動推理。精確而言,算法是一個表示爲有限長列表的有效方法。算法應包含清晰定義的指令用於計算函數。
算法中的指令描述的是一個計算,當其運行時能從一個初始狀態和初始輸入(可能爲空)開始,通過一系列有限而清晰定義的狀態最終產生輸出並中止於一個終態。一個狀態到另外一個狀態的轉移不必定是肯定的。隨機化算法在內的一些算法,包含了一些隨機輸入。
形式化算法的概念部分源自嘗試解決希爾伯特提出的斷定問題,並在其後嘗試定義有效計算性或者有效方法中成形。這些嘗試包括庫爾特·哥德爾、雅克·埃爾布朗和斯蒂芬·科爾·克萊尼分別於1930年、1934年和1935年提出的遞歸函數,阿隆佐·邱奇於1936年提出的λ演算,1936年Emil Leon Post的Formulation 1和艾倫·圖靈1937年提出的圖靈機。即便在當前,依然常有直覺想法難以定義爲形式化算法的狀況。
如今來嘗試提取其中的關鍵詞。jieba.NET提供了TF-IDF和TextRank兩種算法來提取關鍵詞,TF-IDF對應的類是JiebaNet.Analyser.TfidfExtractor,TextRank的是JiebaNet.Analyser.TextRankExtractor。
var extractor = new TfidfExtractor();
// 提取前十個僅包含名詞和動詞的關鍵詞 var keywords = extractor.ExtractTags(text, 10, Constants.NounAndVerbPos); foreach (var keyword in keywords) { Console.WriteLine(keyword); }
運行結果是
算法
定義
計算
嘗試
形式化
提出
狀態
指令
輸入
包含
相應的ExtractTagsWithWeight方法的返回結果中除了包含關鍵詞,還包含了相應的權重值。TextRankExtractor的接口與TfidfExtractor徹底一致,再也不贅述。
分詞、詞性標註和關鍵詞提取是jieba的三個主要功能模塊,jieba.NET目前儘可能在功能和接口上與jieba保持一致,但之後可能會在jieba基礎上提供其它擴展功能。jieba.NET的開發剛剛開始,還有不少細節須要完善。很是歡迎你們的試用和反饋,也但願能和你們一塊兒討論,共同實現更好的中文分詞庫。
參考來源:jieba中文分詞的.NET版本:jieba.NET
GitHub源碼地址: