溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

如何進行HanLP中人名識別分析

發(fā)布時間:2021-11-30 16:27:53 來源:億速云 閱讀:221 作者:柒染 欄目:數(shù)據(jù)庫

如何進行HanLP中人名識別分析,針對這個問題,這篇文章詳細介紹了相對應(yīng)的分析和解答,希望可以幫助更多想解決這個問題的小伙伴找到更簡單易行的方法。

分詞

在 HMM與分詞、詞性標注、命名實體識別 中說:

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

分詞也是采用了維特比算法的動態(tài)規(guī)劃性質(zhì)求解的,具體可參考: 文本挖掘的分詞原理

角色觀察

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

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

iterator.next();
tagList.add(new EnumItem<NR>(NR.A, NR.K)); //  始##始 A K

如何進行HanLP中人名識別分析

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

switch (vertex.guessNature()){        case nr:        case nnt:    default:{
        nrEnumItem = new EnumItem<NR>(NR.A, PersonDictionary.transformMatrixDictionary.getTotalFrequency(NR.A));
    }
}

如何進行HanLP中人名識別分析

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

此時,角色列表如下:

如何進行HanLP中人名識別分析

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

如何進行HanLP中人名識別分析

EnumItem<NR> nrEnumItem = PersonDictionary.dictionary.get(vertex.realWord);
tagList.add(nrEnumItem);

加入“張”之后的角色列表如下:
如何進行HanLP中人名識別分析

“唱首張學友的歌情已逝” 整句的角色列表如下:
如何進行HanLP中人名識別分析

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

總結(jié)一下,對句子進行角色觀察,首先是通過分詞算法將句子分成若干個詞,然后對每個詞查詢?nèi)嗣~典(PersonDictionary)。

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

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

維特比算法(動態(tài)規(guī)劃)求解最優(yōu)路徑

在上圖中,給每個詞都打上了角色標記,可以看出,一個詞可以有多個標記。而我們需要將這些詞選擇一條路徑最短的角色路徑。參考 隱馬爾可夫模型維特比算法詳解

List<NR> nrList = viterbiComputeSimply(roleTagList);//some code....return Viterbi.computeEnumSimply(roleTagList, PersonDictionary.transformMatrixDictionary);

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

  • 隱藏狀態(tài)集合 com.hankcs.hanlp.corpus.tag.NR.java 定義的各個人名標簽

  • 觀察狀態(tài)集合 已經(jīng)分好詞的各個tagList中元素(相當于分詞結(jié)果)

如何進行HanLP中人名識別分析

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

  • 發(fā)射概率 某個人名標簽(隱藏狀態(tài))出現(xiàn)的次數(shù) 除以 所有標簽出現(xiàn)的總次數(shù)

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

  • 初始狀態(tài)(始##始) 和 結(jié)束狀態(tài)(末##末)

如何進行HanLP中人名識別分析

維特比解碼隱藏狀態(tài)的動態(tài)規(guī)劃求解核心代碼如下:

            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()] 是前一個隱藏狀態(tài) pre.ordinal()轉(zhuǎn)換到當前隱藏狀態(tài)cur.ordinal()的轉(zhuǎn)移概率。Math.log((item.getFrequency(cur) + 1e-8) / transformMatrixDictionary.getTotalFrequency(cur)是當前隱藏狀態(tài)的發(fā)射概率。二者“相減”得到一個概率 保存在double now變量中,然后通過 for 循環(huán)找出 當前觀察狀態(tài) 對應(yīng)的 最可能的(perfect_cost最小) 隱藏狀態(tài) perfect_tag。

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

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

nrList = {LinkedList@1065} size = 8
"K" 始##始
"A" 唱首
"K" 張
"Z" 學友
"L" 的
"E" 歌
"A" 情已逝
"A" 末##末
例如:
隱藏狀態(tài)---觀察狀態(tài)
"K"----------始##始

最大匹配

有了最優(yōu)隱藏序列:KAKZLEAA,接下來就是:后續(xù)的“最大匹配處理”了。

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

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

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

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

則會做“拆分處理”

switch(nr)
{    case U:        //拆分成K B
    case V:        //視情況拆分}

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

String pattern = sbPattern.toString();

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

trie.parseText(pattern, new AhoCorasickDoubleArrayTrie.IHit<NRPattern>(){    //.....
    wordNetOptimum.insert(offset, new Vertex(Predefine.TAG_PEOPLE, name, ATTRIBUTE, WORD_ID), wordNetAll);
}

將識別出來的人名保存到最優(yōu)詞網(wǎng)后,再基于最優(yōu)詞網(wǎng)調(diào)用一次維特比分詞算法,得到最終的分詞結(jié)果---細分結(jié)果。

            if (wordNetOptimum.size() != preSize)
            {
                vertexList = viterbi(wordNetOptimum);                if (HanLP.Config.DEBUG)
                {
                    System.out.printf("細分詞網(wǎng):\n%s\n", wordNetOptimum);
                }
            }

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

  • 角色觀察

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

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

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

關(guān)于如何進行HanLP中人名識別分析問題的解答就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關(guān)注億速云行業(yè)資訊頻道了解更多相關(guān)知識。

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI