一、分詞的方法
分詞的方法主要有以下幾種:
1、單字切分
單字切分就是把一段文字按照每個字去建立索引。
如果用來切分“我愛你偉大的中國”,就會切成“我”,“愛”,“你”,“偉”,“大”,“的”,“中”,“國”。這種分詞效率低,但也能解決一些問題,聊勝於無。
2、二分法
二分法就是把一段文字的每兩個相鄰的字算作一個詞。同樣對於上面的句子就會切成“我愛”,“愛你”,“你偉”,“偉大”,“大的”,“的中”,“中國”7個詞。
3、詞典法
詞典法就是建立一個詞典文件,然后使用詞典和文字段落進行匹配,從而得出分詞結果。在這種分詞方法中,詞典和匹配算法是關鍵。
做詞典很容易,維護詞典也不能,統計而已。
匹配算法不好辦,有最大匹配和最小匹配,正向匹配和逆向匹配。二二得四,就成了“最大正向匹配”,“最大逆向匹配”,“最小正向匹配”和“最小逆向匹配”。
這四種分次發哪種最好沒有定論,要根據具體文本段落而定。
4、語義法
這個方法在理論上是存在的,但從實際上講也只是個名詞。看到任何一段文字,讓計算機將其正確理解出來,這個想法幾乎不可能。即使是人也很難全部理解。
二、盤古分詞
在.Net環境中,分詞比較常用的是盤古分詞,項目地址是:http://pangusegment.codeplex.com/
盤古分詞詞庫下載地址是:http://pangusegment.codeplex.com/releases/view/47411
下載解壓后如下:
- Demo.exe是分詞的示例程序,用於測試分詞效果。
- DictManage.exe用於詞庫管理。
分詞測試效果就不說了,下面用一張圖片來說明,如何對詞庫進行管理。
1、盤古分詞初始設置說明
1、配置選項
盤古分詞在初始化的時候,需要首先配置一些參數,這些參數可以通過MatchOptions類由代碼設定,然后通過一些支持該類對象的構造方法來動態設置。
ICollection<WordInfo> words= segment.DoSegment(text); ICollection<WordInfo> words= segment.DoSegment(text, options); ICollection<WordInfo> words= segment.DoSegment(text, options, parameters);
- text 為需要分詞的文本
- options 為自定義分詞選項,默認為 pangu.xml 中指定的分詞選項
- parameters 為分詞參數,默認為 pangu.xml 中指定的分詞參數
配置項列表如下:
MatchOptions屬性 | 說明 |
ChineseNameIdentify | 是否開啟中文人名識別 |
FrequencyFirst | 詞頻優先 |
MultiDimensionality | 是否開啟多元分詞 |
EnglishMultiDimensionality | 英文多元分詞,這個開關,會將英文中的字母和數字分開 |
FilterStopWords | 是否過濾停用詞 |
IgnoreSpace | 是否忽略空格、回車、Tab |
ForceSingleWord | 是否強制一元分詞 |
TraditionalChineseEnabled | 是否開啟繁體中文分詞 |
OutputSimplifiedTraditional | 是否同時輸出簡體和繁體 |
UnknownWordIdentify | 是否開啟未登錄詞別 |
FilterEnglish | 是否過濾英文,這個選項只有在過濾停用詞選項生效時才有效 |
FilterNumeric | 是否過濾數字,這個選項只有在過濾停用詞選項生效時才有效 |
IgnoreCapital | 是否忽略英文大小寫 |
EnglishSegment | 英文分詞 |
SynonymOutput | 同義詞輸出功能一般用於對搜索字符串的分詞,不建議在索引時使用 |
WildcardOutput | 同義詞輸出功能一般用於對搜索字符串的分詞,不建議在索引時使用 |
WildcardSegment | 對通配符匹配的結果分詞 |
CustomRule | 是否進行用戶自定義規則匹配 |
2、配置參數
配置參數通過MatchParameter類設定,在xml里設定也可以:
MatchParameter屬性 | 說明 |
Redundancy | 多元分詞冗余度 |
UnknowRank | 未登錄詞權值 |
BestRank | 最匹配詞權值 |
SecRank | 次匹配詞權值 |
ThirdRank | 再次匹配詞權值 |
SingleRank | 強行輸出的單字的權值 |
NumericRank | 數字的權值 |
EnglishRank | 英文詞匯權值 |
SymbolRank | 符號的權值 |
SimplifiedTraditionalRank | 強制同時輸出簡繁漢字時,非原來文本的漢字輸出權值。原來文本是簡體,這里就是輸出的繁體字的權值,反之亦然 |
SynonymRank | 同義詞權值 |
WildcardRank | 通配符匹配結果的權值 |
FilterEnglishLength | 過濾英文選項生效時,過濾大於這個長度的英文 |
FilterNumericLength | 過濾數字選項生效時,過濾大於這個長度的數字 |
CustomRuleAssemblyFileName | 用戶自定義規則的配件文件名 |
CustomRuleFullClassName | 用戶自定義規則的類的完整名,即帶名字空間的名稱 |
默認的PanGu.xml示例如下:
<?xml version="1.0" encoding="utf-8"?> <PanGuSettings xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.codeplex.com/pangusegment"> <DictionaryPath>..\Dictionaries</DictionaryPath> <MatchOptions> <ChineseNameIdentify>true</ChineseNameIdentify> <FrequencyFirst>false</FrequencyFirst> <MultiDimensionality>false</MultiDimensionality> <FilterStopWords>true</FilterStopWords> <IgnoreSpace>true</IgnoreSpace> <ForceSingleWord>false</ForceSingleWord> <TraditionalChineseEnabled>false</TraditionalChineseEnabled> <OutputSimplifiedTraditional>false</OutputSimplifiedTraditional> </MatchOptions> <Parameters> <UnknowRank>1</UnknowRank> <BestRank>5</BestRank> <SecRank>3</SecRank> <ThirdRank>2</ThirdRank> <SingleRank>1</SingleRank> <NumericRank>1</NumericRank> <EnglishRank>5</EnglishRank> <SymbolRank>1</SymbolRank> <SimplifiedTraditionalRank>1</SimplifiedTraditionalRank> <Redundancy>0</Redundancy> </Parameters> </PanGuSettings>
配置項與上面兩個類的屬性一一對應。
2、查看分詞示例
下面,先寫個小Demo看看如何分詞:
PanGu.Segment.Init(AppDomain.CurrentDomain.SetupInformation.ApplicationBase + "/PanGu.xml"); Segment segment = new Segment(); ICollection<WordInfo> words = segment.DoSegment("張飛武功很好"); foreach (WordInfo w in words) { Console.WriteLine(w.Word); }
分詞效果如下:
4、整合Lucene.net進行索引、搜索示例
下面是一個簡單的示例:
static void Main(string[] args) { PanGu.Segment.Init(AppDomain.CurrentDomain.SetupInformation.ApplicationBase + "/PanGu.xml"); //寫入數據到索引 Analyzer analyzer = new PanGuAnalyzer(); Directory directory = new RAMDirectory(); IndexWriter.MaxFieldLength maxFieldLength = new IndexWriter.MaxFieldLength(10000); using (IndexWriter writer = new IndexWriter(directory, analyzer, maxFieldLength)) { Document document1 = new Document(); document1.Add(new Field("Sentence", "張三是一個牛人", Field.Store.YES, Field.Index.ANALYZED)); writer.AddDocument(document1); } //查找 using (IndexSearcher searcher = new IndexSearcher(directory)) { PanGuTokenizer ktTokenizer = new PanGuTokenizer(); ICollection<WordInfo> words = ktTokenizer.SegmentToWordInfos("一個"); StringBuilder result = new StringBuilder(); foreach(WordInfo word in words) { if (word == null) { continue; } result.AppendFormat("{0}^{1}.0", word.Word,(int)Math.Pow(3,word.Rank)); } QueryParser queryParser = new QueryParser(Lucene.Net.Util.Version.LUCENE_30, "Sentence", new PanGuAnalyzer(true)); Query query = queryParser.Parse(result.ToString()); TopDocs docs = searcher.Search(query, null, 1000); Document doc = searcher.Doc(docs.ScoreDocs[0].Doc); Console.WriteLine(doc.Get("Sentence")); } Console.ReadKey(); }
5、盤古分詞高亮組件
直接上示例:
//創建HTMLFormatter,參數為高亮單詞的前后綴 PanGu.HighLight.SimpleHTMLFormatter simpleHTMLFormatter = new PanGu.HighLight.SimpleHTMLFormatter("<font color=\"red\">", "</font>"); //創建Highlighter ,輸入HTMLFormatter 和盤古分詞對象Semgent PanGu.HighLight.Highlighter highlighter = new PanGu.HighLight.Highlighter(simpleHTMLFormatter, new Segment()); //設置每個摘要段的字符數 highlighter.FragmentSize = 50; //獲取最匹配的摘要段 string ContentLighter = highlighter.GetBestFragment("一個", "張三是一個牛人"); Console.WriteLine(ContentLighter);
輸出如下: