10 月 23 - 25 日,QCon 上海站即将召开,现在购票,享9折优惠 了解详情
写点什么

用于序列标注问题的条件随机场

  • 2019-09-26
  • 本文字数:3097 字

    阅读完需:约 10 分钟

用于序列标注问题的条件随机场


在此前的文章中,我曾介绍过介绍隐马尔科夫模型,隐马尔科夫模型引入了马尔科夫假设,即当前时刻的状态只与其前一时刻的状态有关。但是,在序列标注任务中,当前时刻的状态,应该同该时刻的前后的状态均相关。于是,在很多序列标注任务中,引入了条件随机场。今天详细介绍条件随机场的理论和及其在实体识别中的应用和 tensorflow 中的实现。

1 条件随机场是什么?

机器学习最重要的任务,是根据一些已观察到的证据(例如训练样本)来对感兴趣的未知变量(例如类别标记)进行估计和推测。


概率模型提供这样一种描述的框架,将学习任务归结于计算变量的概率分布。在概率模型中,利用已知变量推测未知变量的分布称为“推断”,其核心是如何基于可观测变量推测出未知变量的条件分布。具体来说,假定所关心的变量集合为 Y,可观测变量集合为 X,“生成式”模型直接通过训练样本基本联合概率分布 P(Y,X);“判别式”模型通过先计算条件分布 P(Y|X)。


我们前面讲的 HMM 是一种生成式概率图模型,条件随机场(CRF)与 HMM 不同,是一种判别式的概率图模型。CRF 是在给定一组变量的情况下,求解另一组变量的条件概率的模型。


设 X 与 Y 是一组随机变量,P(Y,X)是给定随机变量 X 情况下,随机变量 Y 的条件概率。若随机变量 Y 构成一个无向图 G(V,E),当 X 与 Y 两个随机变量的概率分布满足如下的条件:



则称在给定随机变量序列 X 的情况下,随机变量序列 Y 的条件概率 P(Y,X)构成条件随机场。


简单说明一下上面的条件概率公式:


v 表示 G 中的任一节点,例如 Y1,v~V。n(v)表示与 v 有边连接的节点的集合。上式的含义就是,Y 在 i 时刻的状态,仅与其有边连接的节点有关。


在 NLP 中,常用的是线性链的条件随机场,下面着重介绍下线性链条件随机场以加深理解。



设 X={x1,x2,x3,…xn},Y={y1,y2,y3,…yn}均为线性链表示的随机变量序列,若在给定随机变量序列 X 的情况下,随机变量序列 Y 的条件概率 P(Y,X)构成条件随机场,即满足如下的条件:



从上面的定义可以看出,条件随机场与 HMM 之间的差异在于,HMM 中,Y 在 i 时刻状态与其前一时刻,即 y(i-1)相关。而在 CRF 中,Y 在 i 时刻的状态与其前后时刻,即 y(i-1)与 y(i+1)均相关。


上面大致讲了条件随机场的定义,有什么样的性质。如果读过小 Dream 哥上一篇 HMM 讲解文章的同学,此刻对 CRF 应该就有了大致的了解。


在介绍 CRF 的实际应用之前,还有一些概念需要介绍,就是条件随机场的参数化形式。

2 条件随机场的参数化表现形式

我们先列出来 CRF 的参数化形式。假设 P(Y,X)是随机序列 Y 在给定随机序列 X 情况下的条件随机场,则在随机变量 X 取值为 x 的情况下,随机变量 Y 的取值 y 具有如下关系:




t_k 和 s_l 是特征函数,v_k 和 u_l 是对应的权值


t_k 是状态转移函数,v_k 是对应的权值;s_l 是发射函数,u_l 是对应的权值。好的,假如所有的 t_k,s_l 和 v_k,u_l 都已知,我们要算的 P(Yi =yi|X)是不是就可以算出来啦?


在给定随机序列 X 的情况下,计算概率最大 Y 序列可以用维特比算法,维特比算法在上一章节 HMM 中有详细的介绍,没看的同学可以在点击链接查看。


