介紹一種基於角色標註+字詞體位法的人名識別方式-Ansj中文分詞

大家好.最近在做分詞.在分詞中遇到了各種各樣的問題.在這裏選擇一個比較有意思的與大家分享.
在這裏說分詞有點老生常談了.的確.中文分詞已經非常成熟了.但是在實體名識別上一直是中文分詞的軟肋.最近通過對ictclas的學習,和自己的總結.得出了一個還算不錯的人名識別系統.

目前這種方式已經開源.大家可以參看:[url]https://github.com/ansjsun/ansj_seg[/url] , 在線測試:[url]http://www.ansj.org/demo/seg.jsp[/url]


主要思路是..先粗分,粗分的辦法很多.但是在粗分的時候要儘量減少歧異.
比如

祝海林在孫健的右面!
進過第一步粗分的結果應當爲
祝/ 海/ 林/ 在/ 孫/ 健/ 的/ 右面/

在得到以上的粗分序列我們就可以進行進一步分析了
首先我們得準備一些語料庫.對其進行訓練.
比如語料庫裏面有如下詞

孫強
朱海林
孫海林
祝健
....

因爲一般這種語料庫在幾十萬級別.不能一一例舉.所以我們拿具有針對這段文本的是個詞做分析
利用字體位方式,我們得到如下統計結果

孫 2:1:1 \\戴錶 孫 這個字在 2個詞中的第1個位置出現了1次
孫 3:1:1
強 2:2:1
朱 3:1:1
海 3:2:2
,,,


得到如上頻率後.我們就可以進行人名識別了

下面我儘量用僞代碼的方式來進行一次分解

public void recogntion(Term[] terms) {

for (int i = 0; i < terms.length; i++) {
//已名識別從前向後進行識別,4個字,3個字2字人名分別識別
for (int j = 4; j > 1; j--) {
freq = term.getTermNatures().personAttr.getFreq(j, 0);\\取得詞位頻率
if ((freq > 0) ) {//進行初始化校驗.當此字在識別位置出現時
tempTerm = nameFind(i, beginFreq, j);//以序列結構進行人名識別
}
}
}
}

public Term nameFnd(int i , int beginFreq , j){

StringBuilder sb = new StringBuilder();
int undefinite = 0;
skip = false;
PersonNatureAttr pna = null;
int index = 0;
int freq = 0;
double allFreq = 0;
Term term = null;
int i = offe;
for (; i < terms.length; i++) {
// 走到結尾處識別出來一個名字.
term = terms[i] ;
pna = term.getTermNatures().personAttr;
// 在這個長度的這個位置的詞頻,如果沒有可能就幹掉,跳出循環
if ((freq = pna.getFreq(size, index)) == 0) {
return null;
}

//增加人名
sb.append(term.getName());
//這個人名的概率計算
allFreq += Math.log(term.getTermNatures().allFreq+1) ;
allFreq += -Math.log((double) (freq));
index++;


if (index == size + 2) {//當達到制定長度後跳出循環
break;
}
}

double score = -Math.log(factory[size]);
score += allFreq ;
double endFreq = 0;
// 開始尋找結尾詞,
endFreq = terms[i].getTermNatures().personAttr.end + 1;

//根據上下文.概率進行公司計算
score -= Math.log(endFreq);
score -= Math.log(beginFreq);



term = new Term(sb.toString(), offe, TermNatures.NR);
term.selfScore = score;

//識別出來的人名進行返回
return term;
}

進行如上步驟之後.我麼得到了一個二維數組的序列:
如下:

-------->祝
祝海林--->海林

孫建

右面

下一個步驟就是比較 祝海林 和 祝+海林 哪個更像人名的過程了
其實在這裏我們已經構成了隱馬爾科夫鏈.通過貝葉斯定理公式:P(A|B)=P(B|A)*P(A)/P(B)
加上頻率完全可以正確識別出來我們要找的實體名.
好了大概介紹到這裏.有興趣的朋友可以通過:[url]http://www.ansj.org/[/url] 獲取代碼.也希望能在這裏認識一些志同道合的朋友共同勉勵交流
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章