jieba中文分詞的.NET版本:jieba.NET

jopen 9年前發布 | 18K 次閱讀 jieba.NET .NET開發

簡介

平時經常用Python寫些小程序。在做文本分析相關的事情時免不了進行中文分詞,于是就遇到了用Python實現的 結巴中文分詞 。jieba使用起來非常簡單,同時分詞的結果也令人印象深刻,有興趣的可以到它的 在線演示站點 體驗下(注意第三行文字)。

.NET平臺上常見的分詞組件是 盤古分詞 ,但是已經好久沒有更新了。最明顯的是內置詞典,jieba的詞典有50萬個詞條,而盤古的詞典是17萬,這樣會造成明顯不同的分詞效果。另外,對于未登錄詞,jieba“采用了基于漢字成詞能力的HMM模型,使用了Viterbi算法”,效果看起來也不錯。

基于以上兩點,加上對于中文分詞的興趣,就嘗試將jieba移植到.NET平臺上,已經把代碼放在了github上: jieba.NET 。在試用jieba.NET之前,先簡單介紹下jieba的實現思路。

jieba實現淺析

jieba本身提供的文檔較少,但我們可以在《 對Python中文分詞模塊結巴分詞算法過程的理解和分析 》、《 jieba 分詞源代碼研讀(1) 》這一系列文章中一窺jieba實現的整體思路。簡言之,它的核心模塊和分詞過程大致是:

  • 前綴詞典(Trie) :用于存儲主詞典,也可以動態增刪詞條,這個詞典可以理解為jieba所“知道”的詞,或者說已登錄詞;
  • 有向無環圖(DAG) :通過前綴詞典,可以找出句子所有可能的成詞結果;
  • 最大概率路徑 :通過DAG,可以了解 所有的 成詞結果,每個結果對應于一條路徑及其概率。由于不同詞條的出現概率不同,不同的結果就對應了不同的概率,我們找出概率最大的那條路徑。到這里,我們對于已登錄詞做出了最合理的劃分;
  • HMM模型Viterbi算法 :最大概率路徑之后,我們可能會遇到一些未登錄詞(不包含在前綴詞典中的詞),這時通過HMM和Viterbi嘗試進一步的劃分,得到最終結果

這個過程與人的分詞過程很類似。比如看到這句話:“語言學家參加學術會議 ”,我們會把它劃分為:“語言學家 參加 學術會議”。盡管這個過程是瞬間完成的,但是它確實包含了上述過程的前三步:分詞之前,大腦中已有一個“前綴詞典”,它包括語言、語言學、語言學家等等各個詞條;大腦知道這句話確實存在多種分詞的可能;但它最后還是選出了那個最可能的結果,舍棄了諸如“語言學 家 參加 學術 會議”這樣的結果。

前面這句話僅包含了已登錄詞,再來看另一句話:“ 他來到了網易杭研大廈 ”。一般人可以迅速做出劃分:“ 他 來到 了 網易 (杭研)? 大廈 ”,除了“ 杭研”這兩個字,其它的都屬于已登錄詞,容易劃分出來。對于“ 杭研 ”,我們要想一想它們是兩個單字呢,還是一個新詞。最后,可能會伴隨著這樣一個過程:我知道網易是有研發中心或研究院之類的在杭州的,那么“杭研”可能是與此相關的一個縮寫,嗯,又知道了一個新詞。盡管這個過程與HMM不同,但我們至少了解到,jieba確實是通過某種方式去嘗試尋找未登錄詞。

不過可以想象的是,基于狀態轉移概率的HMM模型(建議參考文章《 中文分詞之HMM模型詳解 》)能夠發現的詞應該也是比較自然或正常的詞,對于新的人名、機構名或網絡詞(喜大普奔之類的),效果不會很好。

jieba.NET用法

jieba.NET當前版本是0.37.1,與jieba保持一致,可以通過NuGet安裝:

PM> Install-Package jieba.NET

安裝之后,把Resources目錄copy到程序集所在目錄即可。下面分別是分詞、詞性標注和關鍵詞提取的示例。

分詞

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的開發剛剛開始,還有很多細節需要完善。非常歡迎大家的試用和反饋,也希望能和大家一起討論,共同實現更好的中文分詞庫。

參考:

結巴中文分詞

對Python中文分詞模塊結巴分詞算法過程的理解和分析

中文分詞之HMM模型詳解

結巴分詞Java版

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!