【机器学习】【条件随机场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中的最优的标签序列的计算原理,我们只提到了维特比算法,并没有做进一步的解释,本文将对 ...
随机推荐
- LintCode_133 最长单词
题目 给一个词典,找出其中所有最长的单词. 样例 在词典 { "dog", "google", "facebook", "inte ...
- httpserver实现简单的上下文
package main import ( "net/http" "com.jtthink.net/myhttpserver/core" ) type MyHa ...
- C++ 实现十大排序算法
教你手撕排序,这里有一个概念就是稳定排序.假定在待排序的记录序列中,存在多个具有相同的关键字的记录,若经过排序,这些记录的相对次序保持不变,即在原序列中,r[i]=r[j],且r[i]在r[j]之前, ...
- springboot自定义错误页面(转)
方法一:Spring Boot 将所有的错误默认映射到/error, 实现ErrorController @Controller @RequestMapping(value = "error ...
- Leetcode680.Valid Palindrome II验证回文字符串2
给定一个非空字符串 s,最多删除一个字符.判断是否能成为回文字符串. 示例 1: 输入: "aba" 输出: True 示例 2: 输入: "abca" 输出: ...
- 【难为听】weex-ui
eslint 不喜欢,但是确实规范了代码,同古代统一货币一样,有无穷的意义.故喜欢 weex-ui在项目中的使用方法 npm install -g weex-toolkit@latest weex c ...
- 【机器学习PAI实战】—— 玩转人工智能之美食推荐
前言 在生活中,我们经常给朋友推荐一些自己喜欢的东西,也时常接受别人的推荐.怎么能保证推荐的电影或者美食就是朋友喜欢的呢?一般来说,你们两个人经常对同一个电影或者美食感兴趣,那么你喜欢的东西就很大程度 ...
- qt绘制渐变区域
// 原理:通过点到线,然后叠加成区域.同理,可使用其他图形 QPainter painter(m_pWidget); QLinearGradient linearGradient(QPointF(, ...
- CSS中的margin和padding的用法和区别
在CSS中margin是指从自身边框到另一个容器边框之间的距离,就是容器外距离. 语法结构 (1)padding-left:10px; 左内边距 (2)padding-right:10px; 右内边距 ...
- R语言因子
R语言因子 因子是它们用于将数据进行分类并将其存储为级别的数据对象.它们可以同时存储字符串和整数.它们在具有唯一值的有限数目的列是有用的. 例如,"male, "Female&qu ...