这份代码来自于苏剑林

# -*- coding:utf-8 -*-

from keras.layers import Layer
import keras.backend as K class CRF(Layer):
"""纯Keras实现CRF层
CRF层本质上是一个带训练参数的loss计算层,因此CRF层只用来训练模型,
而预测则需要另外建立模型,但是还是要用到训练好的转移矩阵
"""
def __init__(self, ignore_last_label=False, **kwargs):
"""ignore_last_label:定义要不要忽略最后一个标签,起到mask的效果
"""
self.ignore_last_label = 1 if ignore_last_label else 0
super(CRF, self).__init__(**kwargs)
def build(self, input_shape):
self.num_labels = input_shape[-1] - self.ignore_last_label
self.trans = self.add_weight(name='crf_trans',
shape=(self.num_labels, self.num_labels),
initializer='glorot_uniform',
trainable=True)
def log_norm_step(self, inputs, states):
"""递归计算归一化因子
要点:1、递归计算;2、用logsumexp避免溢出。
技巧:通过expand_dims来对齐张量。
"""
states = K.expand_dims(states[0], 2) # previous
inputs = K.expand_dims(inputs, 2) # 这个时刻的对标签的打分值,Emission score
trans = K.expand_dims(self.trans, 0) # 转移矩阵 output = K.logsumexp(states+trans+inputs, 1) # e 指数求和,log是防止溢出
return output, [output] def path_score(self, inputs, labels):
"""计算目标路径的相对概率(还没有归一化)
要点:逐标签得分,加上转移概率得分。
技巧:用“预测”点乘“目标”的方法抽取出目标路径的得分。
"""
# 在CRF中涉及到标签得分加上转移概率,而这个point score就是相当于是标签得分(在真是标签的情况下,查看预测对于真实标签位置的总得分),因为labels的shape是[B, T, N],而在N这个维度是one-hot,
# 这里再乘以pred,相当于是对labels存在1的地方进行打分,其余地方全为0,再进行第2个维度相加表示去除0的值,再相加表示求一个总的标签得分
point_score = K.sum(K.sum(inputs*labels, 2), 1, keepdims=True) # 逐标签得分, shape [B, 1]
labels1 = K.expand_dims(labels[:, :-1], 3) # shape [B, T-1, N, 1]
labels2 = K.expand_dims(labels[:, 1:], 2) # shape [B, T-1, 1, N]
# 这里相乘的目的相当于从上一时刻转移到当前时刻,确定当前时刻是从上一时刻哪一个标签转移过来的,因为labels是one-hot的形式,所以在最后两个维度只有1个元素为1,其他全部为0,表示转移标志
labels = labels1 * labels2 # 两个错位labels,负责从转移矩阵中抽取目标转移得分 shape [B, T-1, N, N]
trans = K.expand_dims(K.expand_dims(self.trans, 0), 0)
# K.sum(trans*labels, [2, 3]),因为trans*labels的结果是[B, T-1, N, N], 而后面两个维度中只有1个有值,表示转移得分
trans_score = K.sum(K.sum(trans*labels, [2, 3]), 1, keepdims=True) # 求出所有T-1时刻的概率转移总得分,K.sum(trans*labels, [2, 3]), 表示每个时刻的转移得分
return point_score+trans_score # 两部分得分之和 def call(self, inputs): # CRF本身不改变输出,它只是一个loss
return inputs def loss(self, y_true, y_pred): # 目标y_pred需要是one hot形式
mask = 1-y_true[:, 1:, -1] if self.ignore_last_label else None
y_true, y_pred = y_true[:, :, :self.num_labels], y_pred[:, :, :self.num_labels]
init_states = [y_pred[:, 0]] # 初始状态
log_norm, _, _ = K.rnn(self.log_norm_step, y_pred[:, 1:], init_states, mask=mask) # 计算Z向量(对数) shape[batch_size, output_dim]
log_norm = K.logsumexp(log_norm, 1, keepdims=True) # 计算Z(对数)shape [batch_size, 1] 计算一个总的
path_score = self.path_score(y_pred, y_true) # 计算分子(对数)
return log_norm - path_score # 即log(分子/分母) def accuracy(self, y_true, y_pred): # 训练过程中显示逐帧准确率的函数,排除了mask的影响
mask = 1-y_true[:,:,-1] if self.ignore_last_label else None
y_true,y_pred = y_true[:,:,:self.num_labels],y_pred[:,:,:self.num_labels]
isequal = K.equal(K.argmax(y_true, 2), K.argmax(y_pred, 2))
isequal = K.cast(isequal, 'float32')
if mask == None:
return K.mean(isequal)
else:
return K.sum(isequal*mask) / K.sum(mask)

