NLP经典算法复现!CRF原理及实现代码

CRF算法(Conditional Random Fields)揭秘 ​​条件随机场(即CRF)可看成最大熵模型的序列版本(sequence version),这意味着它们都是判别式模型。CRF与HMM对比,除了后者是生成式模型之外,二者另一个重要的不同点是,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 算法的思路。

输入:特征函数 :经验分布 ;

输出:最优参数值 ,最优模型。

  1. 选定初始点 , 取 为正定对称矩阵,;

  2. 计算 ,若 ,则停止计算,否则转 (3) ;

  3. 利用 计算;

  4. 一维搜索:求 使得

  1. 设

  2. 计算,若, 则停止计算;否则,利用下面公式计算 :

     令 ,转步骤(3);

3)预测问题

对于预测问题,常用的方法是维特比算法,其思路如下:

输入:模型特征向量 和权重向量,输入序列(观测序列);

输出:条件概率最大的输出序列(标记序列),也就是最优路径;

  1. 初始化

  1. 递推,对

  1. 终止

  1. 返回路径

    求得最优路径

案例:利用维特比算法计算给定输入序列 对应的最优输出序列:

  1. 初始化

  1. 递推,对

  1. 终止

  1. 返回路径

求得最优路径

代码实现如下:

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()

输出如下图:

 欢迎扫码关注:

NLP入门(八)使用CRF++实现命名实体识别(NER) CRF与NER简介   CRF,英文全称为conditional random field, 中文名为条件随机场,是给定一组输入随机变量条件下另一组输出随机变量的条件概率分布模型,其特点是假设输出随机变量构成马尔可夫(Markov)随机场。   较为简单的条件随机场是定义在线性链上的条件随机场,称为线性链条件随机场(linear chain conditional random field). 线... 阅读详情

相关推荐

基于条件随机场模型的中文分词实现(Python中文分词)

1. 引言 在中文分词领域,基于字标注的方法得到广泛应用,通过字标注分词问题可转换为序列标注问题,现在分词效果较好且常用的是基于条件随机场(CRFs)的标注模型。其模型思想是,条件随机场模型对应一个无向图 ,,Y中的元素与无向图的顶点一一对应。在条件X下,随机变量的条件概率分布符合图的马尔科夫性质,即可称当前是一个条件随机场。条件随机场模型用于在给定需要标记的观察序列的条件下,计算整个编辑序列的联合概率分布,求解出句子中字的标记序列的联合概率分布,从而实现分词。 2. 相关工作 本次...

admiz的博客 2737

CRF算法

一、概念 1.定义 条件随机场:是给定一组输入随机变量条件下,另一组输出随机变量的条件概率分布模型。 2.特点 假设输出随机变量构成马尔科夫随机场。 参考: 1.https://spaces.ac.cn/archives/5542/comment-page-1 2.https://www.zhihu.com/question/35866596/answer/236886066 ...

woshiliulei0的专栏 5731

PyTorch tutorial - BiLSTM CRF 代码解析

本文主要对PyTorch的tutorial之一,Advanced: Making Dynamic Decisions and the Bi-LSTM CRF,进行详细解读,行文顺序上,首先说明一下前面几个辅助函数的作用,然后主体按照Run training的运行顺序进行。(以下删除了原代码注释,可回tutorial中查看) def argmax(vec): _, idx = torch.m...

Ono_online的博客 1310

bp算法和nlp算法_NLP经典算法复现!CRF原理及实现代码

条件随机场(conditional random fields,简称 CRF,或CRFs),是一种判别式概率模型,常用于标注或分析序列资料,如自然语言文字或是生物序列。条件随机场是条件概率分布模型P(Y|X),表示的是给定一组输入随机变量X的条件下另一组输出随机变量Y的马尔可夫随机场,也就是说CRF的特点是假设输出随机变量构成马尔可夫随机场。知识框架马尔可夫过程定义:假设一个随机过程中,时刻的状...

weixin_34049581的博客 374

NLP损失函数实战指南:从交叉熵到CRF的深度解析

损失函数是NLP模型训练的数学基石,本质是将任务目标转化为可优化的概率建模问题。其设计遵循‘任务类型→输出结构→依赖关系→错误代价’的逻辑链:分类任务依赖交叉熵实现置信度校准,序列标注需CRF建模标签转移约束,生成任务则须通过label smoothing缓解过拟合、结合length normalization抑制长度偏差。这些技术不仅影响收敛稳定性与最终指标,更深层决定模型对噪声、长程依赖和领域偏移的鲁棒性。本文聚焦NLP典型场景,结合手写推导、梯度可视化与真实调试案例,系统拆解损失函数的原理、陷阱与工程

weixin_34343000的博客 418

BERT+BiLSTM+CRF实现中文命名实体识别:从原理到代码实战

