• 利用隐马尔科夫链(HMM)模型实现中文分词


    1.什么是HMM?

    隐马尔科夫链(HMM)是一个五元组:

    • 隐状态集合 ;
    • 观测状态集合;
    • 状态概率转移矩阵;
    • 观察状态概率矩阵;
    • 初始状态概率分布;

    2.HMM有两个假设:

    • 齐次马尔可夫链假设:任意时刻的隐藏状态只依赖与前一时刻的隐藏状态。
    • 观测独立性假设:任意时刻的观察状态,只依赖与当前时刻的隐藏状态。

    3.HMM可以解决3类基本问题:

    • 评估观察序列的概率。
    • 学习模型参数。即给定观察序列,估计模型的参数,是观察序列出现的概率最大。
    • 预测问题。即给定观察序列和模型,求最有可能出现的对应状态序列。

    4.中文分词

    <1>抽象出五元组

    • StatusSet。状态集合为{B, M, E, S}.其中B表示词首,M表示词中间,E表示词尾,S表示单字成词。
    • ObservedSet。观察状态集合就是所有的汉字,甚至包括标点符号组成的集合。
    • TransProbMatrix。状态转移概率矩阵,就是{B, M, E, S} X {B, M, E, S}的一个4X4矩阵。
    • EmitProbMatrix。观察矩阵的每个元素都是一个条件概率,代表P(Observed[i]|Status[j])。
    • InitStatus。初始状态概率分布表示句子的第一个字属于{B,E,M,S}这四种状态的概率。

    <2>模型训练

    A_dic = {}        #状态转移概率矩阵
    B_dic = {} #观察概率矩阵
    Count_dic = {} #记录每一个状态出现的次数
    Pi_dic = {} #记录了每一行第一个状态出现的次数
    word_set = set() #存放所有出现的字(包括数字,标点符号等)
    state_list = ['B','M','E','S']
    line_num #记录样本行数


    按行遍历训练样本:

    (1) 获取每行样本对应的字符列表 word_list 以及状态列表  line_state;

    (2)记录字符集合 word_set 以及行数 line_num;

    (3)记录每行第一个状态出现的次数 Pi_dic[line_state[0]]+=1;

    (4)记录第 i-1 到 第 i 个状态转移的次数 A_dic[line_state[i-1]][line_state[i]]+=1;

    (5)记录每个状态出现的次数 count_dic[line_state[i]]+=1;

    (6)记录每个状态对应的发射概率 B_dic[line_state[i]][word_list[i]]+=1;

    (7)统计概率

        Pi_dic[state] = pi_dic[state] / line_num

        A_dic[state1][state2] = A_dic[state1][state2] / count_dic[state1]

        B_dic[state][word]  = B_dic[state][word] / count_dic[state]

    <3>利用Viterbi算法进行分词

     1 #obs:待分词的字符串
     2 #states:状态列表('B','M','E','S')
     3 #start_p:初始概率分布
     4 #trans_p:转移概率矩阵
     5 #emit_p: 发射概率矩阵
     6 def viterbi(obs, states, start_p, trans_p, emit_p):  #维特比算法
     7     V = [{}]#每个字对应一个字典,构成一个字典列表。字典格式:{‘B’:val,'M':val,'E':val,'S':val},val表示概率。字典表示当前字符对应的状态概率
     8     path = {}#以状态y结尾的路径如:{‘B’:['S','B'],'M':['B','M'],'E':['B','E'],'S':['S','S']}
     9     for y in states:   #字符串的第0个位置。初始值
    10         V[0][y] = start_p[y] * emit_p[y].get(obs[0],0)   #初始概率*发射概率。在位置0,以y状态为末尾的状态序列的最大概率
    11         path[y] = [y]#
    12     for t in range(1,len(obs)):#遍历字符串后面的字符
    13         V.append({})
    14         newpath = {}
    15         for y in states:      #从y0 -> y状态的递归,y表示当前时刻的状态,y0表示前一个时刻的状态。
    16             #prob对应状态的最大概率,state对应最大概率下上一时刻的状态。
    17             #(prob, state) = max([(V[t-1][y0] * trans_p[y0].get(y,0) * emit_p[y].get(obs[t],0) ,y0) for y0 in states if V[t-1][y0]>0])
    18             (prob, state) = max([(V[t-1][y0] * trans_p[y0].get(y,0) * emit_p[y].get(obs[t],0) ,y0) for y0 in states])
    19 
    20             V[t][y] =prob
    21             newpath[y] = path[state] + [y]#以状态y结尾的路径如:{‘B’:['S','B'],'M':['B','M'],'E':['B','E'],'S':['S','S']}
    22         path = newpath  #记录状态序列
    23     (prob, state) = max([(V[len(obs) - 1][y], y) for y in states])  #在最后一个位置,以y状态为末尾的状态序列的最大概率
    24     return (prob, path[state])  #返回概率和状态序列
    View Code
  • 相关阅读:
    Integration Services 学习(4):包配置
    Integration Services 学习(3)
    AsyncTask的使用
    asp.net下实现支持文件分块多点异步上传的 Web Services
    wcf/web service 编码
    c# 接发邮件2
    Integration Services 学习
    使用AChartEngine画柱状图
    Cocos2d开发系列(五)
    灵活使用XMultipleSeriesRenderer设置自定义的轴标签
  • 原文地址:https://www.cnblogs.com/cainiao-xf/p/8366402.html
Copyright © 2020-2023  润新知