数据集是关于医疗诊断的,json格式存储,一个样本如下,分别包含text和spo_list,spo_list包含一个或多个对象。spo_list里的predicate是要提取的关系,subject是头实体,object是尾实体。
数据量为14+万,44类关系。
关系抽取的思路是将任务转化成分类任务来做,首先将label抽取出来,然后采用分类模型训练,然后根据输入文本预测对应的关系。采用ALBERT预训练模型+bert4keras框架。
实体识别的思路是采用MRC方式,构建query+passage,来预测start和end位置。框架是ELECTRA预训练模型+bert4keras。
bert4keras用的是084版本。
关系抽取属于多标签分类任务,一个样本对应一个多标签labels。处理完的一个样本如下所示,由text + fengefu + label组成,label用id表示,训练的时候再根据fengefu拆分数据。
实体识别属于MRC任务,query需要自己构建,passage就是text。实体识别的数据和关系抽取有所不一样,关系抽取的一个样本就是一对多的关系,而实体识别的样本对应多个关系,关系还可以重复,但相同关系的头实体和尾实体都不一样。所以将具有多个关系的样本转化成多个样本,而将这个关系作为先验知识放在query中,所以实体识别的任务的数据集将比关系抽取大很多。上述样本处理完如下所示,由query +fengefu+text+fengefu+start_id+end_id
step1:将样本1的数据按照分隔符切分,按照tuple(text,label)的格式写成list。
step2:将list输入子类dataGenerator。bert4keras的DataGenerator可以数据输出为适应bert格式的数据生成器,包含(token_id,segment_id,mask_id)。
step3:加载ALBERT预训练模型。
step4:在albert模型后面接全连接层,单元数为类别个数44,注意激活函数为sigmoid。
step5:用keras的compile函数打包模型参数,并且用fit_generator函数训练,在每个epoch结束时输出f1_score。
step6:预测就是按照分类任务的套路做。
step1:将样本2、3的数据按照分隔符切分,按照tuple(query,text,start_idx,end_idx)的格式写成list。
紫色部分便是实体。头实体和尾实体分别同onehot向量表示,每个样本结尾都有结束标志符。query部分都将不参与loss计算。
step3:加载ELECTRA预训练模型。
step4:在electra模型后面接两个全连接层,start和end各接一个,单元数分别为2。每个位置的都将看成是一个二分类,多少个text_id便有多少个二分类。
step6:定义f1_score,首先,因为start和end位置是分别预测的,先将两个合并起来;然后,加总预测值和实际值都为1的个数,分别除以预测值和实际值为1的个数,得到precision,recall,进而得到f1。
step7:用keras的compile函数打包模型参数,并且用fit_generator函数训练,在每个epoch结束时输出f1_score,precision,recall。
step8:分别对start位置和end位置,然后将text中对应的实体提取出来。
关系抽取和实体识别是分成两个任务来做的,二者不存在什么交互关系。实践结果中,关系分类f1_score可以达到60%,实体识别80%多。关系分类f1_score的结果不是很好,查看了类别的样本数量分布,发现不均衡,估计是由此引起的。
分别采用了自定义带权重的损失函数和focal_loss(),自定义的函数能够将f1_score提升10%,focal_loss()提升7%。
输入以下编码:
from kerasmodels import Model
model = # create the original model
layer_name = 'my_layer
intermediate_layer_model = Model(input=modelinput,
output=modelget_layer(layer_name)output)
intermediate_output = intermediate_layer
简介:
模型需要compile这些优缺点很大程度上都是因为现行版本将theano深度耦合,其作者和一些代码贡献者也意识到了这个问题,于是计划下一步将theano解藕出来放到单独的backend模块里,到时也许可以自由切换其他symbolic引擎。总的来说Keras是一个很有前途的库。
2优点:
支持python,模型库全,搭模型快,关注度极高,迭代快,可用GPU加速。
3缺点:
内部许多类的抽象不合理。
一、参考目录:
官方文档
Stateful LSTM in Keras (必读圣经)
案例灵感来自此GitHub
Stateful and Stateless LSTM for Time Series Forecasting with Python (这篇可以看完本文再看)
二、官方文档简介
stateful: Boolean (default False) If True, the last state for each sample at index i in a batch will be used as initial state for the sample of index i in the following batch
使 RNN 具有状态意味着每批样品的状态将被重新用作下一批样品的初始状态。
注意,此处的状态表示的是原论文公式里的c,h,即LSTM特有的一些记忆参数,并非w权重。
当使用有状态 RNN 时,假定:
所有的批次都有相同数量的样本
如果x1和x2是连续批次的样本,则x2[i]是x1[i]的后续序列,对于每个i
要在 RNN 中使用状态,你需要:
通过将batch_size参数传递给模型的第一层来显式指定你正在使用的批大小。例如,对于10个时间步长的32样本的batch,每个时间步长具有16个特征,batch_size = 32
在RNN层中设置stateful = True
在调用fit()时指定shuffle = False
有点绕,我给翻译翻译
假设Timestep=5,batch_size=2
X1和X2就是连续的两个批次,X2[i]是X1[i]的后续序列,也就是说,床前明月光后面是疑是地上霜
光的状态会传递到疑作为初始状态,也就是用光输出的(h, c)来初始化疑的(h, c)
那就不难理解为什么“所有的批次都有相同数量的样本”,如果不同批次的样本数不同,那上一批次传过来的(h, c)将没人接手
进而,Keras文档说用stateful需要指定batch_size也没毛病,不指定的话,Keras默认容忍最后一个批次样本数不同。例如,samples=9,batch_szie=2,那么默认分成5批,最后一批只有1个样本
下一个问题,shuffle
shuffle = True会在每个epoch开始之前打乱 训练集 数据顺序,使用stateful LSTM肯定要设置shuffle = False,不然光可能传给汗不就乱套了
三、疑问解答:
将一个很长的序列(例如时间序列)分成小序列来构建我的输入矩阵。那LSTM网络会发现我这些小序列之间的关联依赖吗?
不会,除非你使用 stateful LSTM 。大多数问题使用stateless LSTM即可解决,所以如果你想使用stateful LSTM,请确保自己是真的需要它。在stateless时,长期记忆网络并不意味着你的LSTM将记住之前batch的内容。
在Keras中stateless LSTM中的stateless指的是
注意,此文所说的stateful是指的在Keras中特有的,是batch之间的记忆cell状态传递。而非说的是LSTM论文模型中表示那些记忆门,遗忘门,c,h等等在同一sequence中不同timesteps时间步之间的状态传递。
假定我们的输入X是一个三维矩阵,shape = (nb_samples, timesteps, input_dim),每一个row代表一个sample,每个sample都是一个sequence小序列。X[i]表示输入矩阵中第i个sample。步长啥的我们先不用管。
当我们在默认状态stateless下,Keras会在训练每个sequence小序列(=sample)开始时,将LSTM网络中的记忆状态参数reset初始化(指的是c,h而并非权重w),即调用modelreset_states()。
为啥stateless LSTM每次训练都要初始化记忆参数
因为Keras在训练时会默认地shuffle samples,所以导致sequence之间的依赖性消失,sample和sample之间就没有时序关系,顺序被打乱,这时记忆参数在batch、小序列之间进行传递就没意义了,所以Keras要把记忆参数初始化。
那stateful LSTM到底怎么传递记忆参数?
首先要明确一点,LSTM作为有记忆的网络,它的有记忆指的是在一个sequence中,记忆在不同的timesteps中传播。举个例子,就是你有一篇文章X,分解,然后把每个句子作为一个sample训练对象(sequence),X[i]就代表一句话,而一句话里的每个word各自代表一个timestep时间步,LSTM的有记忆即指的是在一句话里,X[i][0]第一个单词(时间步)的信息可以被记忆,传递到第5个单词(时间步)X[i][5]中。
而我们突然觉得,这还远远不够,因为句子和句子之间没有任何的记忆啊,假设文章一共1000句话,我们想预测出第1001句是什么,不想丢弃前1000句里的一些时序性特征(stateless时这1000句训练时会被打乱,时序性特征丢失)。那么,stateful LSTM就可以做到。
在stateful = True 时,我们要在fit中手动使得shuffle = False。随后,在X[i](表示输入矩阵中第i个sample)这个小序列训练完之后,Keras会将将训练完的记忆参数传递给X[i+bs](表示第i+bs个sample),作为其初始的记忆参数。bs = batch_size。这样一来,我们的记忆参数就能顺利地在sample和sample之间传递,X[i+nbs]也能知道X[i]的信息。
用可以更好地展示,如下图,蓝色箭头就代表了记忆参数的传递,如果stateful = False,则没有这些蓝色箭头。
stateful LSTM中为何一定要提供batch_size参数?
我们可以发现,记忆参数(state)是在每个batch对应的位置跳跃着传播的,所以batch_size参数至关重要,在stateful lstm层中必须提供。
那stateful时,对权重参数w有影响吗?
我们上面所说的一切记忆参数都是LSTM模型的特有记忆c,h参数,和权重参数w没有任何关系。无论是stateful还是stateless,都是在模型接受一个batch后,计算每个sequence的输出,然后平均它们的梯度,反向传播更新所有的各种参数。
四、总结
如果你还是不理解,没关系,简单的说:
stateful LSTM:能让模型学习到你输入的samples之间的时序特征,适合一些长序列的预测,哪个sample在前,那个sample在后对模型是有影响的。
stateless LSTM:输入samples后,默认就会shuffle,可以说是每个sample独立,之间无前后关系,适合输入一些没有关系的样本。
如果你还是不理解,没关系……举个例子:
stateful LSTM:我想根据一篇1000句的文章预测第1001句,每一句是一个sample。我会选用stateful,因为这文章里的1000句是有前后关联的,是有时序的特征的,我不想丢弃这个特征。利用这个时序性能让第一句的特征传递到我们预测的第1001句。(batch_size = 10时)
stateless LSTM:我想训练LSTM自动写诗句,我想训练1000首诗,每一首是一个sample,我会选用stateless LSTM,因为这1000首诗是独立的,不存在关联,哪怕打乱它们的顺序,对于模型训练来说也没区别。
以上就是关于Pipline Model--实体关系抽取<总结>全部的内容,包括:Pipline Model--实体关系抽取<总结>、keras怎么读取每层网络的输出、深入理解Keras LSTM的stateful等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)