維特比算法實(shí)現(xiàn)詞性標(biāo)注


s代表句子吱雏,w代表句子中的單詞,z代表單詞的詞性筛峭。推導(dǎo)式中用了一些基本的概率公式铐刘,有些地方簡(jiǎn)寫了。對(duì)于維特比與HMM的概念就不再贅述影晓。
python代碼主要分為三步來實(shí)現(xiàn):
1镰吵、對(duì)數(shù)據(jù)進(jìn)行處理;
2挂签、計(jì)算HMM三元組的PI疤祭、A、B饵婆;
3勺馆、維特比算法的實(shí)現(xiàn)。
數(shù)據(jù)集可聯(lián)系私發(fā),代碼如下:

#整理數(shù)據(jù)集
tag2id,id2tag = {},{}
word2id,id2word = {},{}
res = []
for line in open('dataset.txt','r', encoding='UTF-8'):
    temp = line.rstrip().split("/")
    if len(temp)==2:
        word, tag = temp[0], temp[1]
        if word not in word2id:
            word2id[word] = len(word2id)
            id2word[len(id2word)] = word
        if tag not in tag2id:
            tag2id[tag] = len(tag2id)
            id2tag[len(id2tag)] = tag
M = len(word2id)
N = len(tag2id)


#計(jì)算PI 草穆、A灌灾、B
import numpy as np
PI = np.zeros(N) #初始矩陣;每個(gè)詞性出現(xiàn)在句首的概率
A = np.zeros((N,M)) #發(fā)射矩陣悲柱;A[i][j]:給定tag[i] 出現(xiàn)單詞j的概率
B = np.zeros((N,N)) #狀態(tài)轉(zhuǎn)移矩陣紧卒;B[i][j]:從前一狀態(tài)i轉(zhuǎn)移到當(dāng)前狀態(tài)j的概率
pre_tag = ""
for line in open("dataset.txt","r",encoding='UTF-8'):
    items = line.rstrip().split("/")
    wordid,tagid= word2id[items[0]],tag2id[items[1]]
    if pre_tag=="": #意味著句子的開始
        PI[tagid] += 1 #先計(jì)算出現(xiàn)的次數(shù)
        A[tagid][wordid] += 1
    else: #如果不是句子的開頭
        A[tagid][wordid] += 1
        B[tag2id[pre_tag]][tagid] += 1
    if items[0] in ["。","诗祸!","跑芳?"]: #下一個(gè)單詞是新句子的開始
        pre_tag = ""
    else:
        pre_tag = items[1]

# 把頻次轉(zhuǎn)成概率
PI = PI/sum(PI)
for i in range(N):
    A[i] /= sum(A[i])
    B[i] /= sum(B[i])  #到此為止計(jì)算完了各個(gè)參數(shù)

#計(jì)算log值,防止出現(xiàn)log0
def log(ele):
    if ele == 0:
        return np.log(ele + 0.000001)
    return np.log(ele)

#利用前向最大匹配進(jìn)行分詞
def forwardMaxMatch(strng):
    dict = [x for x in word2id.keys()]
    result = []
    while len(strng):
        maxlength = 5 if len(strng)>=5 else len(strng)
        sub = strng[:maxlength]
        while sub not in dict and len(sub)>1:
            sub = sub[:len(sub)-1]
        result.append(sub)
        strng = strng[len(sub):]
    return "/".join(result)

