1. 程式人生 > >Lucene實現中文分詞

Lucene實現中文分詞

在之前的文章中已經介紹過Lucene了,這裡就不多做介紹。

一、中文分詞的原理

中文分詞是將一個漢字序列切分為一個一個單獨的詞。分詞就是講連續的字序列安裝一定的規範重新組合成詞序列的過程。隨著機器學習的發展,很多分詞的方法都已經被科研人員實現,也越來越精確。分詞的精確性一定程度上影響了搜尋引擎的查全率與查準率,當然這是在你的中文分詞運用在搜尋引擎的前提之下。

分詞的演算法可以分為:基於字串匹配的分詞方法、基於統計的分詞方法,很容易理解基於字串匹配的分詞方法有很大的侷限性,很難做到準確的分詞,因為世界上沒有一本最完備的詞典,很多專業詞彙、人名巴拉巴拉之類很難涉及到。因此顯而易見,基於統計的分詞方法要更精確同時更復雜。

基於字串匹配的分詞方法又有:正向最大匹配、逆向最大匹配、最少切分等等方法

基於統計的分詞方法很大程度上是根據上下文中,相鄰的字同時出現的次數,字與字相鄰共現的頻率之類資訊來實現更精確的分詞,需要用到統計語言模型,設計很多數學原理,這裡就不做更多介紹了,網上有很多資料。

二、關於停用詞

停用詞是自然語言中關鍵的組成,對於語義的構成有重要的意義,但是很多時候我們在做搜尋是隻需要內容的關鍵詞而不是全部詞,所以去除停用詞是很必要的操作。例如漢語中的:“的”“是”等。

網上有一些漢語中常用停用詞的整理,我使用的是GitHub上的一個停用詞表

三、程式碼實現

環境是Lucene4.6

import [圖片]java.io.BufferedReader;
import [圖片]java.io.File;
import [圖片]java.io.FileInputStream;
import [圖片]java.io.IOException;
import [圖片]java.io.InputStreamReader;
import [圖片]java.io.StringReader;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.TokenStream;
import [圖片]org.apache.lucene.analysis.cn.smart.SmartChineseAnalyzer;
import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
//import org.apache.lucene.analysis.tokenattributes.OffsetAttribute;
import org.apache.lucene.analysis.util.CharArraySet;
import org.apache.lucene.util.Version;

public class SegWordTest {
	//建立一個去除停用詞的分析器物件
	public static CharArraySet stopwords = new CharArraySet(Version.LUCENE_46, 3, false);
	public static Analyzer noStopAnalyzer;
	public static void initializeData() throws IOException{
		//讀取停用詞表格
		File filename = new File("someFiles/stopwords.txt");
		InputStreamReader reader = new InputStreamReader(new FileInputStream(filename));
		BufferedReader br = new BufferedReader(reader);
		String line = "";
		line = br.readLine();
		while(line != null){
			stopwords.add(line);
			line = br.readLine();
		}
		br.close();
		noStopAnalyzer = new SmartChineseAnalyzer(Version.LUCENE_46, stopwords);
	}
	public static void testAnanlyzer(String cont) throws IOException{
		/*
		//不去除停用詞的版本
		//建立一箇中文分詞的分析器物件
		Analyzer analyzer = new SmartChineseAnalyzer(Version.LUCENE_46);
		//從分析器物件中獲得tokenStream物件
		TokenStream tokenStream = analyzer.tokenStream("myfield", new StringReader(cont));
		*/
		TokenStream tokenStream = noStopAnalyzer.tokenStream("myfield", new StringReader(cont));
		//設定一個引用,這個引用可以使多種型別,可以是關鍵詞的引用,偏移量的引用等等
		//關鍵詞的引用
		CharTermAttribute charTermAttribute = tokenStream.addAttribute(CharTermAttribute.class);
		//偏移量的引用,可以得到詞彙開始和結束的位置
		//OffsetAttribute offsetAttribute = tokenStream.addAttribute(OffsetAttribute.class);
		tokenStream.reset();	//很關鍵,不然會報錯
		while(tokenStream.incrementToken()){
			System.out.println(charTermAttribute);
		}
		tokenStream.close();
	}
	public static void main(String args[]) throws IOException{
		initializeData();
		String con = "這是一架高空高速飛行的飛機";
		testAnanlyzer(con);
	}
}