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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

hmm进行英文词性标注

發(fā)布時間:2023/12/16 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 hmm进行英文词性标注 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

?

這里采用的手寫維特比算法進行詞性標(biāo)注?

我們也可以選擇第三方的庫進行計算

https://github.com/jmschrei/yahmm

?

?

?

import nltk import sys from nltk.corpus import brown """ 做這個之前 首先我們要知道 我們知道什么 要求什么 第一步 我們需要根據(jù) 給定的語料庫 進行學(xué)習(xí)hmm模型的 (A,B,π) A 是狀態(tài)轉(zhuǎn)移矩陣 在我們詞庫之中 就是tag之間轉(zhuǎn)移的概率矩陣 對整個語料進行統(tǒng)計 P(ti | t{i-1}) = count(t{i-1}, ti) / count(t{i-1}) 計算t(i-1)到 ti的轉(zhuǎn)移概率 就是ti在t(i-1)后面的個數(shù)/ T(i-1)tag的總數(shù) B是每個隱藏狀態(tài)到可見狀態(tài)的概率分布 就是在tag下出現(xiàn)這個可見狀態(tài)的概率 也就是在Tag下出現(xiàn)這個單詞的概率 這個在整個語料庫之中也可以統(tǒng)計 P(wi | ti) = count(wi, ti) / count(ti) 等于 tag1下所有的單詞 /tag的數(shù)量的單詞 π 是初始概率 就是在0時刻 statr 到每個tag的概率 這個在語料庫中也可以統(tǒng)計 等于 start-tag1的數(shù)量 / 所有start到tag的數(shù)量根據(jù)語料庫 計算出模型所有的參數(shù) (A,B,π) 就可以利用hmm的模型求解三種問題 1.根據(jù)hmm模型 用遍歷算法 求出 發(fā)生這個可見狀態(tài)鏈條概率是多少 可以求出發(fā)生這個可見狀態(tài)的可能性是多大2.第2個問題就是我們這里詞性標(biāo)注要解決的問題 給出一個模型(A,B,π) 可見狀態(tài)鏈 也就一句話 求出 隱藏狀態(tài)鏈 也就是單詞的詞性  維特比算法 動態(tài)規(guī)劃求解  也可以用第三方的庫 將參數(shù) (A,b,π)帶入求和 我們這里是自己實現(xiàn)這個算法 求和3。第三種問題這個例子中我們無關(guān)   說的是模型的參數(shù)(A.B.π)不確定  根據(jù)我們出現(xiàn)的可見狀態(tài) 不斷調(diào)整 求出發(fā)生這個可見狀態(tài)最大可能性  這個模型的參數(shù)是什么 在詞性標(biāo)注的應(yīng)用就是 給出一句話 然后給出一個隱藏狀態(tài)鏈tag 判斷一下匹配度 給出一句話  求出每個單詞的詞性 """""" 預(yù)處理詞庫 這里需要的預(yù)處理是 給詞加上開始和結(jié)束符合 brown 里面的句子都是自己標(biāo)注好了的,形式如下:(i.NOUN),(LOVE,VERB),(YOU,NOUN) 我們用 (START,START)(END.END) 的格式做開始和結(jié)束的標(biāo)注 下載語料庫    """ #nltk.download('brown')brown_tags_words=[] for sent in brown.tagged_sents():#加上開頭brown_tags_words.append(("START","START"))#省略tag 只去tag前2個字母brown_tags_words.extend([(tag[:2],word) for (word,tag) in sent])#結(jié)尾加上結(jié)束符合brown_tags_words.append(("END","END"))print(brown_tags_words[0]) #('START', 'START')""" 詞統(tǒng)計 這里計算的是 模型參數(shù)B 這個時候,我們要把我們所有的詞庫中擁有的單詞與tag之間的關(guān)系,做個簡單粗暴的統(tǒng)計。也就是我們之前說過的:P(wi | ti) = count(wi, ti) / count(ti)你可以自己一個個的loop全部的corpus,當(dāng)然,這里NLTK給了我們做統(tǒng)計的工具, (這屬于沒有什么必要的hack,裝起逼來也不X,所以,大家想自己實現(xiàn),可以去實現(xiàn),不想的話,就用這里提供的方法) """ # conditional frequency distribution cfd_tagwords = nltk.ConditionalFreqDist(brown_tags_words) # conditional probability distribution cpd_tagwords = nltk.ConditionalProbDist(cfd_tagwords, nltk.MLEProbDist) """ 好,現(xiàn)在我們看看平面統(tǒng)計下來的結(jié)果: 可以拿到每個tag到 單詞的概率 也就是可見狀態(tài)的分布概率  模型參數(shù)B 動詞duck的概率  JJ new的概率  """ print("The probability of an adjective (JJ) being 'new' is", cpd_tagwords["JJ"].prob("new")) print("The probability of a verb (VB) being 'duck' is", cpd_tagwords["VB"].prob("duck")) """ The probability of an adjective (JJ) being 'new' is 0.01472344917632025 The probability of a verb (VB) being 'duck' is 6.042713350943527e-05 """""" 計算模型參數(shù) A 隱藏狀態(tài)的轉(zhuǎn)移矩陣  這里面我們也把start 到各個tag的概率也一起計算了  也就是我們這次統(tǒng)計 計算了 2個參數(shù)  一個是A 一個是π初始概率   好,接下來,按照課上講的,還有第二個公式需要計算:P(ti | t{i-1}) = count(t{i-1}, ti) / count(t{i-1})這個公式跟words沒有什么卵關(guān)系。它是屬于隱層的馬科夫鏈。所以 我們先取出所有的tag來。 """brown_tags = [tag for (tag, word) in brown_tags_words ] # count(t{i-1} ti) # bigram的意思是 前后兩個一組,聯(lián)在一起 cfd_tags= nltk.ConditionalFreqDist(nltk.bigrams(brown_tags)) # P(ti | t{i-1}) cpd_tags = nltk.ConditionalProbDist(cfd_tags, nltk.MLEProbDist)""" 好的,可以看看效果了: """ print("If we have just seen 'DT', the probability of 'NN' is", cpd_tags["DT"].prob("NN")) print( "If we have just seen 'VB', the probability of 'JJ' is", cpd_tags["VB"].prob("DT")) print( "If we have just seen 'VB', the probability of 'NN' is", cpd_tags["VB"].prob("NN")) """ DT 轉(zhuǎn)移到NN的概率 VB到DT的概率 VB到NN的 概率  If we have just seen 'DT', the probability of 'NN' is 0.5057722522030194 If we have just seen 'VB', the probability of 'JJ' is 0.016885067592065053 If we have just seen 'VB', the probability of 'NN' is 0.10970977711020183 """""" 下面可以根據(jù)語料計算出來的Hmm 模型 進行詞性標(biāo)注求解第2類問題  可以根據(jù)維特比算法進行計算  也可以用第三方面實現(xiàn)的庫進行計算  YAhMm進行計算 我們這里采用的是自己實現(xiàn)算法 https://github.com/jmschrei/yahmm 第三方實現(xiàn)庫 """"""一些有趣的結(jié)果: 那么,比如, 一句話,"I want to race", 一套tag,"PP VB TO VB"他們之間的匹配度有多高呢?其實就是:P(START) * P(PP|START) * P(I | PP) *P(VB | PP) * P(want | VB) *P(TO | VB) * P(to | TO) *P(VB | TO) * P(race | VB) *P(END | VB) """ prob_tagsequence = cpd_tags["START"].prob("PP") * cpd_tagwords["PP"].prob("I") * \cpd_tags["PP"].prob("VB") * cpd_tagwords["VB"].prob("want") * \cpd_tags["VB"].prob("TO") * cpd_tagwords["TO"].prob("to") * \cpd_tags["TO"].prob("VB") * cpd_tagwords["VB"].prob("race") * \cpd_tags["VB"].prob("END")print( "The probability of the tag sequence 'START PP VB TO VB END' for 'I want to race' is:", prob_tagsequence) #The probability of the tag sequence 'START PP VB TO VB END' for 'I want to race' is: 1.0817766461150474e-14""" 根據(jù)hmm進行詞性標(biāo)注環(huán)節(jié) Viterbi 的實現(xiàn) 如果我們手上有一句話,怎么知道最符合的tag是哪組呢? 首先,我們拿出所有獨特的tags(也就是tags的全集) """ distinct_tags = set(brown_tags) sentence = ["I", "want", "to", "race" ] sentlen = len(sentence)""" 接下來,開始維特比:從1循環(huán)到句子的總長N,記為i每次都找出以tag X為最終節(jié)點,長度為i的tag鏈動態(tài)規(guī)劃 從第一個開始算 """ viterbi = [ ] """ 同時,還需要一個回溯器:從1循環(huán)到句子的總長N,記為i把所有tag X 前一個Tag記下來。 """ backpointer = [ ] first_viterbi = { } first_backpointer = { } for tag in distinct_tags:# don't record anything for the START tagif tag == "START": continuefirst_viterbi[ tag ] = cpd_tags["START"].prob(tag) * cpd_tagwords[tag].prob( sentence[0] )first_backpointer[ tag ] = "START"print(first_viterbi) print(first_backpointer)""" 以上,是所有的第一個viterbi 和第一個回溯點。接下來,把樓上這些,存到Vitterbi和Backpointer兩個變量里去 first_viterbi 這個變量記錄的是 每個tag下是這個單詞的概率 那么動態(tài)規(guī)劃的原理 這里可以取出 當(dāng)前概率最大的一個tag作為tag 然后存到backpoint之中 {'CS': 0.0, 'QL': 0.0, 'NP': 1.7319067623793952e-06, 'IN': 0.0, 'AP': 0.0, 'NI': 3.3324520848931064e-07, '(-': 0.0, ')-': 0.0, 'CC': 0.0, 'WD': 0.0, 'END': 0.0, 'NR': 0.0, 'CD': 0.0, '*': 0.0, '(': 0.0, 'DT': 0.0, 'RP': 0.0, 'WQ': 0.0, ':': 0.0, 'WP': 0.0, "''": 0.0, '--': 0.0, 'AT': 0.0, "'": 0.0, 'DO': 0.0, 'PN': 0.0, ',-': 0.0, 'NN': 1.0580313619573935e-06, ')': 0.0, 'AB': 0.0, 'RB': 0.0, 'HV': 0.0, '``': 0.0, '*-': 0.0, ',': 0.0, 'JJ': 0.0, 'FW': 0.0, 'PP': 0.014930900689060006, 'TO': 0.0, 'MD': 0.0, 'EX': 0.0, '.-': 0.0, '.': 0.0, 'UH': 0.0, 'RN': 0.0, 'WR': 0.0, 'VB': 0.0, ':-': 0.0, 'BE': 0.0, 'OD': 0.0} first_backpointer {'CS': 'START', 'QL': 'START', 'NP': 'START', 'IN': 'START', 'AP': 'START', 'NI': 'START', '(-': 'START', ')-': 'START', 'CC': 'START', 'WD': 'START', 'END': 'START', 'NR': 'START', 'CD': 'START', '*': 'START', '(': 'START', 'DT': 'START', 'RP': 'START', 'WQ': 'START', ':': 'START', 'WP': 'START', "''": 'START', '--': 'START', 'AT': 'START', "'": 'START', 'DO': 'START', 'PN': 'START', ',-': 'START', 'NN': 'START', ')': 'START', 'AB': 'START', 'RB': 'START', 'HV': 'START', '``': 'START', '*-': 'START', ',': 'START', 'JJ': 'START', 'FW': 'START', 'PP': 'START', 'TO': 'START', 'MD': 'START', 'EX': 'START', '.-': 'START', '.': 'START', 'UH': 'START', 'RN': 'START', 'WR': 'START', 'VB': 'START', ':-': 'START', 'BE': 'START', 'OD': 'START'} """viterbi.append(first_viterbi) backpointer.append(first_backpointer) #全部存起來 """ 我們可以先看一眼,目前最好的tag是啥: 也就是把第一個單詞所有tag的情況下的概率都算出來 然后取最大值 作為第一個tag的值 """ currbest = max(first_viterbi.keys(), key = lambda tag: first_viterbi[ tag ]) print( "Word", "'" + sentence[0] + "'", "current best two-tag sequence:", first_backpointer[ currbest], currbest) #Word 'I' current best two-tag sequence: START PP""" 就是這樣 我們一個單詞一個單詞往下算 每次都找到最大的那個概率 然后作為tag鏈 序列 好的一些都清晰了我們開始loop: """ for wordindex in range(1, len(sentence)):this_viterbi = { }this_backpointer = { }prev_viterbi = viterbi[-1]for tag in distinct_tags:# START沒有卵用的,我們要忽略if tag == "START": continue# 如果現(xiàn)在這個tag是X,現(xiàn)在的單詞是w,# 我們想找前一個tag Y,并且讓最好的tag sequence以Y X結(jié)尾。# 也就是說# Y要能最大化:# prev_viterbi[ Y ] * P(X | Y) * P( w | X)best_previous = max(prev_viterbi.keys(),key = lambda prevtag: \prev_viterbi[ prevtag ] * cpd_tags[prevtag].prob(tag) * cpd_tagwords[tag].prob(sentence[wordindex]))this_viterbi[ tag ] = prev_viterbi[ best_previous] * \cpd_tags[ best_previous ].prob(tag) * cpd_tagwords[ tag].prob(sentence[wordindex])this_backpointer[ tag ] = best_previous# 每次找完Y 我們把目前最好的 存一下currbest = max(this_viterbi.keys(), key = lambda tag: this_viterbi[ tag ])print( "Word", "'" + sentence[ wordindex] + "'", "current best two-tag sequence:", this_backpointer[ currbest], currbest)# 完結(jié)# 全部存下來viterbi.append(this_viterbi)backpointer.append(this_backpointer)""" 找END,結(jié)束: """# 找所有以END結(jié)尾的tag sequence prev_viterbi = viterbi[-1] best_previous = max(prev_viterbi.keys(),key = lambda prevtag: prev_viterbi[ prevtag ] * cpd_tags[prevtag].prob("END"))prob_tagsequence = prev_viterbi[ best_previous ] * cpd_tags[ best_previous].prob("END")# 我們這會兒是倒著存的。。。。因為。。好的在后面 best_tagsequence = [ "END", best_previous ] # 同理 這里也有倒過來 backpointer.reverse()""" 最終:回溯所有的回溯點此時,最好的tag就是backpointer里面的current best """current_best_tag = best_previous for bp in backpointer:best_tagsequence.append(bp[current_best_tag])current_best_tag = bp[current_best_tag]best_tagsequence.reverse() print( "The sentence was:", end = " ") for w in sentence: print( w, end = " ") print("\n") print( "The best tag sequence is:", end = " ") for t in best_tagsequence: print (t, end = " ") print("\n") print( "The probability of the best tag sequence is:", prob_tagsequence)""" Word 'I' current best two-tag sequence: START PP Word 'want' current best two-tag sequence: PP VB Word 'to' current best two-tag sequence: VB TO Word 'race' current best two-tag sequence: IN NN The sentence was: I want to race The best tag sequence is: START PP VB IN NN END The probability of the best tag sequence is: 5.71772824864617e-14 """

?

總結(jié)

以上是生活随笔為你收集整理的hmm进行英文词性标注的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。