大家应该还有一大堆的疑问,t_k,s_l 和 v_k,u_l 如何确定和学习?在实际中我们如何使用?小 Dream 如果只讲到这里,就会太让大家失望了。下面我们看看在 tensorflow 里,CRF 是怎么实现的,以及我们如何使用他,经过这一段,大家对条件随机场应该就会有一个较为完整的认识了。

3 tensorflow 里的条件随机场

这一节我们以命名实体识别为例,来介绍在 tensorflow 里如何使用条件随机场(CRF)。


命名实体识别与分词一样,是一个序列标注的问题,因为篇幅问题,这里就不展开,不清楚的同学可以先出门百度一下,以后我们再找机会,好好讲一下命名实体识别的项目。


该命名实体识别任务特征提取的网路结构如下:



其他的我们先不看,我们只用知道,自然语言的句子经过神经网络(双向 LSTM)进行特征提取之后,会得到一个特征输出。训练时,将这个特征和相应的标记(label)输入到条件随机场中,就可以计算损失了。预测时,将自然语言输入到该网络,经 CRF 就可以识别该句子中的实体了。


我们来看看具体的代码:



这是我定义的损失层,project_logits 是神经网络最后一层的输出,该矩阵的 shape 为[batch_size, num_steps, num_tags],第一个是 batch size,第二个是输入的句子的长度,第三个标记的个数,即命名实体识别总标记的类别数。targets 是输入句子的 label,即每个字的 label,它的维度为[batch_size, num_steps]。损失层定义了一个 self.trans 矩阵,大小是[num_tags+1, num_tags+1], 加 1 是因为还有一个类别是未定义。


将 project_logit,targets 以及 self.trans 交给 tensorflow 的系统函数 crf_log_likelihood 即可求得损失了。


下面我们进一步来看看 crf_log_likelihood 是怎么实现的:



crf_log_likelihood 函数中分为两步,最终得到 scores:


(1) 调用 crf_sequence_score 函数计算 sequence_scores。


(2) 将 sequence_scores 进行归一化处理。


CRF 参数的学习及 score 计算过程主要在 crf_sequence_score 中进行,我们好好看看这个函数。



从 crf_sequence_score 函数的实现中,我们看出,tf 中的损失值包括一元损失和二元损失。其中 unary_scores 表示的是输入序列之间转化的损失,unary_scores 表示的转化矩阵的损失值。那这两项到底是什么呢?都是两项,是不是和 CRF 的参数化形式感觉有点像?我们看看相关论文是怎么说的。


LampleG, Ballesteros M, Subramanian S, et al. Neural architectures for named entity recognition[J]. arXiv preprint arXiv:1603.01360, 2016.



我们看一下,得分分为两项,第一项:



它表示输入句子中,第 i 个词,取某个标记的概率。


举个例子,假如输入的句子是“Mark Watney visit Mars”, 相应的 label 是[B-PER,E-PER,O,S-LOC],则 P(1,“B-PER”)表示的是第一个词的标记是 B-PER 的概率。所以第一项会是 P(1,“B-PER”)+P(2,“E-PER”)+P(3,“O”)+P(4,“S-LOC”)。


前面提到过,project_logits 是神经网络最后一层的输出,该矩阵的 shape 为[batch_size, num_steps, num_tags]。所以在 tensorflow 的实现中,该矩阵的值会取到 project_logits 矩阵中相应的值,这一点交叉熵有点像,同学们体会一下。


第二项:



它代表的是整个序列从一个标记转化到下一个标记的损失值。它用每一项值从 self.trans 矩阵中取得。它最开始是按照我们初始化的方式初始化的,然后会随着训练的过程优化。


好了,tensorflow 中 crf 就是这么实现的,是不是有种豁然开朗的感觉??


我们来做一个总结,CRF 是一个在给定某一个随机序列的情况下,求另一个随机序列的概率分布的概率图模型,在序列标注的问题中有广泛的应用。