#重頭戲:利用維特比進(jìn)行詞性標(biāo)注
def vertebi(x):
    x = forwardMaxMatch(x).split("/")
    res = [word2id[word] for word in x]
    T = len(res)
    ptr = np.zeros((T,N),dtype=int) #定義一個(gè)維特比籬笆網(wǎng)直颅,存放下標(biāo)博个,故指定為整型
    dp = np.zeros((T,N))
    for j in range(N):  #從前往后計(jì)算,所以要首先填充第一列
        dp[0][j] = log(PI[j])+log(A[j][res[0]]) #第一個(gè)tag是PI[j]的概率 + 詞性是A[j]的情況下是單詞x[0]的概率
    for i in range(1,T):  #每個(gè)單詞
        for j in range(N):  #每個(gè)詞性
            """"
            dp[i][j],ptr[i][j] = max(dp[i-1][k] + log(B[k][j]) + log(A[j][res[i]],k) for k in range(N))   
            這一行可代替下面六行        
            """
            dp[i][j] = -9999999999
            for k in range(N): #從前一項(xiàng)的每一個(gè)k可達(dá)到當(dāng)前的詞性j
                scores = dp[i-1][k] + log(B[k][j]) + log(A[j][res[i]]) #前一列的第k個(gè)轉(zhuǎn)移過來的概率+狀態(tài)轉(zhuǎn)移概率(k->j)+詞性為A[j]時(shí)單詞正好為x[i]的概率
                if scores > dp[i][j]:
                    dp[i][j] = scores
                    ptr[i][j] = k #填充籬笆網(wǎng)絡(luò)  當(dāng)前最好路徑是從k過來的
    # 把最好的tag sequence打印出來(從后到前)
    best_seq= [0]*T #找出籬笆網(wǎng)絡(luò)最后一列中最大的值得下標(biāo)
    best_seq[T-1] = np.argmax(dp[T-1])
    for i in range(T-2,-1,-1): #從后往前其次求出每個(gè)單詞的詞性
        best_seq[i]=ptr[i+1][best_seq[i+1]]
    result = []
    for i in range(len(best_seq)):
        result.append(x[i]+'/'+id2tag[best_seq[i]]+" ")
    return "".join(result)

sentence = input("請(qǐng)輸入您想要進(jìn)行詞性標(biāo)注的句子:")
print(vertebi(sentence))
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末功偿,一起剝皮案震驚了整個(gè)濱河市盆佣,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌械荷,老刑警劉巖共耍,帶你破解...
    沈念sama閱讀 211,817評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異吨瞎,居然都是意外死亡痹兜,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,329評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門颤诀,熙熙樓的掌柜王于貴愁眉苦臉地迎上來字旭,“玉大人,你說我怎么就攤上這事崖叫∫糯荆” “怎么了?”我有些...
    開封第一講書人閱讀 157,354評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵心傀,是天一觀的道長(zhǎng)屈暗。 經(jīng)常有香客問我,道長(zhǎng)脂男,這世上最難降的妖魔是什么养叛? 我笑而不...
    開封第一講書人閱讀 56,498評(píng)論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮疆液,結(jié)果婚禮上一铅,老公的妹妹穿的比我還像新娘。我一直安慰自己堕油,他們只是感情好潘飘,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,600評(píng)論 6 386
  • 文/花漫 我一把揭開白布肮之。 她就那樣靜靜地躺著,像睡著了一般卜录。 火紅的嫁衣襯著肌膚如雪戈擒。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,829評(píng)論 1 290
  • 那天艰毒,我揣著相機(jī)與錄音筐高,去河邊找鬼。 笑死丑瞧,一個(gè)胖子當(dāng)著我的面吹牛柑土,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播绊汹,決...
    沈念sama閱讀 38,979評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼稽屏,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了西乖?” 一聲冷哼從身側(cè)響起狐榔,我...
    開封第一講書人閱讀 37,722評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎获雕,沒想到半個(gè)月后薄腻,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,189評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,519評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,654評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡符匾,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出镐牺,到底是詐尸還是另有隱情撞蜂,我是刑警寧澤,帶...
    沈念sama閱讀 34,329評(píng)論 4 330
  • 正文 年R本政府宣布仓蛆,位于F島的核電站睁冬,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏看疙。R本人自食惡果不足惜豆拨,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,940評(píng)論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望能庆。 院中可真熱鬧施禾,春花似錦、人聲如沸搁胆。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,762評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至攀例,卻和暖如春船逮,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背粤铭。 一陣腳步聲響...
    開封第一講書人閱讀 31,993評(píng)論 1 266
  • 我被黑心中介騙來泰國(guó)打工挖胃, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人梆惯。 一個(gè)月前我還...
    沈念sama閱讀 46,382評(píng)論 2 360
  • 正文 我出身青樓酱鸭,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親垛吗。 傳聞我的和親對(duì)象是個(gè)殘疾皇子凛辣,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,543評(píng)論 2 349

推薦閱讀更多精彩內(nèi)容