命名实体识别是自然语言处理中的基础序列标注任务,目标是识别文本中的人名、地名、组织名等实体边界与类别。传统方法依赖特征工程,而深度学习时代,预训练模型与序列建模的结合成为主流方案。BERT作为预训练语言模型,能够为每个字符生成富含上下文语义的动态表示;BiLSTM通过双向循环结构进一步捕捉序列的局部依赖与顺序信息;CRF层则在全局范围内对标签转移进行约束,确保输出符合BIO标注规则。这一三层架构分工明确,既继承了预训练模型的语义优势,又弥补了独立分类忽略标签依赖的缺陷。在实际工程中,该方案广泛应用于信息抽取

weixin_29061465的博客 272

经典算法复现!(条件随机场)CRF原理及实现代码

Datawhale作者:丁媛媛,Datawhale优秀学习者寄语:本文先对马尔可夫过程及隐马尔可夫算法进行了简单的介绍;然后,对条件随机场的定义及其三种形式进行了详细推导;最后,介绍...

fengdu78的博客 7856

南开NLP期末大作业复盘:从样例复现到ACL论文实战全流程指南

自然语言处理是人工智能的核心方向之一,而论文复现是深入理解NLP模型原理与工程实现的关键手段。从基础文本分类到序列标注,再到预训练模型微调,不同任务对应着差异化的模型设计思路。以ACL经典论文为例,TextCNN通过卷积核捕捉局部n-gram特征,BiLSTM-CRF则结合双向长短期记忆网络与条件随机场实现全局标签约束,而BERT微调展示了预训练模型在下游任务中的强大迁移能力。在实际课程项目中,复现不仅是跑通代码,更需理解数据处理、训练调参、效果评估等全流程。本文基于一篇南开大学NLP期末大作业的完整复盘,

weixin_33610780的博客 354

一步步解读pytorch实现BiLSTM CRF代码

pytorch实现BiLSTM+CRF ​ 网上很多教程都是基于pytorch官网例子进行的解读,所以我就决定看懂官网例子后自己再进行复现,这一篇是我对于官方代码的详细解读。 理解LSTM 参考:http://colah.github.io/posts/2015-08-Understanding-LSTMs/ 这一篇英文的LSTM文章写得真的很好,看了一遍以后就很轻松的捡起了遗忘的知识点 ...

difend的博客 1万+

中文NLP资源包实战:从源代码复现到二次开发

自然语言处理是人工智能领域的重要方向,而中文NLP因语言特点与英文存在显著差异,其中分词、词性标注、命名实体识别等任务构成了技术基础。面对一份包含源代码和实验数据的NLP资源包,学习者往往不知从何入手。理解资源包目录结构、掌握数据流与模型流、复现训练流程,是高效学习的关键。实验数据积累不易,合理划分训练集、验证集与测试集,并通过同义词替换、回译等方式扩增数据,能提升模型效果。复现过程中常遇到编码错误、依赖版本漂移、显存溢出等问题,需要针对性解决。从传统模型到预训练模型,二次开发可结合真实场景将现有代码改造成

weixin_29057695的博客 234

BiLSTM+CRF命名实体识别实战:中文NER原理与代码详解

序列标注是自然语言处理中的核心任务,命名实体识别(NER)作为其典型应用,在信息抽取、知识图谱等领域至关重要。传统方法依赖手工特征,而深度学习模型如BiLSTM能自动学习上下文特征,但缺乏对标签依赖关系的建模。CRF层通过转移矩阵约束标签序列的合法性,解决了纯BiLSTM输出不合规标签的问题。BiLSTM+CRF结合两者优势,在中文NER、小规模数据等场景下兼具高准确率与可解释性,成为教学实践和工程落地的经典方案。本文从数据准备、模型原理到PyTorch实现,详细拆解了BIO标注、动态padding、维特比

weixin_29038303的博客 256

命名实体识别完全攻略:基于PKU-TANGENT nlp-tutorial的LSTM-CRF实现

命名实体识别(NER)是自然语言处理(NLP)中的关键任务,它能够从文本中识别出具有特定意义的实体,如人名、地名、组织机构名等。本教程将带你通过PKU-TANGENT的nlp-tutorial项目,快速掌握基于LSTM-CRF的命名实体识别技术,即使你是NLP领域的新手也能轻松上手! ## 📋 什么是命名实体识别? 命名实体识别是NLP中的结构预测任务,属于序列标注问题的一种。它的核心目标是

gitblog_01005的博客 814

本地AI助手部署指南:DeepSeek Harness与Ollama集成实践

AI Agent作为当前人工智能领域的热门技术,通过模拟人类决策过程,能够自主规划、调用工具并执行复杂任务。其核心原理在于将大语言模型的推理能力与外部工具API相结合,形成可闭环的工作流。这种技术架构的价值在于显著提升了AI系统的实用性和自动化水平,使其从单纯的对话工具转变为能够解决实际问题的智能助手。在应用场景上,AI Agent广泛应用于代码生成、数据分析、自动化办公等领域。本文聚焦于如何通过DeepSeek Harness平台与Ollama本地模型的集成,实现隐私安全、离线可用的AI助手部署方案,特别

