NLP经典算法复现!CRF原理及实现代码
Datawhale
作者:丁媛媛,Datawhale优秀学习者
寄语:本文先对马尔可夫过程及隐马尔可夫算法进行了简单的介绍;然后,对条件随机场的定义及其三种形式进行了详细推导;最后,介绍了条件随机场的三大问题,同时针对预测问题给出了代码实践。
条件随机场(conditional random fields,简称 CRF,或CRFs),是一种判别式概率模型,常用于标注或分析序列资料,如自然语言文字或是生物序列。
条件随机场是条件概率分布模型P(Y|X),表示的是给定一组输入随机变量X的条件下另一组输出随机变量Y的马尔可夫随机场,也就是说CRF的特点是假设输出随机变量构成马尔可夫随机场。
知识框架
马尔可夫过程
定义:假设一个随机过程中,
时刻的状态的条件发布,只与其前一状态 相关,即:
则将其称为马尔可夫过程。
隐马尔可夫算法(HMM)
1、定义
隐马尔可夫算法是对含有未知参数(隐状态)的马尔可夫链进行建模的生成模型,如下图所示:
在隐马尔科夫模型中,包含隐状态和观察状态,隐状态
对于观察者而言是不可见的,而观察状态对于观察者而言是可见的。隐状态间存在转移概率,隐状态到对应的观察状态间存在输出概率。
2、假设
假设隐状态
的状态满足马尔可夫过程,时刻的状态的条件分布,仅与其前一个状态相关,即:
假设观测序列中各个状态仅取决于它所对应的隐状态,即:
3、存在问题
在序列标注问题中,隐状态(标注)不仅和单个观测状态相关,还和观察序列的长度、上下文等信息相关。例如词性标注问题中,一个词被标注为动词还是名词,不仅与它本身以及它前一个词的标注有关,还依赖于上下文中的其他词。
条件随机场
以线性链条件随机场为例
1、定义
给定均为线性链表示的随机变量序列,若在给随机变量序列X的条件下,随机变量序列Y的条件概率分布P(Y|X)构成条件随机场,即满足马尔可夫性:
则称为
为线性链条件随机场。
通过去除了隐马尔科夫算法中的观测状态相互独立假设,使算法在计算当前隐状态
时,会考虑整个观测序列,从而获得更高的表达能力,并进行全局归一化解决标注偏置问题。
1)参数化形式
其中:
为归一化因子,是在全局范围进行归一化,枚举了整个隐状态序列的全部可能,从而解决了局部归一化带来的标注偏置问题。
为定义在边上的特征函数,转移特征,依赖于前一个和当前位置为定义在节点上的特征函数,状态特征,依赖于当前位置。
2)简化形式
因为条件随机场中同一特征在各个位置都有定义,所以可以对同一个特征在各个位置求和,将局部特征函数转化为一个全局特征函数,这样就可以将条件随机场写成权值向量和特征向量的内积形式,即条件随机场的简化形式。
step 1 将转移特征和状态特征及其权值用统一的符号表示,设有
个转移特征,个状态特征,,记
step 2 对转移与状态特征在各个位置
求和,记作
step 3 将
和 用统一的权重表示,记作
step 4 转化后的条件随机场可表示为:
step 5 若
表示权重向量:以 表示特征向量,即
则,条件随机场写成内积形式为:
3)矩阵形式
2、基本问题
条件随机场包含概率计算问题、学习问题和预测问题三个问题。
概率计算问题:已知模型的所有参数,计算观测序列Y出现的概率,常用方法:前向和后向算法;
学习问题:已知观测序列Y,求解使得该观测序列概率最大的模型参数,包括隐状态序列、隐状态间的转移概率分布和从隐状态到观测状态的概率分布,常用方法:Baum-Wehch算法;
预测问题:一直模型所有参数和观测序列Y,计算最可能的隐状态序列X,常用算法:维特比算法。
1)概率计算问题
给定条件随机场
,输入序列 和 输出序列; 计算条件概率
计算相应的数学期望问题;
前向-后向算法
step 1 前向计算;对观测序列x的每个位置
,定义一个阶矩阵(m为标记Y_i取值的个数),对每个指标,定义前向向量 ,则递推公式:
其中,
否则
step 2 后向计算;对每个指标
,定义前向向量,则递推公式:
step 3
step 4 概率计算;所以,标注序列在位置
是标注的条件概率为:
其中,
step 5 期望值计算;通过利用前向-后向向量,计算特征函数关于联合概率分布
和 条件概率分布 的数学期望,即特征函数 关于条件概率分布 的数学期望:
其中:
2)学习问题
这里主要介绍一下 BFGS 算法的思路。
输入:特征函数
:经验分布 ;
输出:最优参数值
,最优模型。
选定初始点
, 取 为正定对称矩阵,;计算
,若 ,则停止计算,否则转 (3) ;利用
计算;一维搜索:求
使得
设
计算
, 若, 则停止计算;否则,利用下面公式计算 :
令
,转步骤(3);
3)预测问题
对于预测问题,常用的方法是维特比算法,其思路如下:
输入:模型特征向量
和权重向量,输入序列(观测序列);
输出:条件概率最大的输出序列(标记序列)
,也就是最优路径;
初始化
递推,对
终止
返回路径
求得最优路径
案例:利用维特比算法计算给定输入序列
对应的最优输出序列:
初始化
递推,对
终止
返回路径
求得最优路径
代码实现如下:
import numpy as npclass 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表,当前状态和最优前导状态的索引表sself.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.0delta += 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] = deltaself.P[i, y] = lprint('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 += 1print('最优状态路径为:', self.BP)return self.BPdef 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)returnif __name__=='__main__':CRF_manual()
输出如下图:
后台回复 社区 和更多优秀学习者一起成长
“为沉迷学习点赞↓
NLP经典算法复现!CRF原理及实现代码相关推荐
- NLP经典模型复现之开宗明义
文章目录 1. 为什么要写这个专栏 2. 专栏的主要内容 3. 阅读论文的正确姿势 1. 为什么要写这个专栏 大家好,我是herosunly,从985院校硕士毕业,现担任算法研究员一职.CSDN博 ...
- 【综合评价分析】熵权算法确定权重 原理+完整MATLAB代码+详细注释+操作实列
[综合评价分析]熵权算法确定权重 原理+完整MATLAB代码+详细注释+操作实列 文章目录 1. 熵权法确定指标权重 (1)构造评价矩阵 Ymn (2)评价矩阵标准化处理 (3)计算指标信息熵值 Mj ...
- 【GA算法】遗传算法原理及其Matlab代码
翻阅几篇遗传算法的文章,这篇通俗易懂,且逻辑清楚,最适合入门,不用担心遗漏关键点. 遗传算法,先选择,交叉和变异顺序可更换. 轮盘赌部分,参考了另外一篇文章的解释. 此外,还有一些有价值的文献: 选择 ...
- 视觉BEV经典算法:LSS详解与代码
本文介绍一篇视觉BEV经典算法:LSS,论文收录于 ECCV2020,本文通过显示的进行图像离散深度估计完成目标语义分割,重点是如何将二维图像特征转换成BEV特征. 项目链接:https://nv-t ...
- C语言经典算法 - 双色河内塔的代码
把内容过程常用的内容片段记录起来,如下的内容内容是关于C语言经典算法 - 双色河内塔的内容,希望能对各位朋友有所好处. #include <stdio.h> void hanoi(int ...
- 经典算法复现!(条件随机场)CRF原理及实现代码
Datawhale 作者:丁媛媛,Datawhale优秀学习者 寄语:本文先对马尔可夫过程及隐马尔可夫算法进行了简单的介绍:然后,对条件随机场的定义及其三种形式进行了详细推导:最后,介绍了条件随机场的 ...
- 【图解经典算法题】如何用一行代码解决约瑟夫环问题
约瑟夫环问题算是很经典的题了,估计大家都听说过,然后我就在一次笔试中遇到了,下面我就用 3 种方法来详细讲解一下这道题,最后一种方法学了之后保证让你可以让你装逼. 问题描述:编号为 1-N 的 N 个 ...
- mopso算法代码程序_JAVA程序员的必杀技,面试中常考的8个经典算法题,过程精妙,代码精炼...
总有一些题,超越了岁月,即便是经过了新框架的层层迭代,它依然散发着令人回味无穷的味道.下面的几个笔试题目,是JAVA面试中经常遇见的,大家一定要牢记于心,可别复习到了到时候又说不出来.我就吃过这种亏, ...
- 面绘制经典算法:MarchingCube实现(C++ OpenGl代码篇)
1.原始代码 #define GLUT_DISABLE_ATEXIT_HACK #include <stdlib.h> #include <string.h> #include ...
最新文章
- vue实例没有挂载到html上,vue 源码学习 - 实例挂载
- 《计算机科学导论》一2.3 非位置化数字系统
- crc16算法php实现,关于实现CRC16校验算法的两个函数
- 平移不变性:Translation Invariance 与 平移同变性:Translation equivariance
- bp神经网络_BP 神经网络驱动的手写体数字识别软件 EasyOCR
- android app 主界面,android ViewPager实现App主界面Tab菜单页面切换和点击事件
- 1.0jpa 2.0_JPA 2.1实体图–第1部分:命名实体图
- java for foreach 效率_Java中LinkedList的fori和foreach效率比较
- 黑马出品代码生成器,超级好用,推荐
- C语言程序设计double,C语言中double类型数据占字节数为
- 叩丁狼开发工程师:SSR服务架构特点分析
- ps常见问题集锦问答形式
- 微信小程序开发者工具平台+Hbuilder开发平台下载
- mobilenet cpu 加速_UP手游加速器苹果版下载安装-UP手游加速器iOS苹果版下载
- special effects - 樱花飘落背景特效
- 使用WInDynamicDesktop自定义上传图库生成主题教程
- android N编译
- 什么是六类网线和超六类网线?
- 隐私泄露防不胜防,真的没有办法了吗?
- Android GPU呈现模式分析功能,手机流畅度。仅供参考
热门文章
- php中类和对象的操作
- 题目 1477:【蓝桥杯】【入门题】字符串输入输出函数
- 如何读取Excel表格中不同sheet表的同一位置单元格数据,并绘制条形图呢?
- 赠书 | 图解机器学习算法,看这文就够了!
- 上市之后,青云存储平台 QingStor 也要“进军”云原生
- 2020 ACM Fellows 名单出炉,13 名华人入选,7 名来自国内!
- 98年“后浪”科学家,首次挑战图片翻转不变性假设,一作拿下CVPR最佳论文提名​...
- 高文、张钹、杨强隔空论道:AI精度与隐私的博弈
- 44岁的微软如何刷新未来?
- 谷歌新研究:基于数据共享的神经网络快速训练方法