一、簡介
IKAnalyzer是一個開源的,基于java語言開發(fā)的輕量級的中文分詞工具包。以開源項目Luence為應(yīng)用主體的,結(jié)合詞典分詞和文法分析算法的中文分詞組件。獨立于Lucene項目,同時提供了對Lucene的默認(rèn)優(yōu)化實現(xiàn)。
二、準(zhǔn)備
項目結(jié)構(gòu):
IKAnalyzer2012FF_u1.jar 下載
lucene-core-4.6.1.jar 下載
ext.dic
stopword.dic
IKAnalyzer.cfg.xml
三、分詞
分詞由于比較簡單,就直接粘貼代碼了
public static Vector<String> participle( String str ) {
Vector<String> str1 = new Vector<String>() ;//對輸入進(jìn)行分詞
try {
StringReader reader = new StringReader( str );
IKSegmenter ik = new IKSegmenter(reader,true);//當(dāng)為true時,分詞器進(jìn)行最大詞長切分
Lexeme lexeme = null ;
while( ( lexeme = ik.next() ) != null ) {
str1.add( lexeme.getLexemeText() );
}
if( str1.size() == 0 ) {
return null ;
}
//分詞后
System.out.println( "str分詞后:" + str1 );
} catch ( IOException e1 ) {
System.out.println();
}
return str1;
}
四、計算相似度
計算句子相似度,①常用方法有基于語義和詞序相似度計算方法,②基于關(guān)系向量模型
基于語義和詞序的句子相似度計算方法簡介
定義1:給定一個句子Ti,經(jīng)過漢語分詞系統(tǒng)分詞后,得到的所有詞W1構(gòu)成的向量稱為句子Ti的向量表示,表示為Ti = {w1,w2,.....wn}。
例子1:T1:這個中文分詞可不可以,用著方不方便。分詞后:T1=[這個, 中文分詞, 可不可以, 用著, 方, 不, 方便]。向量表示T1={這個, 中文分詞, 可不可以, 用著, 方, 不, 方便}
T2:這個中文分詞比較方便,用著方便還可以。分詞后:T2=[這個, 中文分詞, 比較方便, 用著, 方便, 還可以]。向量表示T2={這個, 中文分詞, 比較方便, 用著, 方便, 還可以}
定義2:給定一個句子Ti的向量表示,Ti中詞的個數(shù)稱為Ti的向量長度,表示為Len(Ti).
例子2:對于句子T1和T2的向量長度表示為:Len(T1)=7,Len(T1)=6。
定義3:給定兩個句子Ti、Tj的向量表示,將Ti、Tj中的所有詞Wi進(jìn)行合并,并且對于重復(fù)初想的詞只保留一個,由此得到兩個向量之和,稱為Ti、Tj的并集,表示T=T1 U T2={這個, 中文分詞, 可不可以, 比較方便,用著, 方, 不, 方便,還可以},很顯然,并集長度Len(T)<=Len(T1)+Len(T2)。
定義4:給定一個句子Ti的向量表示Ti = {w1,w2,.....wn}和一個詞wi,依次計算wi和Ti中每一個詞的相似度(值為0到1之間),所以所有結(jié)果中的最大值稱為wi在Ti中的語義分?jǐn)?shù),表示為Ci。
定義5:給定兩個句子Ti、Tj的向量表示,Ti和Tj的集合T={w1、w2,....wn},對T中的每一個詞Wi,計算Wi在Ti中的語義分?jǐn)?shù)Ci,T中每個分詞的語義分?jǐn)?shù)組成的一個向量稱為Ti基于T的語義向量,表示為Si={C1,C2,...,Cn}。
在該算法中,基于T分別計算Ti和Tj的語義向量Si、Sj,以計算Si作為說明,過程如下:
1、對于T中的每一個詞wi,如果wi 在Ti 中出現(xiàn),則在語義向量Si中將wi 的語義分?jǐn)?shù)Ci設(shè)為1。
2、如果Ti中不包含wi,則計算wi 在 Ti 中的語義分?jǐn)?shù) Ci=a(a為預(yù)先設(shè)定的閾值 , 無閾值設(shè)為0 ,本文中閾值為0.2 ) 。
根據(jù)語義向量計算語義相似度方法如下圖:
詞序相似度計算法方法如下:
其中r1、r2 分別為T1、T2的詞序向量,以T1為例,其計算方法如下:
1、對于T中的每一個詞wi,如果T1中包含該次,則r1中該次的取值為該詞在T1中出現(xiàn)的詞序。否則在T1中找出與wi最相似的詞Wi。
2、如果wi 和 wi 的相似度大于一個給定的閾值(實驗取值為0.4),wi在r1中的取值設(shè)為wi在Ti中出現(xiàn)的詞序。
3、如果兩種情況均為發(fā)生,則wi在r1中的取值設(shè)為null。
然而,根據(jù)語義向量計算語義相似度方法中,想到了之前看過的一篇博客,通過 余玄定理來實現(xiàn),計算方法如下
//閾值
public static double YUZHI = 0.2 ;
/**
* 返回百分比
* @author: Administrator
* @Date: 2015年1月22日
* @param T1
* @param T2
* @return
*/
public static double getSimilarity(Vector<String> T1, Vector<String> T2) throws Exception {
int size = 0 , size2 = 0 ;
if ( T1 != null && ( size = T1.size() ) > 0 && T2 != null && ( size2 = T2.size() ) > 0 ) {
Map<String, double[]> T = new HashMap<String, double[]>();
//T1和T2的并集T
String index = null ;
for ( int i = 0 ; i < size ; i++ ) {
index = T1.get(i) ;
if( index != null){
double[] c = T.get(index);
c = new double[2];
c[0] = 1; //T1的語義分?jǐn)?shù)Ci
c[1] = YUZHI;//T2的語義分?jǐn)?shù)Ci
T.put( index, c );
}
}
for ( int i = 0; i < size2 ; i++ ) {
index = T2.get(i) ;
if( index != null ){
double[] c = T.get( index );
if( c != null && c.length == 2 ){
c[1] = 1; //T2中也存在,T2的語義分?jǐn)?shù)=1
}else {
c = new double[2];
c[0] = YUZHI; //T1的語義分?jǐn)?shù)Ci
c[1] = 1; //T2的語義分?jǐn)?shù)Ci
T.put( index , c );
}
}
}
//開始計算,百分比
Iterator<String> it = T.keySet().iterator();
double s1 = 0 , s2 = 0, Ssum = 0; //S1、S2
while( it.hasNext() ){
double[] c = T.get( it.next() );
Ssum += c[0]*c[1];
s1 += c[0]*c[0];
s2 += c[1]*c[1];
}
//百分比
return Ssum / Math.sqrt( s1*s2 );
} else {
throw new Exception("傳入?yún)?shù)有問題!");
}
}
測試結(jié)果:
str分詞后:[這個, 中文分詞, 可不可以, 用著, 方, 不, 方便]
str分詞后:[這個, 中文分詞, 比較方便, 用著, 方便, 還可以]
相似度:0.7595872466989299 代碼地址: twosnail源碼地址 原創(chuàng)作者: twosnail(兩只蝸牛) 轉(zhuǎn)載地址:http:///detail/52615-ikanalyzer-%E4%B8%AD%E6%96%87%E5%88%86%E8%AF%8D-%E8%AE%A1%E7%AE%97
|