HMM 隐形马尔科夫模型 分词

隐马模型




维特比算法

import codecs
import re
import numpy as np

stateNum = 4 #begin middle end single 四个状态
obsNum = 3717

def train():

    A = np.zeros((stateNum, stateNum))
    B = np.zeros((stateNum, obsNum))
    E = np.mat(np.zeros((1, stateNum)))
    tempB = np.zeros((obsNum, stateNum), dtype=int)
    all_chars = []
    train_corpus = "train_corpus"
    # train_corpus = "train_corpus_small"
    lines = codecs.open(train_corpus, encoding='utf-8').readlines()

    head_b_num = head_s_num = 0 #统计先验概率或者初始概率的
    bm = be = mm = me = eb = es = sb = ss = 0#处理转移概率的

    cnt = 0
    for line in lines:
        cnt += 1
        # print('sentence %d' % cnt)
        state_seq = ''
        line = line.strip()
        words_list = re.split('[,:;"\'?!、,:;。“”‘’?!()()<>〈〉《》\[\]【】 ]+', line)
        while '' in words_list:
            words_list.remove('')

        # print(line, words_list)
        if len(words_list) > 0:
            head = words_list[0]
            if len(head) == 1: head_s_num += 1
            else: head_b_num += 1

        for word in words_list:
            if len(word) == 1:
                char = word
                if char not in all_chars:
                    all_chars.append(char)
                ind = all_chars.index(char)
                tempB[ind][3] += 1
                state_seq += 'S'
            else:
                beg_char = word[0]
                state_seq += 'B'
                if beg_char not in all_chars:
                    all_chars.append(beg_char)
                ind = all_chars.index(beg_char)
                tempB[ind][0] += 1

                for i in range(1, len(word) - 1):
                    char = word[i]
                    if char not in all_chars:
                        all_chars.append(char)
                    ind = all_chars.index(char)
                    tempB[ind][1] += 1
                    state_seq += 'M'

                end_char = word[-1]
                state_seq += 'E'
                if end_char not in all_chars:
                    all_chars.append(end_char)
                ind = all_chars.index(end_char)
                tempB[ind][2] += 1
        bm, be, mm, me, eb, es, sb, ss = bm+state_seq.count('BM'),be+state_seq.count('BE'),mm+state_seq.count('MM'),me+state_seq.count('ME'),eb+state_seq.count('EB'),es+state_seq.count('ES'),sb+state_seq.count('SB'),ss+state_seq.count('SS'),
        # print(state_seq, [bm, be, mm, me, eb, es, sb, ss])
    print('共%d个字' % len(all_chars))
    # print([bm, be, mm, me, eb, es, sb, ss])
    E[0,0], E[0,3] = float(head_b_num)/(head_s_num+head_b_num), float(head_s_num)/(head_s_num+head_b_num)
    A[0][1],A[0][2],A[1][1],A[1][2],A[2][0],A[2][3],A[3][0],A[3][3] = float(bm)/(bm+be), float(be)/(bm+be), float(mm)/(mm+me), float(me)/(mm+me), float(eb)/(eb+es), float(es)/(eb+es), float(sb)/(sb+ss), float(ss)/(sb+ss)
    for i in range(stateNum):
        column_sum = tempB.sum(axis=0)  # obsNum*stateNum矩阵列求和结果为1*stateNum
        for j in range(obsNum):
            B[i,j] = float(tempB[j,i])/column_sum[i]
    # print(tempB, B)

    f = open('HMM-model\chars', 'a+')
    f.write('\n'.join(all_chars))
    np.savetxt('HMM-model\prob_start', E)
    np.savetxt('HMM-model\prob_trans', A)
    np.savetxt('HMM-model\prob_emit', B)
    np.savetxt('HMM-model\prob_B', tempB, fmt='%d')

    # f = open('HMM-model\small\chars', 'a+')
    # f.write('\n'.join(all_chars))
    # np.savetxt('HMM-model\small\prob_start', E)
    # np.savetxt('HMM-model\small\prob_trans', A)
    # np.savetxt('HMM-model\small\prob_emit', B)
    # np.savetxt('HMM-model\small\prob_B', tempB, fmt='%d')
    print('done')

'''
delta矩阵记录概率
psi矩阵记录路径
A B 记录转移和和发射概率的矩阵
'''


def viterbi(obs_seq):
    E = np.loadtxt('prob_start')
    A = np.loadtxt('prob_trans')
    B = np.loadtxt('prob_emit')
    f = open('chars').read()
    # E = np.loadtxt('HMM-model\small\prob_start')
    # A = np.loadtxt('HMM-model\small\prob_trans')
    # B = np.loadtxt('HMM-model\small\prob_emit')
    # f = open('HMM-model\small\chars').read()
    E = np.mat(E)
    all_chars = f.split('\n')
    while '' in all_chars:
        all_chars.remove('')#加载字典
    # print(len(all_chars))
    # print(E.shape, A.shape, B.shape)

    obs_seq = re.sub(' ', '', obs_seq)#观测到的值 待切分
    L = len(obs_seq)
    if L == 0: return

    Delta = np.zeros((L, stateNum))  #10*4
    l = [-1] * L * stateNum #10*4 长度的list
    Psi = np.mat(l).reshape(L, stateNum) #10*4的matrix 都是-1  # np.matrix(Delta-1)也行
    beg_char = obs_seq[0]
    ind = all_chars.index(beg_char) # 通过字典索引第一个字


    Delta[0,:] = np.multiply(E, B[:,ind].T)#先验概率乘发射概率

    for t in range(1, L):
        ind = all_chars.index(obs_seq[t])
        for i in range(stateNum):
            temp = np.multiply(Delta[t-1,:], A[:,i].T)#上一层最大概率乘以本层转移概率 (1,4)*(1,4)
            Delta[t,i] = np.max(temp) * B[i, ind]#上一层最大概率乘以本层转移概率乘以本层发射概率 找极大值,更新至本层最大概率
            if Delta[t,i] > 0:
                Psi[t,i] = np.argmax(temp) #存储本层最优路径
            print('temp: ', temp)
            print(np.max(temp), B[i, ind], A[:, i].T)
            print(np.argmax(temp), Delta[t,i])
            print(Psi)

    print(Delta)
    print(Psi)

    print('最优路径的概率为:', np.max(Delta[L-1, :]))

    t = L-1
    i = np.argmax(Delta[t, :])
    state_seq = str(i)
    i = Psi[t,i]
    state_seq += str(i)
    while(t > 1):
        t -= 1
        i = Psi[t,i]
        state_seq += str(i)
    state_seq = state_seq[::-1]
    print('最优路径为:', state_seq)

    seg_seq = ''
    for i in range(L):
        char = obs_seq[i]
        if state_seq[i] == '0':  seg_seq += ' ' + char
        elif state_seq[i] == '2': seg_seq += char + ' '
        elif state_seq[i] == '3': seg_seq += ' ' + char + ' '
        else: seg_seq += char
    return seg_seq


# train()
obs_seq = '新华社驻英国记者报道'
print('分词结果: ', viterbi(obs_seq))
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,519评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,842评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,544评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,742评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,646评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,027评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,513评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,169评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,324评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,268评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,299评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,996评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,591评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,667评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,911评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,288评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,871评论 2 341

推荐阅读更多精彩内容