NLP-结巴分词
結(jié)巴分詞
結(jié)巴分詞是有國內(nèi)程序員(https://github.com/fxsjy/jieba)做的一個分詞工具,剛開始是Python版本的,后來由anderscui(https://github.com/anderscui/jieba.NET )移植到.Net上面。
結(jié)巴分詞的分詞過程大致為:
·前綴詞典(Trie):用于存儲主詞典,也可以動態(tài)增刪詞條,這個詞典可以理解為jieba所“知道”的詞,或者說已登錄詞;
·有向無環(huán)圖(DAG):通過前綴詞典,可以找出句子所有可能的成詞結(jié)果;
·最大概率路徑:通過DAG,可以了解所有的成詞結(jié)果,每個結(jié)果對應(yīng)于一條路徑及其概率。由于不同詞條的出現(xiàn)概率不同,不同的結(jié)果就對應(yīng)了不同的概率,我們找出概率最大的那條路徑。到這里,我們對于已登錄詞做出了最合理的劃分;
·HMM模型和Viterbi算法:最大概率路徑之后,我們可能會遇到一些未登錄詞(不包含在前綴詞典中的詞),這時通過HMM和Viterbi嘗試進一步的劃分,得到最終結(jié)果
剛開始結(jié)巴分詞只有分詞功能,后來加入了詞性標(biāo)注、關(guān)鍵詞提取等功能,加上其開源的屬性,還是很好用的。
安裝方法
通過NuGet包管理器安裝jieba.NET
在當(dāng)前項目安裝了結(jié)巴分詞之后,可以在當(dāng)前項目的packages\jieba.NET\文件夾下看到一個Resource文件夾,里面是結(jié)巴分詞所需要的各種數(shù)據(jù)文件,需要對數(shù)據(jù)文件的位置進行配置才能使用。有幾種方法:
????方法一、對于VS項目來說,直接將Resource文件夾拷貝到項目的bin\Debug\目錄下。
???????? ??????????方法二、修改VS的配置文件app.config,加入如下配置項。
<appSettings>
??? <add key="JiebaConfigFileDir" value=fileDir />
</appSettings>
其中的fileDir就是Resource文件夾的內(nèi)容所在的目錄
Jieba.NET使用
分詞
結(jié)巴提供了三種分詞的方法:
精確模式:試圖將句子最精確地切開,適合文本分析;
全模式:把句子中所有的可以成詞的詞語都掃描出來,?速度非常快,但是不能解決歧義問題;
搜索引擎模式:在精確模式的基礎(chǔ)上,對長詞再次切分,提高召回率,適合用于搜索引擎分詞。
對于未登錄詞,采用了基于漢字成詞能力的HMM模型,使用了Viterbi算法。
下面請看詳細(xì)用法:
1.??????精確模式
<span style="color:#333333"><span style="background-color:#f5f5f5">using?System;
using?System.Collections.Generic;
using?System.Linq;
using?System.Text;
using?System.Threading.Tasks;
using?JiebaNet.Analyser;
using?JiebaNet.Segmenter;
namespace?JiebaTest
{class?Program{static?void?Main(string[]?args){??????????string?text?=?"當(dāng)人類得知宇宙的黑暗森林狀態(tài)后,這個在篝火旁大喊的孩子立刻?澆滅了火,在黑暗中瑟瑟發(fā)抖,連一顆火星都害怕了。在最初的幾天里,甚至民用移動通信都被禁止,全球大部分通信基站?都被強令關(guān)閉。";var?segmenter?=?new?JiebaSegmenter();//使用精確模式,函數(shù)參數(shù):待分詞文本,關(guān)閉全模式,不使用hmm模型var?result?=?segmenter.Cut(text,cutAll:?false,?hmm:?false);Console.WriteLine("{0}",?string.Join("/",?result));Console.ReadKey();}}
}</span></span>
運行結(jié)果:
2.??????全模式
與精確模式不同的只有如下一句:
<span style="color:#333333"><span style="background-color:#f5f5f5">var?result1?=?segmenter.Cut(text,?cutAll:true,?hmm:?false);</span></span>
可以看到會有重復(fù)分詞的現(xiàn)象,這是因為結(jié)巴分詞把歧義詞項一并列出來的緣故。
3.??????搜索模式
<span style="color:#333333"><span style="background-color:#f5f5f5">????????????var?result2?=?segmenter.CutForSearch(text,hmm:true);Console.WriteLine("{0}",?string.Join("/",?result2));</span></span>
CutForSearch()只有兩個參數(shù),意義也和精確模式一樣,程序運行結(jié)果:
?
自定義分詞
很多時候我們需要針對自己的場景進行分詞,會有一些領(lǐng)域內(nèi)的專有詞匯。這時候我們需要讓分詞器能識別特定的詞或者不識別特定的詞。有兩種方法:
1.?對于少量的詞匯,我們可以通過AddWord()函數(shù)添加新詞和調(diào)整詞頻,通過DeleteWord()函數(shù)刪除詞典中的某一詞使分詞器不再將其作為一個詞;若AddWord()的參數(shù)freq不是正整數(shù),則使用自動計算出的詞頻,計算出的詞頻可保證該詞被分出來。
2.?通過LoadUserDict(“usr_dict_path”)函數(shù)添加自定義的詞典。開發(fā)者可以指定自定義的詞典,以便包含jieba詞庫里沒有的詞。雖然jieba有新詞識別能力,但是自行添加新詞可以保證更高的正確率。詞典格式與主詞典格式相同,即一行包含:詞、詞頻(可省略)、詞性(可省略),用空格隔開。詞頻省略時,分詞器將使用自動計算出的詞頻保證該詞被分出。
下面請看詳細(xì)介紹:
1.AddWord()和DeleteWord()的使用
程序運行結(jié)果:
<span style="color:#333333"><span style="background-color:#f5f5f5">using?System;
using?System.Collections.Generic;
using?System.Linq;
using?System.Text;
using?System.Threading.Tasks;
using?JiebaNet.Analyser;
using?JiebaNet.Segmenter;namespace?JiebaTest
{class?Program{static?void?Main(string[]?args){var?segmenter?=?new?JiebaSegmenter();string?hello?=?"大家好,這個人叫陳建驅(qū)";var?result_hello?=?segmenter.Cut(hello,hmm:false);Console.WriteLine("{0}",?string.Join("/",?result_hello));segmenter.AddWord("陳建驅(qū)",freq:0,tag:null);var?result_hello1?=?segmenter.Cut(hello,?hmm:?false);Console.WriteLine("{0}",?string.Join("/",?result_hello1));segmenter.DeleteWord("陳建驅(qū)");?//使用JiebaSegmenter.DeleteWord(word)可移除一個詞,使其不能被分出來var?result_hello2?=?segmenter.Cut(hello,?hmm:?false);Console.WriteLine("{0}",?string.Join("/",?result_hello2));Console.ReadKey();}}
}</span></span>
2.加載自定義詞典
首先加載這個詞典,我把它放到了運行目錄下:
然后對比加載詞典前后的區(qū)別,代碼如下:
<span style="color:#333333"><span style="background-color:#f5f5f5">segmenter.LoadUserDict("usr_dict_file_path");
var?result_hello1?=?segmenter.Cut(hello,?hmm:?false);
Console.WriteLine("{0}",?string.Join("/",?result_hello1));</span></span>
運行結(jié)果:
待續(xù)。。。
?
關(guān)鍵詞提取
Jieba有兩種關(guān)鍵詞提取的算法,一種是基于TF-IDF算法的關(guān)鍵詞提取,另一種是基于TextRank算法的關(guān)鍵詞提取。后者在語料庫小時效果較差。
TF-IDF關(guān)鍵詞抽取基于逆向文件頻率(IDF),組件內(nèi)置一個IDF語料庫,可以配置為其它自定義的語料庫。關(guān)鍵詞抽取會過濾停用詞(Stop Words),組件內(nèi)置一個停用詞語料庫,這個語料庫合并了NLTK的英文停用詞和哈工大的中文停用詞。
1.??????基于TF-IDF的關(guān)鍵詞提取
通過TfidfExtractor類的ExtractTags()方法調(diào)用該算法,剛方法有四個參數(shù),各個參數(shù)的意義如下:
text:待提取的文本
count:選取權(quán)值最高的count個詞返回
allowPos:對哪些詞進行選取,null為默認(rèn)值,表示不過濾特定的詞
代碼實現(xiàn):
<span style="color:#333333"><span style="background-color:#f5f5f5">using?System;
using?System.Collections.Generic;
using?System.Linq;
using?System.Text;
using?System.Threading.Tasks;
using?JiebaNet.Analyser;
using?JiebaNet.Segmenter;namespace?JiebaTest
{class?Program{static?void?Main(string[]?args){string?text1?=?"在塔的二層,被劍釘在墻上的女魔法師死了,她可能是人類歷史上唯?一真正的魔法師。而在這之前約十小時,短暫的魔法時代也結(jié)束了。魔?法時代開始于公元?1453?年?5?月?3?日?16?時,那時高維碎塊首次接觸地球;?結(jié)束于?1453?年?5?月?28?日?21?時,這時碎塊完全離開地球;歷時二十五天?五小時。之后,這個世界又回到了正常的軌道上。29?日傍晚,君士坦丁堡陷落了。在一天的慘烈血戰(zhàn)接近尾聲時,君士坦丁十一世面對著蜂擁而來的?奧斯曼軍隊,高喊一聲:“灘道就沒有一個基督徒來砍下我的頭嗎?!”然后?皇帝掀下紫袍,拔劍沖人敵陣,他那銀色的盔甲像扔進暗紅色鏹水的一小?片錫箔,轉(zhuǎn)瞬間無影無蹤。。。。。。君士坦丁堡陷落的歷史意義許久之后才顯現(xiàn)出來,事情發(fā)生時人們?首先想到的,就是羅馬帝國終于完全消失了。拜占庭是古羅馬拖在身后?的長達(dá)千年的車轍,雖也有過輝煌,但還是終于像烈日下的水漬一樣蒸發(fā)?了。當(dāng)年,古羅馬人在宏偉華麗的浴宮中吹著口哨,認(rèn)為帝國就像身下的?浴池一樣,建在整塊花崗巖上,將永世延續(xù)。現(xiàn)在人們知道,沒有不散的宴席,一切都有個盡頭。";var?tf_idf?=?new?TfidfExtractor();var?tem?=?tf_idf.ExtractTags(text1,?count:?10,?allowPos:?null);Console.WriteLine("{0}",?string.Join("/",?tem));Console.WriteLine("\n");//帶權(quán)重的關(guān)鍵詞提取var?temW?=?tf_idf.ExtractTagsWithWeight(text1,?count:?10,?allowPos:?null);foreach(var?t?in?temW)Console.WriteLine("{0}?{1}",t.Word,t.Weight);Console.WriteLine("\n");Console.ReadKey();}}
}</span></span>
運行結(jié)果:
?
2.??????基于TextRank的關(guān)鍵詞提取
該算法通過TextRankExtractor類的ExtractTags()類調(diào)用,方法參數(shù)和上面的一樣。下面的代碼中對提取的范圍進行了限制,只分析動詞和名詞。
代碼實現(xiàn):
<span style="color:#333333"><span style="background-color:#f5f5f5">List<string>?strlist?=?new?List<string>();
strlist.Add("n");
strlist.Add("v");
IEnumerable<string>?allow=strlist;
//基于TextRank的關(guān)鍵詞提取,接口和TF-IDF一樣
var?textRankExtractor?=?new?TextRankExtractor();
//textRankExtractor.Span?=?5;//調(diào)整固定窗口的大小
var?tem1?=?textRankExtractor.ExtractTags(text1,count:10,allowPos:allow);
Console.WriteLine("{0}",?string.Join("/",?tem1));
Console.WriteLine("\n");
var?tem2?=?textRankExtractor.ExtractTagsWithWeight(text1,?count:?10,?allowPos:?null);
foreach?(var?t?in?tem2)Console.WriteLine("{0}?{1}",?t.Word,?t.Weight);
Console.WriteLine("\n");</span></span>
?
運行結(jié)果:
詞性標(biāo)注
通過jieba.posseg.POSTokenizer(tokenizer=None)?可以自定義分詞器,tokenizer?參數(shù)可指定內(nèi)部使用的?jieba.Tokenizer?分詞器。jieba.posseg.dt?為默認(rèn)詞性標(biāo)注分詞器。標(biāo)注句子分詞后每個詞的詞性,采用和?ictclas?兼容的標(biāo)記法。
代碼如下:
<span style="color:#333333"><span style="background-color:#f5f5f5">var?posSegmenter?=?new?JiebaNet.Segmenter.PosSeg.PosSegmenter();
var?tokens?=?posSegmenter.Cut(text);
Console.WriteLine(string.Join("?",?tokens.Select(token?=>?string.Format("{0}/{1}",?token.Word,?token.Flag))));</span></span>
運行結(jié)果:
詞性符號采用《計算所漢語詞性標(biāo)記集》,詳情可查看附錄。
?
獲取單詞位置
代碼實現(xiàn):
<span style="color:#333333"><span style="background-color:#f5f5f5">var?tk?=?segmenter.Tokenize(text);
//var?tk1?=?segmenter.Tokenize(text,TokenizerMode.Search);//搜索模式
foreach(var?t?in?tk)Console.WriteLine("word{0,-12}?start:{1,-3}?end:{2,-3}",?t.Word,?t.StartIndex,?t.EndIndex);</span></span>
運行結(jié)果:
?
參考文獻
[1]CSDN博客:山鷹的天空. jieba.NET是jieba中文分詞的.NET版本(C#實現(xiàn))。.
https://blog.csdn.net/lansetiankong12/article/details/53485816. 2016-12-06
[2]博客園:Ander Cui. jieba中文分詞的.NET版本:jieba.NET.
https://www.cnblogs.com/anderslly/p/jiebanet.html .2015-09-08
?
附錄
計算所漢語詞性標(biāo)記集
Version 3.0
制訂人:劉群?張華平?張浩
計算所漢語詞性標(biāo)記集
0.????說明
1.????名詞??(1個一類,7個二類,5個三類)
2.????時間詞(1個一類,1個二類)
3.????處所詞(1個一類)
4.????方位詞(1個一類)
5.????動詞(1個一類,9個二類)
6.????形容詞(1個一類,4個二類)
7.????區(qū)別詞(1個一類,2個二類)
8.????狀態(tài)詞(1個一類)
9.????代詞(1個一類,4個二類,6個三類)
10.??????????數(shù)詞(1個一類,1個二類)
11.??????????量詞(1個一類,2個二類)
12.??????????副詞(1個一類)
13.??????????介詞(1個一類,2個二類)
14.??????????連詞(1個一類,1個二類)
15.??????????助詞(1個一類,15個二類)
16.??????????嘆詞(1個一類)
17.??????????語氣詞(1個一類)
18.??????????擬聲詞(1個一類)
19.??????????前綴(1個一類)
20.??????????后綴(1個一類)
21.??????????字符串(1個一類,2個二類)
22.??????????標(biāo)點符號(1個一類,16個二類)
?
0.??????????說明
計算所漢語詞性標(biāo)記集(共計99個,22個一類,66個二類,11個三類)主要用于中國科學(xué)院計算技術(shù)研究所研制的漢語詞法分析器、句法分析器和漢英機器翻譯系統(tǒng)。
1.??????????名詞??(1個一類,7個二類,5個三類)
名詞分為以下子類:
n?名詞
nr?人名
nr1?漢語姓氏
nr2?漢語名字
nrj?日語人名
nrf?音譯人名
ns?地名
nsf?音譯地名
nt?機構(gòu)團體名
nz?其它專名
nl?名詞性慣用語
ng?名詞性語素
2.??????????時間詞(1個一類,1個二類)
t?時間詞
tg?時間詞性語素
3.??????????處所詞(1個一類)
s?處所詞
4.??????????方位詞(1個一類)
f?方位詞
5.??????????動詞(1個一類,9個二類)
v?動詞
vd?副動詞
vn?名動詞
vshi?動詞“是”
vyou?動詞“有”
vf?趨向動詞
vx?形式動詞
vi?不及物動詞(內(nèi)動詞)
vl?動詞性慣用語
vg?動詞性語素
6.??????????形容詞(1個一類,4個二類)
a?形容詞
ad?副形詞
an?名形詞
ag?形容詞性語素
al?形容詞性慣用語
7.??????????區(qū)別詞(1個一類,2個二類)
b?區(qū)別詞
?
bl?區(qū)別詞性慣用語
8.??????????狀態(tài)詞(1個一類)
z?狀態(tài)詞
9.??????????代詞(1個一類,4個二類,6個三類)
r?代詞
rr?人稱代詞
rz?指示代詞
rzt?時間指示代詞
rzs?處所指示代詞
rzv?謂詞性指示代詞
ry?疑問代詞
ryt?時間疑問代詞
rys?處所疑問代詞
ryv?謂詞性疑問代詞
rg?代詞性語素
10.?????數(shù)詞(1個一類,1個二類)
m?數(shù)詞
mq?數(shù)量詞
11.?????量詞(1個一類,2個二類)
q?量詞
qv?動量詞
qt?時量詞
12.?????副詞(1個一類)
d?副詞
13.?????介詞(1個一類,2個二類)
p?介詞
pba?介詞“把”
pbei?介詞“被”
14.?????連詞(1個一類,1個二類)
c?連詞
????cc?并列連詞
15.?????助詞(1個一類,15個二類)
u?助詞
uzhe?著
ule?了?嘍
uguo?過
ude1?的?底
ude2?地
ude3?得
usuo?所
udeng?等?等等?云云
uyy?一樣?一般?似的?般
udh?的話
uls?來講?來說?而言?說來
?
uzhi?之
ulian?連?(“連小學(xué)生都會”)
?
16.?????嘆詞(1個一類)
e?嘆詞
17.?????語氣詞(1個一類)
y?語氣詞(delete?yg)
18.?????擬聲詞(1個一類)
o?擬聲詞
19.?????前綴(1個一類)
h?前綴
20.?????后綴(1個一類)
k?后綴
21.?????字符串(1個一類,2個二類)
x?字符串
????xe??Email字符串
xs?微博會話分隔符
xm?表情符合
xu?網(wǎng)址URL
?
?
22.?????標(biāo)點符號(1個一類,16個二類)
w?標(biāo)點符號
wkz?左括號,全角:(?〔??[??{??《?【??〖?〈???半角:( [ { <
wky?右括號,全角:)?〕??]?}?》??】?〗?〉?半角:?) ] { >
wyz?左引號,全角:“?‘?『?
wyy?右引號,全角:”?’?』
wj?句號,全角:。
ww?問號,全角:??半角:?
wt?嘆號,全角:!?半角:!
wd?逗號,全角:,?半角:,
wf?分號,全角:;?半角:?;
wn?頓號,全角:、
wm?冒號,全角::?半角:?:
ws?省略號,全角:……??…
wp?破折號,全角:――???--???――-???半角:---??----
wb?百分號千分號,全角:%?‰???半角:%
wh?單位符號,全角:¥?$?£??°??℃??半角:$
?
總結(jié)
- 上一篇: 免流所需软件和节点...
- 下一篇: Altium Designer简明教程2