精华内容
下载资源
问答
  • HMM——求隐藏序列,维特比算法求解
    2020-12-19 23:54:08

    情景假设

    一个东京的朋友每天根据天气{下雨,天晴}决定当天的活动{公园散步,购物,清理房间}中的一种,我每天只能在twitter上看到她发的推“啊,我前天公园散步、昨天购物、今天清理房间了!”,那么我可以根据她发的推特推断东京这三天的天气。在这个例子里,显状态是活动即购物,散步以及整理,隐状态是天气。我们要求出活动对应得天气情况。

    条件描述

    隐含状态

    states = ('Rainy', 'Sunny')

    显性状态

    observations = ('walk', 'shop', 'clean')

    初试状态概率(隐含态)

    start_probability = {'Rainy': 0.6, 'Sunny': 0.4}

    转换状态

    transition_probability = {

    'Rainy' : {'Rainy': 0.7, 'Sunny': 0.3},

    'Sunny' : {'Rainy': 0.4, 'Sunny': 0.6},

    }

    发射状态(对应隐含状态为显性状态概率)

    emission_probability = {

    'Rainy' : {'walk': 0.1, 'shop': 0.4, 'clean': 0.5},

    'Sunny' : {'walk': 0.6, 'shop': 0.3, 'clean': 0.1},

    }

    states = ('Rainy', 'Sunny')

    observations = ('walk', 'shop', 'clean')

    start_probability = {'Rainy': 0.6, 'Sunny': 0.4}

    transition_probability = {

    'Rainy': {'Rainy': 0.7, 'Sunny': 0.3},

    'Sunny': {'Rainy': 0.4, 'Sunny': 0.6},

    }

    emission_probability = {

    'Rainy': {'walk': 0.1, 'shop': 0.4, 'clean': 0.5},

    'Sunny': {'walk': 0.6, 'shop': 0.3, 'clean': 0.1},

    }

    # 打印路径概率表

    def print_dptable(V):

    print " ",

    for i in range(len(V)): print "%7d" % i,

    print

    for y in V[0].keys():

    print "%.5s: " % y,

    for t in range(len(V)):

    print "%.7s" % ("%f" % V[t][y]),

    print

    def viterbi(obs, states, start_p, trans_p, emit_p):

    """

    :param obs:观测序列

    :param states:隐状态

    :param start_p:初始概率(隐状态)

    :param trans_p:转移概率(隐状态)

    :param emit_p: 发射概率 (隐状态表现为显状态的概率)

    :return:

    """

    # 路径概率表 V[时间][隐状态] = 概率

    V = [{}]

    # 一个中间变量,代表当前状态是哪个隐状态

    path = {}

    # 初始化初始状态 (t == 0)

    for y in states:

    V[0][y] = start_p[y] * emit_p[y][obs[0]]

    path[y] = [y]

    # 对 t > 0 跑一遍维特比算法

    for t in range(1, len(obs)):

    V.append({})

    newpath = {}

    for y in states:

    # 概率 隐状态 = 前状态是y0的概率 * y0转移到y的概率 * y表现为当前状态的概率

    (prob, state) = max([(V[t - 1][y0] * trans_p[y0][y] * emit_p[y][obs[t]], y0) for y0 in states])

    # 记录最大概率

    V[t][y] = prob

    # 记录路径

    newpath[y] = path[state] + [y]

    # 不需要保留旧路径

    path = newpath

    print path

    #print_dptable(V)

    (prob, state) = max([(V[len(obs) - 1][y], y) for y in states])

    return (prob, path[state])

    def example():

    return viterbi(observations,

    states,

    start_probability,

    transition_probability,

    emission_probability)

    print example()

    需要注意

    隐性状态的转移必须满足马尔可夫性。(状态转移的马尔可夫性:一个状态只与前一个状态有关)

    隐性状态必须能够大概被估计。在满足条件的情况下,确定问题中的隐性状态是什么,隐性状态的表现可能又有哪些.HMM适用于的问题在于,真正的状态(隐态)难以被估计,而状态与状态之间又存在联系。

    本文转自以下博主

    更多相关内容
  • HMM学习笔记1

    2020-12-29 07:34:04
    周文铠最近在看HMM模型,先看了理论基础的东西,写了总结如下,大体就是把国内一些书上的概述和HMM学习范例结合在一起,自己以后看起来方便点。众所周知,定义一个一阶马尔科夫过程,可以由三个量来描述:1)状态:...

    周文铠

    最近在看HMM模型,先看了理论基础的东西,写了总结如下,大体就是把国内一些书上的概述和HMM学习范例结合在一起,自己以后看起来方便点。

    众所周知,定义一个一阶马尔科夫过程,可以由三个量来描述:

    1)状态:状态个数(N)、状态集(

    );

    2)π向量:系统初始化状态向量;

    3)状态转移矩阵(A):表示前一个状态已知的情况下下一个状态的发生概率。

    在某些情况下,马尔科夫状态并不能满足模式描述的要求。典型的例子如语音识别,我们听到的声音是来自于声带、喉咙大小、舌头位置以及其他一些东西的组合结果。所有这些因素相互作用产生一个单词的声音,一套语音识别系统检测的声音就是来自于个人发音时身体内部物理变化所引起的不断改变的声音。这时我们定义两类状态:观察状态和隐藏状态。语音识别装置工作的原理是将内部的语音产出看作是隐藏的状态,而将声音结果作为一系列观察的状态,这些由语音过程生成并且最好的近似了实际(隐藏)的状态。

    在这种情况下,观察到的状态序列与隐藏过程有一定的概率关系。我们使用隐马尔科夫模型(HMM)对这样的过程建模,这个模型包含了一个底层隐藏的随时间改变的马尔科夫过程,以及一个与隐藏状态某种程度相关的可观察到的状态集合。

    通常,定义一个HMM状态

    建模包含两组状态集合和三组概率集合:

    1)观察状态集:M(可观察到的符号数)、符号集V={

    }、观察序列O={

    };

    2)隐藏状态集:状态个数(N)、状态集

    3)隐藏状态转移概率分布(矩阵):A=(

    );

    4)观察符号概率分布(混淆矩阵):B=(

    )给定了HMM某一个隐藏状态下,观察到某个符号的概率;

    5)π向量:Π=(

    )系统初始化状态向量。

    一旦一个系统可以作为HMM被描述,就可以用来解决三个基本问题。其中前两个是模式识别问题:给定HMM求一个观察序列的概率(评估);搜索最有可能生成一个观察序列的隐藏状态序列(解码)。第三个问题是给定观察序列生成一个HMM(学习)。

    1、评估:

    已知一个特定的观察序列O和一些HMM模型(

    的集合),求,最有可能产生该观察序列的HMM模型。即求每个HMM模型产生此观察序列的概率

    ,取最大值。

    方法:

    穷举搜索:

    找到每一个可能的隐藏状态,并且将这些隐藏状态下的观察序列概率相加。用这种方式计算观察序列概率极为昂贵,特别对于大的模型或较长的序列,因此我们可以利用这些概率的时间不变性来减少问题的复杂度。

    前向算法:

    给定一个隐马尔科夫模型(HMM),我们将考虑递归地计算一个观察序列的概率。我们首先定义局部概率а,它是到达网格中的某个中间状态时的概率。

    第一步:计算t=1时刻所有状态的局部概率,为初始概率乘以观察概率分布:

    第二步:计算t=2,3,…,T时每个状态的局部概率,根据前一时刻的状态不变性,进行迭代计算:

    =P(观察状态|隐藏状态j)*P(t时刻所有指向j状态的路径)

    第三步:对于给定HMM,观察序列的概率等于T时刻所有局部概率之和:

    使用前向算法来计算给定隐马尔科夫模型(HMM)后的一个观察序列的概率。它在计算中利用递归避免对网格所有路径进行穷举计算。给定这种算法,可以直接用来确定对于已知的一个观察序列,在一些隐马尔科夫模型(HMMs)中哪一个HMM最好的描述了它——先用前向算法评估每一个(HMM),再选取其中概率最高的一个。

    总结:在语音识别中,我们可以通过计算比较

    ,从多个模型中选择出与观察序列匹配的最好的那个模型。

    2、解码:

    已知一个特定的HMM以及一个相应的观察序列,找到生成此观察序列最可能的隐藏状态序列,即找出从初始时刻到结束时刻的最佳状态转移路径。

    方法:

    穷举搜索:

    可以通过列出所有可能的隐藏状态序列并且计算对于每个组合相应的观察序列的概率来找到最可能的隐藏状态序列。最可能的隐藏状态序列是使下面这个概率最大的组合:

    P(观察序列|隐藏状态的组合)

    这种方法是可行的,但是通过穷举计算每一个组合的概率找到最可能的序列是极为昂贵的。与前向算法类似,我们可以利用这些概率的时间不变性来降低计算复杂度。

    Viterbi算法:

    我们首先定义局部概率δ,它是到达网格中的某个特殊的中间状态时的概率。对于网格中的每一个中间及终止状态,都有一个到达该状态的最可能路径。我们称这些路径为局部最佳路径(

    )。其中每个局部最佳路径都有一个相关联的概率,即局部概率。与前向算法中的局部概率不同,是到达该状态(最可能)的一条路径的概率,而不是所有路径概率的总和。

    因而

    是t时刻到达状态i的所有序列概率中最大的概率,而局部最佳路径是得到此最大概率的隐藏状态序列。对于每一个可能的i和t值来说,这一类概率(及局部路径)均存在。特别地,在t

    =T时每一个状态都有一个局部概率和一个局部最佳路径。这样我们就可以通过选择此时刻包含最大局部概率的状态及其相应的局部最佳路径来确定全局最佳路径(最佳隐藏状态序列)。

    第一步:通过隐藏状态的初始概率和相应的观察概率之积计算t=1时刻的局部概率。

     1≤

    ≤N

    第二步:回顾一下马尔科夫假设:给定一个状态序列,一个状态发生的概率只依赖于前n个状态。特别地,在一阶马尔可夫假设下,当前状态在一个状态序列后发生的概率只取决于之前的一个状态(迭代计算):

    在每一个中间及终止状态我们都知道了局部概率

    。然而我们的目标是在给定一个观察序列的情况下寻找网格中最可能的隐藏状态序列。因此,我们需要一些方法来记住网格中的局部最佳路径。回顾一下我们是如何计算局部概率的,计算t时刻的δ时,我们仅仅需要知道t-1时刻的δ。在这个局部概率计算之后,就有可能记录前一时刻哪个状态生成了

    。也就是说,在t-1时刻系统必须处于某个状态,该状态导致了系统在t时刻到达状态i是最优的。这种记录(记忆)是通过对每一个状态赋予一个反向指针完成的,这个指针指向最优的引发当前状态的前一时刻的某个状态。形式上,我们可以写成如下的公式:

    其中arg max运算符是用来计算使括号中表达式的值最大的索引j的。

    这样就确定了到达下一个状态的最可能路径,并对如何到达下一个状态做了记录。具体来说首先通过考察所有的转移概率与上一步获得的最大的局部概率之积,然后记录下其中最大的一个,同时也包含了上一步触发此概率的状态。

    第三步:确定系统完成时(t=T)最可能的隐藏状态:

    第四步:通过回溯确定最终路径:

    3、学习:

    根据观察序列生成隐马尔科夫模型。在以上两个问题当中,我们都是已知一个固定的HMM( )来进行计算,在一些情况中,如一个庞大的语音处理数据库,其隐层的语音可能由一个马尔可夫过程基于已知的音素建模的,而其可以观察的部分可能由可识别的状态(可能通过一些矢量数据表示)建模的,但是没有直接的方式来获取隐马尔科夫模型(HMM)参数。这时就需要通过学习让系统自己寻找最优参数。通常用Baum-Waich算法来实现这一目的。

    定义两个相关的概率模型:

    表示给定观察序列O和模型

    的情况下,t时刻处于状态i,t+1时刻处于状态j的概率,归一化表示:

    表示给定观察序列O和模型

    的情况下,t时刻处于状态i的概率,归一化表示:

    表示观察序列中,从状态i出发的状态转移次数的期望。

    表示观察序列中,从状态i到j的状态转移次数的期望。

    Baum-Waich算法的基本思想就是,先任意指定参数模型 ,通过特定的参数重估公式根据现有的模型 得到新的参数 ,保证

    ,然后将新的参数 重复上述过程,直到参数模型处于收敛状态,即得到最大似然模型。

    重构公式的推导过程忽略,最后得到的结果是:

    在限制条件:

    下:

    总结来说重估的步骤就是EM算法的一种特殊情况,按照E步M步计算即可。

    展开全文
  • HMM用于序列标注

    2020-02-07 00:17:15
    HMM原理 初始化矩阵、发射矩阵、状态转移矩阵的训练 使用viterbi预测 jieba的使用方法 保存预训练好的参数,直接使用并预测

    1. HMM模型

    1.1 模型

    隐马尔可夫模型(Hidden Markov Model, HMM)是可用于标注问题(属于监督学习)的统计学习模型,描述由隐藏的马尔可夫链随机生成观测序列的过程,属于生成模型。HMM模型是关于时序的概率模型,由隐藏的状态随机序列生成可观测的观测随机序列,在语音识别、自然语言处理、生物信息、模式识别、安全领域中的网络安全领域等有广泛的应用。
    在这里插入图片描述
    HMM属于概念图模型中的有向图模型。上图中一个结点代表一个随机变量,有向边代表依赖关系。比如 o 1 o_1 o1依赖于 q 1 q_1 q1。这里注意:观测序列是依赖于隐状态的!

    1.2 HMM参数

    λ = { A , B , π } \lambda = \{A,B,\pi \} λ={A,B,π}

    A为状态转移矩阵:各个隐状态之间转化的概率,矩阵 A = [ a i j ] N × N A=[a_{ij}]_{N \times N} A=[aij]N×N代表隐状态 s i s_i si转化为 s j s_j sj状态的概率。比如第 i i i行表示隐状态 s i s_i si转化为每一个状态的概率。本质上是一个条件概率: a i j = P ( i t + 1 = q j ∣ i t = q i ) a_{ij}=P(i_{t+1}=q_j|i_t=q_i) aij=P(it+1=qjit=qi)

    B为发射矩阵或者叫做观测概率矩阵:在某个隐状态下观测到不同的预测值的概率, B = [ b j ( k ) ] N × M B=[b_j(k)]_{N \times M} B=[bj(k)]N×M。其中 b j ( k ) = P ( o t = v k ∣ i t = q j ) , k = 1 , 2 , . . . , M ; j = 1 , 2 , . . , N b_j(k)=P(o_t=v_k|i_t=q_j),k=1,2,...,M;j=1,2,..,N bj(k)=P(ot=vkit=qj)k=1,2,...,Mj=1,2,..,N
    是在t时刻处于状态 q j q_j qj的条件下生成观测 v k v_k vk的概率。

    π \pi π为初始化概率:初始状态下各个隐状态发生的概率

    1.3 两个假设

    • 齐次马尔可夫假设:隐状态 q t q_t qt发生只依赖于上一个隐状态
      P ( q t ∣ q 1 , q 2 , . . . , q i − 1 , o 1 , o 2 , . . . , o t − 1 ) = P ( q t ∣ q t − 1 ) P(q_t|q_1,q_2,...,q_{i-1},o_1,o_2,...,o_{t-1})=P(q_t|q_{t-1}) P(qtq1,q2,...,qi1,o1,o2,...,ot1)=P(qtqt1)
    • 观测独立性假设:观测值 o t o_t ot的出现只依赖于此时的状态,与其它的隐状态无关
      P ( o t ∣ o 1 , o 2 , . . . , o t − 1 , o t + 1 , . . . , o T , q 1 , q 2 , . . . , q t , q t + 1 , . . . , q T ) = P ( o t ∣ q t ) P(o_t|o_1,o_2,...,o_{t-1},o_{t+1},...,o_T,q_1,q_2,...,q_t,q_{t+1},...,q_T)=P(o_t|q_t) P(oto1,o2,...,ot1,ot+1,...,oT,q1,q2,...,qt,qt+1,...,qT)=P(otqt)

    1.4 三个问题

    1. 概率计算问题(Evaluating),给定模型 λ = { A , B , π } \lambda = \{A,B,\pi \} λ={A,B,π}和观测序列 O = { o 1 , o 2 , . . . , o T } O=\{o_1,o_2,...,o_T\} O={o1,o2,...,oT},计算在模型 λ \lambda λ下观测序列 O O O出现的概率 P ( O ∣ λ ) P(O|λ) P(Oλ)。使用的方法:向前或向后算法。

    2. 学习问题(Learning),已知观测序列 O = { o 1 , o 2 , . . . , o T } O=\{o_1,o_2,...,o_T\} O={o1,o2,...,oT},估计模型的参数 λ = { A , B , π } \lambda = \{A,B,\pi \} λ={A,B,π},使得在该模型下观测序列的概率 P ( O ∣ λ ) P(O|λ) P(Oλ)最大。有监督(已经观测序列和标注序列)的训练方法:极大似然估计的方法估计参数,无监督(只知道观测序列,不知道标注序列)的训练方法:BW/EM算法进行参数估计。

    3. 预测问题,也称为解码(Decoding)问题。已知模型 λ = { A , B , π } \lambda = \{A,B,\pi \} λ={A,B,π}和观测序列 O = { o 1 , o 2 , . . . , o T } O=\{o_1,o_2,...,o_T\} O={o1,o2,...,oT},求对给定观测序列条件概率 P ( I ∣ O ) P(I|O) P(IO)最大的状态序列 I = { i 1 , i 2 , . . . i T } I=\{i_1,i_2,...i_T\} I={i1,i2,...iT},即给定观测序列求最有可能的对应的状态序列,使用动态规则求解,即Viterbi算法。注意Viterbi算法不是HMM的专属,在CRF中也有使用。

    2. HMM用于分词

    HMM模型代码:

    import pickle
    import json
    
    # 定义模型的四个状态 B代表词的第一个字,M代表中间的字,
    # E代表词的结尾,S表示单独的一个字
    STATES = {'B', 'M', 'E', 'S'}
    EPS = 0.0001
    # 定义停顿标点
    seg_stop_words = {" ", ",", "。", "“", "”", '“', "?", "!", ":", "《", "》", "、", ";", "·", "‘ ", "’", "──", ",", ".", "?",
                      "!", "`", "~", "@", "#", "$", "%", "^", "&", "*", "(", ")", "-", "_", "+", "=", "[", "]", "{", "}",
                      '"', "'", "<", ">", "\\", "|" "\r", "\n", "\t"}
    
    
    class HmmModel:
        def __init__(self):
            """
            类中维护的模型参数均为频数而非频率, 这样的设计使得模型可以进行在线训练,
            使得模型随时都可以接受新的训练数据继续训练,不会丢失前次训练的结果
            """
            # 转移矩阵,二维:trans_mat[stat1][stat2]表示训练集中由stat1转化为stat2的次数
            self.trans_mat = {}
            # 发射矩阵,二维:emit_mat[stat1][char]表示训练集中单字char被标注为状态stat1的次数
            self.emit_mat = {}
            # 初始矩阵,一维:init_vec:表示状态stat在训练集中出现的次数
            self.init_vec = {}
            # 统计四个状态出现的次数 二维用来计算初始概率
            self.state_count = {}
            # 状态 四个状态
            self.states = STATES
            self.inited = False
    
        # 初始化hmm模型的参数矩阵
        def setup(self):
            for state in self.states:
                self.trans_mat[state] = {}
                # 转移矩阵初始化完成,trans_mat[i][j]是指状态i转化为状态j的概率
                for target in self.states:
                    self.trans_mat[state][target] = 0.0
                # 发射矩阵每一行是一个状态,每一列是一个字
                self.emit_mat[state] = {}
                # 初始状态为0
                self.init_vec[state] = 0.0
                self.state_count[state] = 0
            self.inited = True
    
        # 模型保存, 支持两种类型的数据格式,json和pickle
        def save(self, filename='hmm.json', code='json'):
            with open(filename, 'w', encoding='utf-8') as f:
                data = {
                    'trans_mat': self.trans_mat,
                    'emit_mat': self.emit_mat,
                    'init_vec': self.init_vec,
                    'state_count': self.state_count,
                }
                if code == 'json':
                    txt = json.dumps(data)
                    txt = txt.encode('utf-8').decode('unicode-escape')
                    f.write(data)
                elif code == 'pickle':
                    pickle.dump(data, f)
    
        # 模型加载
        def load(self, filename='hmm.json', code='json'):
            with open(filename, 'r', encoding='utf-8') as f:
                if code == 'json':
                    model = json.load(f)
                elif code == 'pickle':
                    model = pickle.load(f)
    
                # 这里加载模型是把参数初始化了,并没有返回文件
                self.trans_mat = model['trans_mat']
                self.emit_mat = model['emit_mat']
                self.init_vec = model['init_vec']
                self.state_count = model['state_count']
                self.inited = True
    
        # 模型训练 参数是观测序列与状态序列
        def do_train(self, observes, states):
            if not self.inited:
                self.setup()
            for i in range(len(states)):
                if i == 0:
                    # 把一条序列的第一个状态作为初始状态
                    self.init_vec[states[0]] += 1
                    # 所有的状态计数
                    self.state_count[states[0]] += 1
                else:
                    # states[i-1][i] 第i-1个状态转化为第i个状态的次数
                    self.trans_mat[states[i - 1]][states[i]] += 1
                    self.state_count[states[i]] += 1
    
                # 处理emit_mat
                # 如果观测值在之前没有出现过,计为1,否则+1
                if observes[i] not in self.emit_mat[states[i]]:
                    self.emit_mat[states[i]][observes[i]] = 1
                else:
                    self.emit_mat[states[i]][observes[i]] += 1
    
        # 在进行预测前,将各个矩阵中的频数转换为频率
        def get_prob(self):
            init_vec = {}
            trans_mat = {}
            emit_mat = {}
    
            # default是一个非零的数
            defalut = max(self.state_count.values())
    
            # 以B开头的个数除以B出现的总个数,如果是零的话就为0
            for key in self.init_vec:
                if self.state_count[key] != 0:
                    init_vec[key] = float(self.init_vec[key] / self.state_count[key])
                else:
                    init_vec[key] = float(self.init_vec[key] / defalut)
    
            # B转化为M的概率为B转化为M的次数除以B出现的总次数
            for key1 in self.trans_mat:
                trans_mat[key1] = {}
                for key2 in self.trans_mat[key1]:
                    if self.state_count[key1] != 0:
                        trans_mat[key1][key2] = float(self.trans_mat[key1][key2] / self.state_count[key1])
                    else:
                        trans_mat[key1][key2] = float(self.trans_mat[key1][key2] / defalut)
    
            # B状态下“我”出现的概率为B状态下“我”出现的次数除以B状态出现的总次数
            for key1 in self.emit_mat:
                emit_mat[key1] = {}
                for key2 in self.emit_mat[key1]:
                    if self.state_count[key1] != 0:
                        emit_mat[key1][key2] = float(self.emit_mat[key1][key2] / self.state_count[key1])
                    else:
                        emit_mat[key1][key2] = float(self.emit_mat[key1][key2] / defalut)
    
            return init_vec, trans_mat, emit_mat
    
        # 模型预测,使用viterbi算法
        def do_predict(self, sequence):
            tab = [{}]
            path = {}
            init_vec, trans_mat, emit_mat = self.get_prob()
            for state in self.states:
                tab[0][state] = init_vec[state] * emit_mat[state].get(sequence[0], EPS)
                path[state] = [state]
    
            # 创建动态搜索表
            for t in range(1, len(sequence)):
                tab.append({})
                new_path = {}
                for state1 in self.states:
                    items = []
                    for state2 in self.states:
                        if tab[t - 1][state2] == 0:
                            continue
                        prob = tab[t - 1][state2] * trans_mat[state2].get(state1, EPS) * emit_mat[state2].get(sequence[t],
                                                                                                              EPS)
                        items.append((prob, state2))
                    # max()函数,默认是list中所有tuple的第一个值的最大值
                    best = max(items)
                    tab[t][state1] = best[0]
                    new_path[state1] = path[best[1]] + [state1]
                path = new_path
    
            # 搜索最优路径
            prob, state = max([(tab[len(sequence) - 1][state], state) for state in self.states])
            return path[state]
    
    
    # 打标签的工具函数
    def get_tags(word):
        tag = []
        if len(word) == 1:
            return ['S']
        elif len(word) == 2:
            return ['B', 'E']
        else:
            num_mid = len(word) - 2
            tag.append('B')
            tag.extend(['M'] * num_mid)
            tag.append('E')
            return tag
    
    
    # 根据预测得到的标注序列将输入的句子分割为词语列表,也就是预测得到的状态序列,
    # 解析成一个 list 列表进行返回,具体实现如下:
    def cut_sent(src, tags):
        word_list = []
        start = -1
        started = False
    
        if len(tags) != len(src):
            return None
    
        if tags[-1] not in {'S', 'E'}:
            if tags[-2] in {'S', 'E'}:
                tags[-1] = 'S'
            else:
                tags[-1] = 'E'
    
        for i in range(len(tags)):
            if tags[i] == 'S':
                if started:
                    started = False
                    word_list.append(src[start:i])
                word_list.append(src[i])
            elif tags[i] == 'B':
                if started:
                    word_list.append(src[start:i])
                start = i
                started = True
            elif tags[i] == 'E':
                started = False
                word = src[start:i + 1]
                word_list.append(word)
            elif tags[i] == 'M':
                continue
        return word_list
    
    
    class HMMKnife(HmmModel):
        def __init__(self, *args, **kwargs):
            super(HMMKnife, self).__init__(*args, **kwargs)
            self.state = STATES
            self.data = None
    
        # 加载训练数据
        def read_text(self, filename):
            self.data = open(filename, 'r', encoding='utf-8')
    
        # 训练模型
        def train(self):
            if not self.inited:
                self.setup()
    
            for line in self.data:
                line = line.strip()
                if not line:
                    continue
    
                # 观测序列
                observe = []
                for i in range(len(line)):
                    if line[i] == ' ':
                        continue
                    else:
                        observe.append(line[i])
    
                # 状态序列
                words = line.split(' ')
                states = []
                for word in words:
                    if word in seg_stop_words:
                        continue
                    states.extend(get_tags(word))
    
                # 开始训练数据
                if len(observe) >= len(states):
                    self.do_train(observe, states)
                else:
                    pass
    
        # 对给定的句子分词
        def lcut(self, sentense):
            tags = self.do_predict(sentense)
            return cut_sent(sentense, tags)
    

    参考 :
    https://www.jianshu.com/p/59490ffe7f7c

    3. jieba的使用

    保存预训练好的参数,直接使用并预测。
    jieba对句子分词的核心代码在finalseg模块中:
    在这里插入图片描述
    从模型信息中可以看出来,HMM模型最核心的三个矩阵emit,start,trans矩阵都是训练好的数据存在模块中的。
    加载模型时会加载矩阵,直接使用viterbi算法根据句子计算最优的隐状态(BMES)的序列。
    在这里插入图片描述

    展开全文
  • hmm隐藏状态是什么?

    2020-12-19 23:54:05
    隐藏状态是抽象出来的概念,目前我没有见到过哪篇论文或教材对其进行过准确的解释。我个人理解,由于语音信号在一个长时间断内(比如一秒以上)是非平稳信号,而在一个较短的时间内则可近似看做平稳的(比如50毫秒)。...

    隐藏状态是抽象出来的概念,目前我没有见到过哪篇论文或教材对其进行过准确的解释。我个人理解,由于语音信号在一个长时间断内(比如一秒以上)是非平稳信号,而在一个较短的时间内则可近似看做平稳的(比如50毫秒)。平稳信号的特点在于信号的频谱分布是稳定的,不同时间段的频谱分布相似。隐马尔可夫模型将一小段频谱相似的连续信号归为一个隐状态。隐马尔可夫模型的训练过程是最大化似然度,每一个状态产生的数据用一个概率分布表示。只有当相似的连续信号尽可能被归为同一个状态,似然度才能尽可能的大。

    为了能够更加形象的说明隐状态的含义,我举个例子。下面这张图片是一个单词的时频谱图,横坐标为时间,纵坐标为频率,图中的每个像素点的强度表示在某一时刻,某一频率下信号的强度;每个像素点的信号强度用颜色表示,蓝色部分的信号强度最弱,红色部分强度次之,白色强度最高。

    可以看到在整个时间窗口内(大约240毫秒),信号在初始时刻的各频率的强度分布和中间段,以及末尾段各频率的强度分布是有着很大的差距的。但是如果我们用黑色的虚线将信号分成8小段(如图所示),在这一小段时间内各频率的强度分布大致是相似的。因此我们可以将这个音频看做由8个隐状态的hmm模型产生的,每个隐状态产生的信号对应着这8段中的一段信号,每个隐状态负责对频谱相似的一小段信号进行建模。

    我这里为了说明隐状态的含义只是手动的对音频进行分段,而真实hmm-gmm模型的训练任务就是通过EM算法自动的对数据进行分段,每一小段数据用一个隐状态进行建模。

    hmm-gmm模型的训练只需要给出语音段的文本标注即可,不需要隐状态序列的标注。但是hmm-dnn的训练则需要隐状态序列的标注,该标注是通过hmm-gmm+音频生成的。实际上hmm-dnn的训练只是对dnn进行训练而已,其中的hmm模型是从hmm-gmm那里复制过来的,而不是和dnn一起训练得到的。而dnn的训练则需要隐状态标注。

    展开全文
  •  隐马尔科夫模型HMM(四)维特比算法解码隐藏状态序列  在隐马尔科夫模型HMM(一)HMM模型中,我们讲到了HMM模型的基础知识和HMM的三个基本问题,本篇我们就关注于HMM第一个基本问题的解决方法,即...
  • 隐马尔科夫模型HMM(四)维特比算法解码隐藏状态序列在本篇我们会讨论HMM模型最后一个问题的求解,即即给定模型和观测序列给定观测序列条件下,最可能出现的对应的隐藏状态序列。在阅读本篇前,建议先阅读这个系列...
  • 在本篇我们会讨论HMM模型最后一个问题的求解,即即给定模型和观测序列给定观测序列条件下,最可能出现的对应的隐藏状态序列。在阅读本篇前,建议先阅读这个系列的第一篇以熟悉HMM模型。HMM模型的解码问题最常用...
  • 前言 概率序列模型:它的工作是为序列中的每个单元分配一个标签或类,从而将一个观察序列映射到一个标签序列。给定一个单位序列(单词、字母、语素、句子,等等),它...HMM 隐式马尔可夫模型 在许多情况下,我们...
  • 隐藏式马尔可夫模型(HMM)用于分离细菌DNA中的基因和基因间区域 等级= 100% 问题1 a)使用霍乱弧菌的基因组序列和基因注释,创建配置表 代码: i)基因间区域的平均长度:1164.4bp ii)遗传区域的平均长度:991....
  • 仍沿用上一节中HMM模型盒子和球的例子,已知盒子与球的模型及取3次球以后球的颜色观测序列{红,白,红},需推测三次取球可能对应的盒子序列隐藏状态序列),...
  • 对于此示例,观察值是空格和字母,但是代码足够通用,可以与任何观察值序列隐藏状态一起使用。 下面讨论的所有概率将在日志空间中。 HMM的推论被实现为一种维特比算法(动态编程) 依存关系 Python 3.x load_...
  • 自然语言处理(八):经典序列模型HMM与CRF
  • 沿用上一节中HMM模型盒子和球的例子,我们使用前向算法计算HMM观测序列的概率。依次取3次球,得到球的颜色的观测序列:O={红,白,红}在第一个时刻取到的是红色...
  • 如图HMM模型,初始概率: 1,请列出所有可能输出序列的状态转移序列。 2,分别计算由每一个状态转移序列输出观察序列V 的概率 3,计算最有可能输出观察序列V 的状态转移序列 解析: 不合理之处还请批评指正,小弟...
  • 从本文开始,到了序列比对的第二部分,主要是介绍HMM以及其在序列比对中的基础应用。 前面八篇文章介绍了动态规划在序列比对中的基础应用。从本文开始,开始介绍HMM(隐马尔可夫模型)。 ###Markov链 首先我们先...
  • ICSC-HMM:用于变换不变时间序列分割的IBP耦合SPCM-CRP隐藏Markov模型网站: 作者:纳迪亚·菲格罗亚(Nadia Figueroa)(nadia.figueroafernandez AT epfl.ch) 注意:如果您仅对[1]中引入的协方差矩阵的不变变换...
  • 算法概述隐马尔科夫模型(Hidden Markov Model)是关于时序的概率模型,描述由一个隐含的马尔科夫链生成不可观测的状态序列,再由状态序列生成观测序列的过程。这种通过观测序列预测隐含的标记序列的问题叫做标注。下...
  • 详解MATLAB中HMM工具包中各个函数的使用方法,给出例子,并有详细注释 ...说明由转移矩阵混淆矩阵生成随机观察和隐藏序列、维特比算法(viterbi)、通过训练估计转移矩阵和混淆矩阵等函数的运用 大家一起学习吧~
  • 前言2 概率计算问题2.1 前向算法2.2 后向算法3 模型训练问题3.1 监督学习–最大似然估计2.2 Baum·welch算法4 序列预测问题4.1 维特比算法 1. 前言 在上一篇《一文读懂NLP之隐马尔科夫模型(HMM)详解加python实现...
  • 1. 模型简介 隐马尔科夫模型(Hidden Markov Model,以下简称HMM)是比较经典的机器学习模型了,主要用于时序数据建模,它在语言识别,自然语言处理,模式识别等领域得到广泛的应用。(1)状态变量 {y1,y2, ... ,yn...
  • hmm模型matlab代码高密度聚乙烯 隐马尔可夫模型参数估计的AntMarkov算法的HMM参数估计实现。 AntMarkov的实现在“ ...Mattila,“关于使用频谱和非负矩阵分解方法识别隐藏的马尔可夫模型”,2015年 [2
  • 占坑系列3 转载于:https://www.cnblogs.com/yelbosh/p/5791271.html
  • 隐马尔可夫模型HMM

    2020-12-19 23:54:06
    以下内容来自刘建平Pinard-博客园的学习笔记,总结如下:1 隐马尔可夫模型HMM隐马尔科夫模型(Hidden Markov Model,以下简称HMM)是比较经典的机器学习模型了,它在语言识别,自然语言处理,模式识别等领域得到广泛的...
  • 在深度学习的崛起,尤其是RNN、LSTM等神经网络序列模型的火热,HMM的地位有些下降。但是作为一个经典的模型,学习HMM的模型和对应算法,对咱们解决问题建模的能力提高以及算法思路的扩招还是很好的。 一. 一般常见的...
  • 时序模型:隐马尔科夫模型(HMM

    千次阅读 2022-02-06 20:25:09
    隐马尔科夫模型(hidden Markov model,HMM)描述由一个隐藏的马尔科夫链随机生成不可观测的状态随机序列,再由各个状态生成一个观测从而产生观测随机序列的过程。隐藏的马尔科夫链随机生成的状态的序列,称作状态...
  • 该代码已使用Smith-Waterman序列比对算法在数据集JUDD和NUSEF上进行了测试。 结果与本文报道的结果有所不同(见下文)。 但是,这些差异可能由以下原因解释: 在原始实现中,观察向量(可视单词的包)被归一化为总和...
  • 文章目录经典的序列模型(HMM与CRF) 经典的序列模型(HMM与CRF) HMM模型的输入和输出 HMM(Hidden Markov Model), 中文称作隐含马尔科夫模型, 因俄国数学家马尔可夫而得名. 它一般以文本序列数据为输入, 以该序列对应...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 3,771
精华内容 1,508
热门标签
关键字:

hmm 求隐藏序列