在 tensorflow 中,实现了 crf_log_likelihood 函数。在本文讲的命名实体识别项目中,自然语言是已知的序列,自然语言经过特征提取过后的 logits,是发射矩阵,对应着 t_k 函数;随机初始化的 self.trans 矩阵是状态转移矩阵,对应着参数 s_l,随着训练的过程不断的优化。


CRF 相关的理论及其在 tensorflow 中的实现,就差不多讲完了。但是有一个很关键的点,需要读者们思考一下。在这个实体识别的任务中,经过 LSTM 完成特征提取之后,为什么要接一层 CRF 再得到 scores 和损失值?

总结

条件随机场(CRF)在现今 NLP 中序列标记任务中是不可或缺的存在。太多的实现基于此,例如 LSTM+CRF,CNN+CRF,BERT+CRF。因此,这是一个必须要深入理解和吃透的模型。


作者介绍


小 Dream 哥,公众号“有三 AI”作者。该公号聚焦于让大家能够系统性地完成 AI 各个领域所需的专业知识的学习。


原文链接


https://mp.weixin.qq.com/s/79M6ehrQTiUc0l_sO9fUqA


2019-09-26 18:372082

评论

发布
暂无评论
发现更多内容

实习是步入社会的一道坎

KEY.L

7月月更

分布式事务的性能设计

穿过生命散发芬芳

分布式事务 7月月更

你学会如何将项目部署到Linux系统上了吗?要不我带你耍耍。

Java学术趴

7月月更

群里的初级工程师求助说,要采集采招数据,必须给他安排上

梦想橡皮擦

Python 爬虫 7月月更

zookeeper-watcher的javaApi相关使用

zarmnosaj

7月月更

C#入门系列(二十二) -- 面向对象之多态

陈言必行

7月月更

Setup的使用技巧

bo

Vue 前端 7月月更

ArkUI开发框架组件的生命周期详解

坚果

HarmonyOS OpenHarmony Open Harmony 7月月更

模块7(王者荣耀商城异地多活架构设计)

Geek_701557

Okaleido或杀出NFT重围,你看好它吗?

BlockChain先知

函数初认识-下

芒果酱

C语言 7月月更

Istio XDS配置生成实现

阿泽🧸

envoy 7月月更

模块1 作业

Mysql 温故知新系列「触发器详解」

安逸的咸鱼

MySQL 7月月更

uni-app进阶之自定义【day13】

恒山其若陋兮

7月月更

Zabbix 6.0 源码安装以及 HA 配置

耳东@Erdong

zabbix ha 7月月更 zabbix 6.0

读书笔记之《深入理解Java虚拟机:JVM高级特性与最佳实践》(下)

蔡农曰

Java 后端 JVM 后端技术 Java 开发

C++ Workflow异步调度框架 - 性能优化网络篇

1412

c++ 开源 workflow 异步调度 网络框架

Linux tar打包

工程师日月

Linux tar 7月月更

Vscode 搭建 C / C++ 开发环境

攻城狮杰森

c c++ vscode 开发环境 7月月更

如何在Linux中比较多个文件?这12个优秀工具了解一下!

wljslmz

Linux 7月月更 文件比较

Qt | 控件之QComboBox

YOLO.

qt 7月月更

C++ Workflow 异步编程框架 - 性能优化上篇

1412

c++ GitHub 开源 异步编程 workflow

长安链学习研究-存储分析wal机制

长安链

排序子序列与倒置字符串

未见花闻

7月月更

【萌新解题】四数之和

面试官问

LeetCode

王者荣耀商城异地多活架构设计

地下地上

架构实战营

Vue3 状态管理 Pinia 快速入门指南

程序员海军

Vue 状态管理 7月月更

现场可程式化逻辑闸阵列 FPGA

贾献华

7月月更

Flutter 使用 AnimatedSwitcher 做场景切换

岛上码农

flutter ios 前端 安卓开发 7月月更

用于序列标注问题的条件随机场_AI&大模型_小Dream哥_InfoQ精选文章