【机器学习】【条件随机场CRF-2】CRF的预测算法之维特比算法(viterbi alg) 详解 + 示例讲解 + Python实现
1.CRF的预测算法
条件随机场的预测算法是给定条件随机场P(Y|X)和输入序列(观测序列)x,求条件概率最大的输出序列(标记序列)y*,即对观测序列进行标注。条件随机场的预测算法是著名的维特比算法(Vitebi Algorthim)。
维特比算法在隐马尔科夫模型的预测算法中已经详细介绍和Python实现过,详见以前的博客:
【机器学习】【隐马尔可夫模型-4】维特比算法:算法详解+示例讲解+Python实现
2.CRF的预测算法之维特比算法
2.1维特比算法简介
维特比算法实际使用动态规划解CRF条件随机场的预测问题,即用动态规划(Dynamic Programming)求概率最大状态路径(最优路径)。这时一条路径对应一个状态序列。
根据动态规划原理,最优路径具有这样的特性:如果最优路径在时刻t通过节点i*t,那么这一路径从节点i*t到终点i*T的部分路径,对于从i*t到i*T的所有可能的部分来说,必须是最优的。
我们只需要从时刻t=1开始,递推地计算在时刻t状态为i的各条部分路径的最大概率,直至得到时刻t=T状态为i的各条路径的最大概率。时刻t=T的最大概率即为最优路径的概率P*,最优路径的终结点i*T也同时得到。
之后,为了找出最优路径的各个节点,从终结点i*T开始,由后向前逐步求得节点i*T-1,……,i*1,得到最优路径I*=(i*1, i*2, i*3,……,i*T),这就是维特比算法。
2.2CRF预测问题的维特比算法
在条件随机场预测问题中,CRF预测问题就成为了求非规范化概率最大的最优路径问题。
提高效率思想:
在CRF预测问题的维特比算法中,最终结果求得是最优路径,只需要计算非规范化概率,不必计算概率,可以大大提高效率。
条件随机场预测的维特比算法步骤:
输入:模型特征向量F(y, x)和权值向量w, 观测序列x=(x1, x2, ……,xn)
输出:最优路径y*=(y*1, y*2, ……,y*n)
(1)初始化位置1的各个标记j=1,2,……,m的非规范化概率
(2)递推计算,对i=2,3,……,n
(3)终止
(4)返回路径
注意理解:ψ保存每个节点的最大非规范化概率的前导节点,即当前节点的最优前节点,最优路径先已知最优终结点,然后根据最优终结点从ψ里面求出他的最优前前节点,依次求出y*n, y*n-1, ……,y*2, y*1
则Y*=(y*1, y*2, ……,y*n-1, y*n)T就是条件随机场预测问题的最优路径。
3.数学示例展示:CRF的预测算法之维特比算法
设有一标注问题:输入观测序列为X=(X1,X2,X3),输出标记序列为Y=(Y1,Y2,Y3),Y1,Y2,Y3取值于{1,2}.
假设特征t<k>,s<l>的对应的权值为λ<k>,μ<l>,公式如下所示:
这里只注明特征取值为1的条件,取值为0的条件省略,如下:
下同
请用维特比算法求给定的输入序列(观测序列)x对应的最有输出序列(标记序列)y*=(y*1, y*2, y*3)。
说明:t<k>是定义在边上的特征函数,称为转移特征,依赖于当前和前一个位置,s<l>是定义在节点上的特征函数,称为状态特征,依赖于当前位置。这部分内容属于:条件随机场的参数形式的知识。关于条件随机场的参数化形式,详见前面博客:点我。
示例中给的是条件随机场的参数化形式,我给出了对应的状态路径图,画在了纸上,人肉出品,哈哈,详见下图:
上图中给出了对t和s函数的理解,如果仔细看,应该很容易清楚其含义,然后就很容易地画出条件随机场的参数化形式对应的状态路径图~
下面给出维特比算法的数学求解过程,如果不懂,可以板砖儿扔过来~:
最后求得此示例的最优标记序列,即最优状态路径为Y*=(1,2,1)。
4.python实现CRF的预测算法之维特比算法
下面是展示数学过程的CRF预测问题的维特比算法的python实现,不是最终精简的代码,精简的代码,请见5节。
完全人肉出品,请详见:
4.1代码
# -*- coding: utf-8 -*-
"""
@author: 蔚蓝的天空tom
Talk is cheap, show me code
Aim:实现条件随机场预测问题的维特比算法
"""
import numpy as np
class CRF(object):
'''实现条件随机场预测问题的维特比算法
'''
def __init__(self, V, VW, E, EW):
'''
:param V:是定义在节点上的特征函数,称为状态特征
:param VW:是V对应的权值
:param E:是定义在边上的特征函数,称为转移特征
:param EW:是E对应的权值
'''
self.V = V #点分布表
self.VW = VW #点权值表
self.E = E #边分布表
self.EW = EW #边权值表
self.D = [] #Delta表,最大非规范化概率的局部状态路径概率
self.P = [] #Psi表,当前状态和最优前导状态的索引表s
self.BP = [] #BestPath,最优路径
return
def Viterbi(self):
'''
条件随机场预测问题的维特比算法,此算法一定要结合CRF参数化形式对应的状态路径图来理解,更容易理解.
'''
self.D = np.full(shape=(np.shape(self.V)), fill_value=.0)
self.P = np.full(shape=(np.shape(self.V)), fill_value=.0)
for i in range(np.shape(self.V)[0]):
#初始化
if 0 == i:
self.D[i] = np.multiply(self.V[i], self.VW[i])
self.P[i] = np.array([0, 0])
print('self.V[%d]='%i, self.V[i], 'self.VW[%d]='%i, self.VW[i], 'self.D[%d]='%i, self.D[i])
print('self.P:', self.P)
pass
#递推求解布局最优状态路径
else:
for y in range(np.shape(self.V)[1]): #delta[i][y=1,2...]
for l in range(np.shape(self.V)[1]): #V[i-1][l=1,2...]
delta = 0.0
delta += self.D[i-1, l] #前导状态的最优状态路径的概率
delta += self.E[i-1][l,y]*self.EW[i-1][l,y] #前导状态到当前状体的转移概率
delta += self.V[i,y]*self.VW[i,y] #当前状态的概率
print('(x%d,y=%d)-->(x%d,y=%d):%.2f + %.2f + %.2f='%(i-1, l, i, y, \
self.D[i-1, l], \
self.E[i-1][l,y]*self.EW[i-1][l,y], \
self.V[i,y]*self.VW[i,y]), delta)
if 0 == l or delta > self.D[i, y]:
self.D[i, y] = delta
self.P[i, y] = l
print('self.D[x%d,y=%d]=%.2f\n'%(i, y, self.D[i,y]))
print('self.Delta:\n', self.D)
print('self.Psi:\n', self.P)
#返回,得到所有的最优前导状态
N = np.shape(self.V)[0]
self.BP = np.full(shape=(N,), fill_value=0.0)
t_range = -1 * np.array(sorted(-1*np.arange(N)))
for t in t_range:
if N-1 == t:#得到最优状态
self.BP[t] = np.argmax(self.D[-1])
else: #得到最优前导状态
self.BP[t] = self.P[t+1, int(self.BP[t+1])]
#最优状态路径表现在存储的是状态的下标,我们执行存储值+1转换成示例中的状态值
#也可以不用转换,只要你能理解,self.BP中存储的0是状态1就可以~~~~
self.BP += 1
print('最优状态路径为:', self.BP)
return self.BP
def CRF_manual():
S = np.array([[1,1], #X1:S(Y1=1), S(Y1=2)
[1,1], #X2:S(Y2=1), S(Y2=2)
[1,1]]) #X3:S(Y3=1), S(Y3=1)
SW = np.array([[1.0, 0.5], #X1:SW(Y1=1), SW(Y1=2)
[0.8, 0.5], #X2:SW(Y2=1), SW(Y2=2)
[0.8, 0.5]])#X3:SW(Y3=1), SW(Y3=1)
E = np.array([[[1, 1], #Edge:Y1=1--->(Y2=1, Y2=2)
[1, 0]], #Edge:Y1=2--->(Y2=1, Y2=2)
[[0, 1], #Edge:Y2=1--->(Y3=1, Y3=2)
[1, 1]]])#Edge:Y2=2--->(Y3=1, Y3=2)
EW= np.array([[[0.6, 1], #EdgeW:Y1=1--->(Y2=1, Y2=2)
[1, 0.0]], #EdgeW:Y1=2--->(Y2=1, Y2=2)
[[0.0, 1], #EdgeW:Y2=1--->(Y3=1, Y3=2)
[1, 0.2]]])#EdgeW:Y2=2--->(Y3=1, Y3=2)
crf = CRF(S, SW, E, EW)
ret = crf.Viterbi()
print('最优状态路径为:', ret)
return
if __name__=='__main__':
CRF_manual()
4.2运行结果
会发现,运行结果展示的数学计算中间值,和上面的数学求解步骤中间值一模一样~~~~~,可以说明代码is ok~~
runfile('C:/Users/tom/CRF_vitebi.py', wdir='C:/Users/tom')
self.V[0]= [1 1] self.VW[0]= [ 1. 0.5] self.D[0]= [ 1. 0.5]
self.P: [[ 0. 0.]
[ 0. 0.]
[ 0. 0.]]
(x0,y=0)-->(x1,y=0):1.00 + 0.60 + 0.80= 2.4
(x0,y=1)-->(x1,y=0):0.50 + 1.00 + 0.80= 2.3
self.D[x1,y=0]=2.40
(x0,y=0)-->(x1,y=1):1.00 + 1.00 + 0.50= 2.5
(x0,y=1)-->(x1,y=1):0.50 + 0.00 + 0.50= 1.0
self.D[x1,y=1]=2.50
(x1,y=0)-->(x2,y=0):2.40 + 0.00 + 0.80= 3.2
(x1,y=1)-->(x2,y=0):2.50 + 1.00 + 0.80= 4.3
self.D[x2,y=0]=4.30
(x1,y=0)-->(x2,y=1):2.40 + 1.00 + 0.50= 3.9
(x1,y=1)-->(x2,y=1):2.50 + 0.20 + 0.50= 3.2
self.D[x2,y=1]=3.90
self.Delta:
[[ 1. 0.5]
[ 2.4 2.5]
[ 4.3 3.9]]
self.Psi:
[[ 0. 0.]
[ 0. 0.]
[ 1. 0.]]
最优状态路径为: [ 1. 2. 1.]
最优状态路径为: [ 1. 2. 1.]
5.精简后的python代码
5.1代码
# -*- coding: utf-8 -*-
"""
@author: 蔚蓝的天空tom
Talk is cheap, show me code
Aim:实现条件随机场预测问题的维特比算法
"""
import numpy as np
class CRF(object):
'''实现条件随机场预测问题的维特比算法
'''
def __init__(self, V, VW, E, EW):
'''
:param V:是定义在节点上的特征函数,称为状态特征
:param VW:是V对应的权值
:param E:是定义在边上的特征函数,称为转移特征
:param EW:是E对应的权值
'''
self.V = V #点分布表
self.VW = VW #点权值表
self.E = E #边分布表
self.EW = EW #边权值表
self.D = [] #Delta表,最大非规范化概率的局部状态路径概率
self.P = [] #Psi表,当前状态和最优前导状态的索引表s
self.BP = [] #BestPath,最优路径
return
def Viterbi(self):
'''
条件随机场预测问题的维特比算法,此算法一定要结合CRF参数化形式对应的状态路径图来理解,更容易理解.
'''
self.D = np.full(shape=(np.shape(self.V)), fill_value=.0)
self.P = np.full(shape=(np.shape(self.V)), fill_value=.0)
for i in range(np.shape(self.V)[0]):
#初始化
if 0 == i:
self.D[i] = np.multiply(self.V[i], self.VW[i])
self.P[i] = np.array([0, 0])
#递推求解布局最优状态路径
else:
for y in range(np.shape(self.V)[1]): #delta[i][y=1,2...]
for l in range(np.shape(self.V)[1]): #V[i-1][l=1,2...]
#前导状态的最优状态路径的概率 + 前导状态到当前状体的转移概率 + 当前状态的概率
delta = self.D[i-1, l] + self.E[i-1][l,y]*self.EW[i-1][l,y] + self.V[i,y]*self.VW[i,y] #
if 0 == l or delta > self.D[i, y]:
self.D[i, y], self.P[i, y] = delta, l
#返回,得到所有的最优前导状态
N = np.shape(self.V)[0]
self.BP = np.full(shape=(N,), fill_value=0.0)
t_range = -1 * np.array(sorted(-1*np.arange(N)))
for t in t_range:
if N-1 == t:#得到最优状态
self.BP[t] = np.argmax(self.D[-1])
else: #得到最优前导状态
self.BP[t] = self.P[t+1, int(self.BP[t+1])]
#最优状态路径表现在存储的是状态的下标,我们执行存储值+1转换成示例中的状态值
#也可以不用转换,只要你能理解,self.BP中存储的0是状态1就可以~~~~
self.BP += 1
return self.BP
def CRF_manual():
S = np.array([[1,1], #X1:S(Y1=1), S(Y1=2)
[1,1], #X2:S(Y2=1), S(Y2=2)
[1,1]]) #X3:S(Y3=1), S(Y3=1)
SW = np.array([[1.0, 0.5], #X1:SW(Y1=1), SW(Y1=2)
[0.8, 0.5], #X2:SW(Y2=1), SW(Y2=2)
[0.8, 0.5]])#X3:SW(Y3=1), SW(Y3=1)
E = np.array([[[1, 1], #Edge:Y1=1--->(Y2=1, Y2=2)
[1, 0]], #Edge:Y1=2--->(Y2=1, Y2=2)
[[0, 1], #Edge:Y2=1--->(Y3=1, Y3=2)
[1, 1]]])#Edge:Y2=2--->(Y3=1, Y3=2)
EW= np.array([[[0.6, 1], #EdgeW:Y1=1--->(Y2=1, Y2=2)
[1, 0.0]], #EdgeW:Y1=2--->(Y2=1, Y2=2)
[[0.0, 1], #EdgeW:Y2=1--->(Y3=1, Y3=2)
[1, 0.2]]])#EdgeW:Y2=2--->(Y3=1, Y3=2)
crf = CRF(S, SW, E, EW)
ret = crf.Viterbi()
print('最优状态路径为:', ret)
return
if __name__=='__main__':
CRF_manual()
5.2运行结果
runfile('C:/Users/tom/CRF_vitebi_imp.py', wdir='C:/Users/tom')
最优状态路径为: [ 1. 2. 1.]
写完了,条件随机场先到此结束,后续再更新。
---------------------
作者:CV_ML_DP
来源:CSDN
原文:https://blog.csdn.net/u012421852/article/details/80287588
版权声明:本文为博主原创文章,转载请附上博文链接!
【机器学习】【条件随机场CRF-2】CRF的预测算法之维特比算法(viterbi alg) 详解 + 示例讲解 + Python实现的更多相关文章
- 条件随机场理论分析CRF(Conditional Random Field)
- 条件随机场(conditional random field,CRF)模型初探
0. 引言 0x1:为什么会有条件随机场?它解决了什么问题? 在开始学习CRF条件随机场之前,我们需要先了解一下这个算法的来龙去脉,它是在什么情况下被提出的,是从哪个算法演进而来的,它又解决了哪些问题 ...
- CRF条件随机场简介
CRF(Conditional Random Field) 条件随机场是近几年自然语言处理领域常用的算法之一,常用于句法分析.命名实体识别.词性标注等.在我看来,CRF就像一个反向的隐马尔可夫模型(H ...
- 标注-CRF条件随机场
1 概率无向图模型1.1 模型定义1.2 因子分解2 条件随机场的定义2.2 条件随机场的参数化形式2.3 条件随机场的简化形式2.4 条件随机场的矩阵形式 3 条件随机场的概率计算问题 3.1 前向 ...
- 条件随机场之CRF++源码详解-训练
上篇的CRF++源码阅读中, 我们看到CRF++如何处理样本以及如何构造特征.本篇文章将继续探讨CRF++的源码,并且本篇文章将是整个系列的重点,会介绍条件随机场中如何构造无向图.前向后向算法.如何计 ...
- 条件随机场(CRF)理论及应用
http://x-algo.cn/index.php/2016/02/15/conditional-random-field-crf-theory-and-implementation/ 条件随机场( ...
- CRF条件随机场简介<转>
转自http://hi.baidu.com/hehehehello/item/3b0d1f8ba1c2e5c698255f89 CRF(Conditional Random Field) 条件随机场是 ...
- 【算法】BILSTM+CRF中的条件随机场
BILSTM+CRF中的条件随机场 tensorflow中crf关键的两个函数是训练函数tf.contrib.crf.crf_log_likelihood和解码函数tf.contrib.crf.vit ...
- Viterbi(维特比)算法在CRF(条件随机场)中是如何起作用的?
之前我们介绍过BERT+CRF来进行命名实体识别,并对其中的BERT和CRF的概念和作用做了相关的介绍,然对于CRF中的最优的标签序列的计算原理,我们只提到了维特比算法,并没有做进一步的解释,本文将对 ...
随机推荐
- web前端学习(四)JavaScript学习笔记部分(2)-- JavaScript语法详解
2.1.Javascript语法-运算符(1) 复数运算符 %取余 ++ -- 赋值运算符 += -= *= /= %= 字符串操作 <!DOCTYPE html> <html la ...
- jquery源码学习(二)——jquery中的变量
jquery在 21-93 行提供了变量 var // A central reference to the root jQuery(document) rootjQuery, // The defe ...
- 从0开始学习 GitHub 系列之「05.Git 进阶」
关于 Git 相信大家看了之前一系列的文章已经初步会使用了, 但是关于Git还有很多知识与技巧是你不知道的,今天就来给大家介绍下一些 Git 进阶的知识. 1. 用户名和邮箱 我们知道我们进行的每一次 ...
- django1.11启动错误
错误信息: 复制代码 Unhandled exception in thread started by <function check_errors..wrapper at 0x10f03b8c ...
- PHP学习(数据类型)
PHP中,支持8种原始类型,其中包括四种标量类型.两种复合类型和两种特殊类型.PHP是一门松散类型的语言,不必向PHP声明变量的数据类型,PHP会自动把变量转换为自动的数据类型,一定程度降低了学习PH ...
- bash 小技巧
CTRL-R (reverse find),按下之后敲几个字母就能在最近打过的命令里搜索.
- SQL优化经验总结34条
SQL优化经验总结34条 我们要做到不但会写SQL,还要做到写出性能优良的SQL,以下为笔者学习.摘录.并汇总部分资料与大家分享! (1) 选择最有效率的表名顺序(只在基于规则的优化器中有效): OR ...
- 值得研究的J2EE开源项目推荐
导读:笔者在学习J2EE的过程中发现了一些很有用,而且很值得学习的开源项目,在此推荐给大家. 关键词:J2EE 开源项目 J2SE JBoss SOA EJB 这篇文章写在我研究J2SE.J2EE ...
- day4new-转自金角大王
Python之路,Day4 - Python基础4 (new版) 本节内容 迭代器&生成器 装饰器 Json & pickle 数据序列化 软件目录结构规范 作业:ATM项目开发 ...
- php 获取客户端的ip、地理信息、浏览器信息、本地真实ip
转自:http://www.blhere.com/948.html 这是非常实用的php常用类.获取客户端的ip.地理信息.浏览器信息.本地真实ip 1234567891011121314151617 ...