CRF keras代码实现的更多相关文章

  1. 从 python 中 axis 参数直觉解释 到 CNN 中 BatchNorm 的工作方式(Keras代码示意)

    1. python 中 axis 参数直觉解释 网络上的解释很多,有的还带图带箭头.但在高维下是画不出什么箭头的.这里阐述了 axis 参数最简洁的解释. 假设我们有矩阵a, 它的shape是(4, ...

  2. 深度学习(七)U-Net原理以及keras代码实现医学图像眼球血管分割

    原文作者:aircraft 原文链接:https://www.cnblogs.com/DOMLX/p/9780786.html DRIVE数据集下载百度云链接:链接:https://pan.baidu ...

  3. 大数据开发之keras代码框架应用

    总体来讲keras这个深度学习框架真的很“简易”,它体现在可参考的文档写的比较详细,不像caffe,装完以后都得靠技术博客,keras有它自己的官方文档(不过是英文的),这给初学者提供了很大的学习空间 ...

  4. Keras代码超详细讲解LSTM实现细节

    1.首先我们了解一下keras中的Embedding层:from keras.layers.embeddings import Embedding: Embedding参数如下: 输入尺寸:(batc ...

  5. 条件随机场CRF原理介绍 以及Keras实现

    本文是对CRF基本原理的一个简明的介绍.当然,“简明”是相对而言中,要想真的弄清楚CRF,免不了要提及一些公式,如果只关心调用的读者,可以直接移到文末. 图示# 按照之前的思路,我们依旧来对比一下普通 ...

  6. 到底该如何入门Keras、Theano呢?(浅谈)

    目前刚刚开始学习Theano,可以说是一头雾水,后来发现Keras是对Theano进行了包装,直接使用Keras可以减少很多细节程序的书写,它是模块儿化的,使用比较方便,但更为细节的内容,还没有理解, ...

  7. Keras 学习之旅(一)

    软件环境(Windows): Visual Studio Anaconda CUDA MinGW-w64 conda install -c anaconda mingw libpython CNTK ...

  8. Inception模型和Residual模型卷积操作的keras实现

    Inception模型和Residual残差模型是卷积神经网络中对卷积升级的两个操作. 一.  Inception模型(by google) 这个模型的trick是将大卷积核变成小卷积核,将多个卷积核 ...

  9. Keras官方中文文档:序贯模型

    快速开始序贯(Sequential)模型 序贯模型是多个网络层的线性堆叠,也就是"一条路走到黑". 可以通过向Sequential模型传递一个layer的list来构造该模型: f ...

随机推荐

  1. September 15th, 2019. Sunday, Week 38th.

    Break down these walls and come on in. 一路披荆斩棘,勇往直前. We are the only wall that stands in our way to s ...

  2. MATLAB实例:求相关系数、绘制热图并找到强相关对

    MATLAB实例:求相关系数.绘制热图并找到强相关对 作者:凯鲁嘎吉 - 博客园 http://www.cnblogs.com/kailugaji/ 用MATLAB编程,求给定数据不同维度之间的相关系 ...

  3. 给定数轴上的n个点,求距离最近的两个点的距离

    public class MinimumSpacing { //给定平面上的n个点,求距离最近的两个点的距离. //无从下手的话,先分解问题,分解成简单的,逐个分析,然后再合在一起考虑 //这是个2维 ...

  4. 关于Git和GitHub的一些知识

    git是分布式的版本控制工具,可离线,svn是集中式的,要联网操作.集中式的所有数据都放在服务器端,如果服务器宕机,则历史记录也可能就丢失了,这叫做单点故障.分布式的数据可直接保存在客户端. 为何要版 ...

  5. [CodeForces-1225A] Forgetting Things 【构造】

    [CodeForces-1225A] Forgetting Things [构造] 标签: 题解 codeforces题解 构造 题目描述 Time limit 2000 ms Memory limi ...

  6. STM32F429的新版用户手册更新记录, 改进、交流(2019-08-18发布V0.9版本)

    2019-06-16 发布首版V0.1 2019-06-23 发布V0.2版本 新增章节: 第3章 STM32F429 整体把控 第4章 STM32F429 工程模板建立(MDK5) 第5章 STM3 ...

  7. IT兄弟连 HTML5教程 HTML5表单 小结及习题

    小结 HTML表单提交的方法有get方法和post方法,get方法的作用是从指定的资源请求数据,post方法的作用是向指定的资源提交要被处理的数据.HTML表单一直都是Web的核心技术之一,有了它我们 ...

  8. Python 从入门到进阶之路(六)

    之前的文章我们简单介绍了一下 Python 的面向对象,本篇文章我们来看一下 Python 中异常处理. 我们在写程序时,有可能会出现程序报错,但是我们想绕过这个错误执行操作.即使我们的程序写的没问题 ...

  9. SpringBoot2.0 整合 Redis集群 ,实现消息队列场景

    本文源码:GitHub·点这里 || GitEE·点这里 一.Redis集群简介 1.RedisCluster概念 Redis的分布式解决方案,在3.0版本后推出的方案,有效地解决了Redis分布式的 ...

  10. API统一管理平台-YApi

    前言:开发过程中,会产生很多接口对接操作,这个时候可能需要一个接口管理平台管理已经开发好的接口方便业务对接. 一.概述 YApi 是高效.易用.功能强大的 api 管理平台,旨在为开发.产品.测试人员 ...