CRF模型详解

条件随机场(CRF)是自然语言处理的重要模型,广泛应用于分词、实体识别和词性标注等任务。本文详细介绍了CRF的基础概念、公式、CRF++的实现,包括模型训练和预测,并对比了HMM、MEMM与CRF的差异。通过理解特征函数定义和CRF的线性链结构,阐述了如何利用CRF进行序列标注并优化模型性能。

条件随机场(CRF)是自然语言处理中的基础模型, 广泛用于分词, 实体识别和词性标注等场景. 随着深度学习的普及, BILSTM+CRF, BERT+CRF, TRANSFORMER+CRF等模型, 逐步亮相, 并在这些标注场景, 效果有显著的提升.

下面是我学习CRF的学心总结, 看了多篇知乎, paper, 和CRF++的实现代码后, 终于有了深刻的理解.

基础概念

首先, 一起看一下随机过程, 随机场, 马尔可夫随机场的定义, 在最后请出条件随机场.

随机过程:
设 ​​​​​​​TTT是一无限实数集, 把依赖于参数t∈Tt\in TtT的一族(无限多个)随机变量称为随机过程, 记为 X(t),t∈T{X(t), t \in T}X(t),tT

随机场: 从平面(随机过程)到向量空间(随机场)
TTTnnn维空间的某个子集, 即ttt是一个nnn维向量, 此时随机过程又称为随机场. 常见随机场有: 马尔可夫随机场(MRF), 吉布斯随机场(GRF), 条件随机场(CRF)和高斯随机场.

马尔可夫随机场:
具有马尔可夫性的随机场.
马尔可夫性: P(Yv∣Yw,w≠v)=P(Yv∣Yw,w∼v)P(Y_v|Y_w, w\neq v) = P(Y_v|Y_w, w \sim v)P(YvYw,w=v)=P(YvYw,wv)

  • w∼vw \sim vwv表示在图G=(V,E)G=(V, E)G=(V,E)中与顶点vvv有边连接的所有顶点www
  • w≠vw \neq vw=v表示顶点vvv以外的所有顶点
  • YvY_vYvYwY_wYw为顶点vvvwww对应的随机变量

那么, 条件随机场是如何定义的呢?

条件随机场:

XXXYYY是随机变量, P(Y∣X)P(Y|X)P(YX)是在给定XXX的条件下YYY的条件概率分布.
若随机变量YYY构成一个由无向图G=(V,E)G=(V, E)G=(V,E)表示的马尔可夫随机场, 即
P(Yv∣X,Yw,w≠v)=P(Yv∣X,Yw,w∼v)P(Y_v|X, Y_w, w \neq v) = P(Y_v|X, Y_w, w \sim v)P(YvX,Yw,w=v)=P(YvX,Yw,wv)
对任意顶点vvv成立, 则称条件概率分布P(Y∣X)P(Y|X)P(YX)为条件随机场.

  • w∼vw \sim vwv表示在图G=(V,E)G=(V, E)G=(V,E)中与顶点vvv有边连接的所有顶点www
  • w≠vw \neq vw=v表示顶点vvv以外的所有顶点
  • YvY_vYvYwY_wYw为顶点vvvwww对应的随机变量

只基于Y序列做预测, 太单调了, 所以额外给出一个观测序列X, 帮助你更好的做决策. 这就是从马尔可夫随机场变成条件随机场的过程. 条件随机场中, "条件"指的是给定观测序列X的情况, 求状态序列Y的概率, 即输出的是条件概率分布. 而"随机场"指的是状态序列Y构成的随机场.

线性链条件随机场:

常见的标注场景, 如分词, 实体识别和词性标注等, 都是典型的线性链条件随机场. 那么什么是线性链条件随机场呢?
XXXYYY有相同结构(线性表示的随机变量序列)的条件随机场就构成了线性链条件随机场. (这里指的线性, 指语言天然具有的先后顺序,成线性特性.)