dengjuanshou7445的博客 476

【NLP 38、实践 ⑨ NER 命名实体识别任务 LSTM + CRF 实现】

数据加载。

m0_73983707的博客 1756

ADSP-21565的SigmaStudio图形化编程实战:从FW工程改造到音频通道打通

本文详细介绍了如何将ADSP-21569的SigmaStudio图形化编程固件工程改造,以适配ADSP-21565的纯片内SRAM内存架构。通过修改内存映射和链接文件,打通了音频输出通道,并成功利用SigmaStudio进行图形化编程,实现了从白噪声生成到音频输出的完整验证流程。

weixin_29169505的博客 381

不到200块!手把手教你用ZYNQ7010和AD9363攒一台自己的开源SDR硬件(附BOM清单)

本文详细介绍了如何用不到200元的预算,基于ZYNQ7010 FPGA和AD9363射频芯片打造一台功能完备的开源SDR硬件平台。从核心组件选型、PCB设计到焊接调试,提供全流程实战指南,特别适合预算有限的硬件爱好者和创客群体探索无线通信世界。

weixin_26854829的博客 483

从NLP复习笔记到实战项目:如何用Python复现宗成庆老师课程中的经典算法(附代码)

本文详细解析了如何用Python复现宗成庆教授《自然语言处理》课程中的经典算法,涵盖统计语言模型、序列标注、文本表示等核心技术。通过完整的代码实现和性能对比,帮助开发者从理论快速过渡到实战,提升自然语言处理(NLP)项目的开发能力。

weixin_29066781的博客 151

从空调温控到信号降噪:一阶RC低通滤波器在Arduino和STM32上的C语言实现指南

本文详细介绍了如何在Arduino和STM32平台上使用C语言实现一阶RC低通滤波器,涵盖从基础理论到实际应用的完整流程。通过具体代码示例和优化技巧,帮助开发者有效处理传感器噪声、信号平滑等问题,提升嵌入式系统的信号处理能力。

weixin_30565199的博客 502

NLP 面试宝典

一、动机篇1.1 什么是文本摘要?1.2 文本摘要技术有哪些类型?二、抽取式摘要篇2.1 抽取式摘要是怎么做的?2.1.1 句子重要性评估算法有哪些?2.1.2 基于约束的摘要生成方法有哪些?2.1.3 TextTeaser算法是怎么抽取摘要的?2.1.4 TextRank算法是怎么抽取摘要的?2.2 抽取式摘要的可读性问题是什么?三、压缩式摘要篇3.1 压缩式摘要是怎么做的?四、生成式摘要篇4.1 生成式摘要是怎么做的?4.2 生成式摘要存在哪些问题?

weixin_43520816的博客 1508

STM32F103C8T6+TB6612驱动直流电机全攻略(附PWM调速代码)

本文提供了一份基于STM32F103C8T6微控制器和TB6612驱动模块的直流电机驱动完整解决方案。详细解析了硬件连接、STM32CubeMX配置、HAL库驱动代码编写,并附带了PWM调速代码实现。内容涵盖从基础原理到实战调试的全过程,旨在帮助开发者快速构建稳定、可精准调速的电机控制系统,适用于智能车、机器人等嵌入式项目。

weixin_29181861的博客 586

csp-j/s

CSP-J/S 是中国计算机学会(CCF)主办的 ‌‌(Certified Software Professional Junior/Senior),是信息学奥赛(NOI)体系的入门级选拔考试,也是国内最具权威性的青少年编程能力认证之一。

gxyxxrYYDS的博客 2033

【传知代码】命名实体识别(论文复现)

在自然语言处理(NLP)领域,实体识别任务(Named Entity Recognition,简称NER)被视为一个核心任务,其主要目的是从文本资料中进行实体的识别和分类命名。命名实体一般都是由专有名词组成的,例如人名,地名和组织名。下面的图示展示了一个基础的实体提取任务,该任务从句子中提取了阿里巴巴(组织名)、马云(人名)以及杭州(地名)这三个不同的实体:NER 的主要目标是找到文本中有意义的实体,并将其归类到预定义的类别中。以下是一些常见的类别:人名(Person):例如“乔布斯”、“马云”。

ztK63LrD的博客 1778

动态规划之【树形DP】第3课:树形DP应用案例实践2

动态规划之【树形DP】第3课:树形DP应用案例实践2

王老师青少年编程 769

自然语言处理(NLP)的系统学习路径规划

入门后立即实践:1周内跑通第一个情感分析项目,比读3本书更重要。

HappyAcmen 1504

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

上一篇: 优化问题都需要哪些数学基础
下一篇: 10 大受欢迎的全球顶级编程语言与薪资水平
机器学习算法那些事
博客等级 码龄9年 1633粉丝 62原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值