日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

java人名识别_HanLP中人名识别分析(示例代码)

發布時間:2025/4/16 编程问答 19 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java人名识别_HanLP中人名识别分析(示例代码) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

HanLP中人名識別分析

在看源碼之前,先看幾遍論文《基于角色標注的中國人名自動識別研究》

關于命名識別的一些問題,可參考下列一些issue:

HanLP參考博客:

分詞

分詞:給定一個字的序列,找出最可能的標簽序列(斷句符號:[詞尾]或[非詞尾]構成的序列)。結巴分詞目前就是利用BMES標簽來分詞的,B(開頭),M(中間),E(結尾),S(獨立成詞)

分詞也是采用了維特比算法的動態規劃性質求解的,具體可參考:文本挖掘的分詞原理

角色觀察

以“唱首張學友的歌情已逝”為例,

先將起始頂點 始##始,角色標注為:NR.A 和 NR.K,頻次默認為1

iterator.next();

tagList.add(new EnumItem(NR.A, NR.K)); // 始##始 A K

對于第一個詞“唱首”,它不存在于 nr.txt中,EnumItem nrEnumItem = PersonDictionary.dictionary.get(vertex.realWord);返回null,于是根據它本身的詞性猜一個角色標注:

switch (vertex.guessNature()){

case nr:

case nnt:

default:{

nrEnumItem = new EnumItem(NR.A, PersonDictionary.transformMatrixDictionary.getTotalFrequency(NR.A));

}

}

由于"唱首"的Attribute為 nz 16,不是nr 和 nnt,故默認給它指定一個角色NR.A,頻率為nr.tr.txt中 NR.A 角色的總頻率。

此時,角色列表如下:

接下來是頂點“張”,由于“張”在nr.txt中,因此PersonDictionary.dictionary.get(vertex.realWord)返回EnumItem對象,直接將它加入到角色列表中:

EnumItem nrEnumItem = PersonDictionary.dictionary.get(vertex.realWord);

tagList.add(nrEnumItem);

加入“張”之后的角色列表如下:

“唱首張學友的歌情已逝” 整句的角色列表如下:

至此,角色觀察 部分 就完成了。

總結一下,對句子進行角色觀察,首先是通過分詞算法將句子分成若干個詞,然后對每個詞查詢人名詞典(PersonDictionary)。

若這個詞在人名詞典中(nr.txt),則記錄該詞的角色,所有的角色在com.hankcs.hanlp.corpus.tag.NR.java中定義。

若這個詞不在人名詞典中,則根據該詞的Attribute “猜一個角色”。在猜的過程中,有些詞在核心詞典中可能已經標注為nr或者nnt了,這時會做分裂處理。其他情況下則是將這個詞標上NR.A角色,頻率為 NR.A 在轉移矩陣中的總詞頻。

維特比算法(動態規劃)求解最優路徑

在上圖中,給每個詞都打上了角色標記,可以看出,一個詞可以有多個標記。而我們需要將這些詞選擇一條路徑最短的角色路徑。

List nrList = viterbiComputeSimply(roleTagList);

//some code....

return Viterbi.computeEnumSimply(roleTagList, PersonDictionary.transformMatrixDictionary);

而這個過程,其實就是:維特比算法解碼隱藏狀態序列。在這里,五元組是:

隱藏狀態集合 com.hankcs.hanlp.corpus.tag.NR.java 定義的各個人名標簽

觀察狀態集合 已經分好詞的各個tagList中元素(相當于分詞結果)

轉移概率矩陣 由 nr.tr.txt 文件生成得到。具體可參考:

發射概率 某個人名標簽(隱藏狀態)出現的次數 除以 所有標簽出現的總次數