定义:
X=(X1,X2,...,Xn)X=(X_1, X_2, ..., X_n)X=(X1,X2,...,Xn), Y=(Y1,Y2,...,Yn)Y=(Y_1, Y_2, ..., Y_n)Y=(Y1,Y2,...,Yn)均为线性表示的随机变量序列,
若在给定随机变量序列XXX的条件下,
随机变量序列YYY的条件概率分布P(Y∣X)P(Y|X)P(YX)构成条件随机场, 即满足马尔可夫性
P(Yi∣X,Y1,...,Yi−1,Yi+1,...,Yn)=P(Yi∣X,Yi−1,Yi+1)P(Y_i|X, Y_1, ..., Y_{i-1}, Y_{i+1}, ..., Y_n) = P(Y_i|X, Y_{i-1}, Y_{i+1})P(YiX,Y1,...,Yi1,Yi+1,...,Yn)=P(YiX,Yi1,Yi+1)
则称P(Y∣X)P(Y|X)P(YX)为线性链条件随机场. 其中i=(1,2,..n)i=(1,2,..n)i=(1,2,..n), 在i=1i=1i=1i=ni=ni=n时只考虑单边.

两种主要的线性链条件随机场的图结构如下:
在这里插入图片描述
由于线性链条件随机场应用非常广泛, 所以习惯把"线性链条件随机场"简称为条件随机场(CRF).

CRF公式

根据Hammersley Clifford定理, 一个无向图模型的概率, 可以表示为定义在图上所有最大团上的势函数的乘积.
那么, CRF的条件概率可以在因子分解下表示为:
在这里插入图片描述
线性链CRF的因子分解

在这里插入图片描述
如上图, 线性链CRF的因子分解, 根据函数类型, 可细化为:
P(y∣x)=1Z(x)exp⁡(∑i,kλktk(yi−1,yi,x,i)+∑i,lμlsl(yi,x,i))P(y|x) = \frac{1}{Z(x)} \exp (\sum_{i,k}\lambda_k t_k(y_{i-1}, y_i, x, i) + \sum_{i, l}\mu_l s_l (y_i, x, i))P(yx)=Z(x)1exp(i,kλktk(yi1,yi,x,i)+i,lμlsl(yi,x,i))
其中,
Z(x)=∑yexp⁡(∑i,kλktk(yi−1,yi,x,i)+∑i,lμlsl(yi,x,i))Z(x) = \sum_y \exp (\sum_{i,k}\lambda_k t_k(y_{i-1}, y_i, x, i) + \sum_{i,l}\mu_l s_l(y_i, x, i))Z(x)=yexp(i,kλktk(yi1,yi,x,i)+i,lμlsl(yi,x,i))

  • tkt_ktk为转移特征函数, 在CRF++中转移特征由Bigram Template + 输入字(词)序列生成
  • sls_lsl为状态特征函数, 在CRF++中状态特征由Uigram Template + 输入字(词)序列生成

CRF中, 通常有两类特征函数, 分别为转移特征和状态特征. 状态特征表示输入序列与当前状态之间的关系. 转移特征表示前一个输出状态与当前输出状态之间的关系. CRF++中, 特征模板需要人工设定, 有一定的局限性. 若结合深度神经网络, 如BERT+CRF, 则特征就可由模型自动学习得到, 具体讲, BERT学习状态特征, CRF学习转移特征, 并用viterbi获取最优路径.

理论讲了很多, 接下来讲讲CRF的实现代码, 以牛逼的CRF++为例.

CRF++实现详解

https://taku910.github.io/crfpp/ 是开源的CRF++的工具源代码.

CRF++中, 核心功能分为模型训练和预测两部分.

模型训练

整个训练过程分为三步:

  • 准备训练数据集
  • 通过定义特征模板, 自动生成特征函数集
  • 通过LBFGS算法, 学习特征函数的权重
训练数据集

训练数据集, 按照文档要求准备即可, 例子如下:

山 B_PROV
东 I_PROV
省 I_PROV
菏 B_CITY
泽 I_CITY
市 I_CITY
牡 B_DIST
丹 I_DIST
区 I_DIST
重 B_ROAD
庆 I_ROAD
路 I_ROAD

特征函数定义

特征模板格式:%x[row,col]。x可取U或B,对应两种类型。方括号里的编号用于标定特征来源,row表示相对当前位置的行,0即是当前行;col对应训练文件中的列。这里只使用第1列(编号0),即文字。若值为1, 则使用标签值.

定义特征模板:

# Unigram
U00:%x[-2,0]
U01:%x[-1,0]
U02:%x[0,0]
U03:%x[1,0]
U04:%x[2,0]
U05:%x[-2,0]/%x[-1,0]/%x[0,0]
U06:%x[-1,0]/%x[0,0]/%x[1,0]
U07:%x[0,0]/%x[1,0]/%x[2,0]
U08:%x[-1,0]/%x[0,0]
U09:%x[0,0]/%x[1,0]
# Bigram
B

特征函数, 前面提到过, 分为两种, 转移特征和状态特征. 特征模板中的Unigram or Bigram, 是针对输出序列YYY, 即标注label而言的. 如转移特征tk(yi−1,yi,x,i)t_k(y_{i-1}, y_i, x, i)tk(yi1,yi,x,i), 涉及到yi−1y_{i-1}yi1yiy_iyi, 所以叫Bigram特征. 状态特征sl(yi,x,i)s_l(y_i, x, i)sl(yi,x,i)只涉及到yiy_iyi, 所以叫Unigram特征.

以训练集中的第一行为例, 基于上面的特征模板, 生成10个特征 (此时还未与label进行结合):

U00:%x[-2, 0] =>“U00:_B-2” (这里的_B-2指的是beginning of sentence)
U01:%x[-1, 0] => “U01:_B-1” (_B-1, _B-2均为指代)
U02:%x[0, 0] => “U02:山”
U05:%x[-2,0]/%x[-1,0]/%x[0,0] => “U05:_B-2/_B-1/山”
U06:%x[-1,0]/%x[0,0]/%x[1,0] => “U06:_B-1/山/东”
U07:%x[0,0]/%x[1,0]/%x[2,0] => “U07:山/东/省”
U08:%x[-1,0]/%x[0,0] => “U08:_B-1/山”
U09:%x[0,0]/%x[1,0] => “U09:山/东”

基于输入序列生成的单边特征, 再与标签集合(Y集合)结合, 生成最终的特征函数.
若特征类型为Unigram, 每行模板生成一组状态特征函数,数量是L*N 个,L是标签状态数。N是此行模板在训练集上展开后的去重后的样本数, 如:

func0 = if (output = B_PROV and feature=“U02:山”) return 1 else return 0
func1 = if (output = I_PROV and feature=“U02:山”) return 1 else return 0
func1 = if (output = B_CITY and feature=“U02:山”) return 1 else return 0

若特征类型为Bigram, 每行模板生成一组转移特征函数, 数量是L*L*N 个。经过训练后,这些函数的权值反映了上一个节点的标签对当前节点的影响。例如对应 B00:%x[0, 0]:

func0 = if (prev_output = B_PROV and output = B_PROV and feature=“U02:山”) return 1 else return 0
func1 = if (prev_output = B_PROV and output = I_PROV and feature=“U02:山”) return 1 else return 0
func2 = if (prev_output = B_PROV and output = B_CITY and feature=“U02:山”) return 1 else return 0

funcN = if (prev_output = I_DIST and output = B_PROV and feature=“U02:山”) return 1 else return 0

现实中, 若Bigram模板的定义中, 涉及输入序列, 容易导致特征数巨大, 所以默认只使用简单的B, 即简化的转移特征函数tk(yi−1,yi)t_k(y_{i-1}, y_i)tk(yi1,yi), 与输入序列无关.

模型预测

HMM, MEMM vs. CRF对比

评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值