Math.log((item.getFrequency(cur) + 1e-8) / transformMatrixDictionary.getTotalFrequency(cur)

初始狀態(始##始) 和 結束狀態(末##末)

維特比解碼隱藏狀態的動態規劃求解核心代碼如下:

for (E cur : item.labelMap.keySet())

{

double now = transformMatrixDictionary.transititon_probability[pre.ordinal()][cur.ordinal()] - Math.log((item.getFrequency(cur) + 1e-8) / transformMatrixDictionary.getTotalFrequency(cur));

if (perfect_cost > now)

{

perfect_cost = now;

perfect_tag = cur;

}

}

transformMatrixDictionary.transititon_probability[pre.ordinal()][cur.ordinal()] 是前一個隱藏狀態 pre.ordinal()轉換到當前隱藏狀態cur.ordinal()的轉移概率。Math.log((item.getFrequency(cur) + 1e-8) / transformMatrixDictionary.getTotalFrequency(cur)是當前隱藏狀態的發射概率。二者“相減”得到一個概率 保存在double now變量中,然后通過 for 循環找出 當前觀察狀態 對應的 最可能的(perfect_cost最小) 隱藏狀態 perfect_tag。

至于為什么是上面那個公式來計算轉移概率和發射概率,可參考論文:《基于角色標注的中國人名自動識別研究》

在上面例子中,得到的最優隱藏狀態序列(最優路徑)K->A->K->Z->L->E->A->A 如下:

nrList = {[email?protected]} size = 8

"K" 始##始

"A" 唱首

"K" 張

"Z" 學友

"L" 的

"E" 歌

"A" 情已逝

"A" 末##末

例如:

?隱藏狀態---觀察狀態

"K"----------始##始

最大匹配

有了最優隱藏序列:KAKZLEAA,接下來就是:后續的“最大匹配處理”了。

PersonDictionary.parsePattern(nrList, pWordSegResult, wordNetOptimum, wordNetAll);

在最大匹配之前,會進行“模式拆分”。在com.hankcs.hanlp.corpus.tag.NR.java 定義了隱藏狀態的具體含義。比如說,若最優隱藏序列中 存在 ‘U‘ 或者 ‘V‘,

U Ppf 人名的上文和姓成詞 這里【有關】天培的壯烈

V Pnw 三字人名的末字和下文成詞 龔學平等領導, 鄧穎【超生】前

則會做“拆分處理”

switch(nr)

{

case U:

//do something

case V:

//do something

}

拆分完成之后,重新得到一個新的隱藏序列(模式)

String pattern = sbPattern.toString();

接下來,就用AC自動機進行最大模式匹配了,并將匹配的結果存儲到“最優詞網”中。當然,在這里就可以自定義一些針對特定應用的 識別處理規則

trie.parseText(pattern, new AhoCorasickDoubleArrayTrie.IHit(){

//.....

wordNetOptimum.insert(offset, new Vertex(Predefine.TAG_PEOPLE, name, ATTRIBUTE, WORD_ID), wordNetAll);

}

將識別出來的人名保存到最優詞網后,再基于最優詞網調用一次維特比分詞算法,得到最終的分詞結果---細分結果。

if (wordNetOptimum.size() != preSize)

{

vertexList = viterbi(wordNetOptimum);

if (HanLP.Config.DEBUG)

{

System.out.printf("細分詞網:\n%s\n", wordNetOptimum);

}

}

總結

源碼上的人名識別基本上是按照論文中的內容來實現的。對于一個給定的句子,先進行下面三大步驟處理:

角色觀察

維特比算法解碼求解隱藏狀態(求解各個分詞 的 角色標記)

對角色標記進行最大匹配(可做一些后處理操作)

最后,再使用維特比算法進行一次分詞,得到細分結果,即為最后的識別結果。

這篇文章里面沒有寫維特比分詞算法的詳細過程,以及轉移矩陣的生成過程,以后有時間再補上。看源碼,對隱馬模型的理解又加深了一點,感受到了理論的東西如何用代碼一步步來實現。由于我也是初學,對源碼的理解不夠深入或者存在一些偏差,歡迎批評指正。

總結

以上是生活随笔為你收集整理的java人名识别_HanLP中人名识别分析(示例代码)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。