赞
踩
继续追随苏神的脚步~
在阅读一些论文的时候,在做文本序列任务时,会看到span-level,token-level的说法。在中文任务中token-level就是指字级别的任务,span-level可以理解成词级别的任务。以NER任务来说传统的LSTM+CRF 就是token-level的任务 对每个位置上的字进行预测,然后通过标注的规则解码出符合要求的连续token串组成实体。span-level就是以词为单位直接进行相关的任务,这里的词应该理解为任意个连续token串组成的连续文本(单个token也符合要求,也是一个span),与我们理解的词语不同。
总结一下:
在中文任务中 token-level就是指每个字,而span-level 就是任意个连续的字串组成的连续文本
在英文任务中 token-level就是指每个单词,而span-level 就是任意个连续单词串组成的连续文本
参考阅读
Span-Level Model for Relation Extraction
span-level NER 是一种应对嵌套实体任务的方法,基于片段排列的方式,提取所有可能的片段排列,当某个片段排列是我们需要的正确排列作为正确实体,其他的作为负面实体,通过SoftMax对每一个Span进行实体类型判断,将原来的序列标注问题转化成分类问题。
举个例子,针对下面的case:
句子:《邪少兵王》是冰火未央写的网络小说连载于旗峰天下
这句话中包含的实体:邪少兵王(作品名), 冰火未央(作者)
在span-level NER任务中, 这个句子中任何长度的子串都是一个实体
我们理论上可以得到
'《'
‘《邪’
‘《邪少’
‘《邪少兵’
‘《邪少兵王’
‘《邪少兵王》’
‘《邪少兵王》是’
‘《邪少兵王》是冰’
‘《邪少兵王》是冰火’
...
等等的很多的实体 ,在上面这些实体中,‘《邪少兵王》’就是属于小说名称的正面实体,其他都是负面实体。然后用分类模型识别出正面实体。
原始数据集 百度2020比赛的数据集 百度网盘 请输入提取码 提取码 vu02
处理后生成的数据集 部分包含在github项目中 GitHub - hgliyuhao/span_level_ner
整个算法其实就是一个分类模型 ,复杂的地方在于构建合适的训练集,需要在众多负面实体中选择一部分作为负样本。
可以看到在对于含n个token的文本,理论上共有n(n+1)/2 种片段排列。比如长度为20的句子,就有20*(20+1)/2个潜在的实体
对于该数据集共有110000左右的样本,其中很多都是非常长的句子,数据量简直爆炸,而且包含了大量的负样本,计算量也异常的大。
所以在算力有限的情况下,尝试做了一些优化:
1 用分词的方式去分割句子 代替原来按字的方式分割句子,将大量减少样本数量,并且可以增加样本的对抗性和合理性
2 随机在负样本中选取一定量的样本
3 拓展正面实体的边界获取对抗性较高的负样本,比如‘《邪少兵王》’是正面实体,就需要生成‘《邪少兵王 ’,‘邪少兵王》’,‘《邪少兵王》 ’这些对抗性强的负样本。(在实验的时候开始并没有针对的制作负样本,结果观察结果的时候
会发现有大量边界错误的问题)
4 限制实体的最大长度,效果同1
5 可以考虑去掉带有标点符号的负样本
原数据集的样子:{"text": "《邪少兵王》是冰火未央写的网络小说连载于旗峰天下", "spo_list": [{"predicate": "作者", "object_type": {"@value": "人物"}, "subject_type": "图书作品", "object": {"@value": "冰火未央"}, "subject": "邪少兵王"}]}
转换成分类模型 即 (《邪少兵王》,图书作品) ,(冰火未央,人物),(未央写的网,非实体),(络小说连载于,非实体)
模型使用实体 + 原句拼接后 使用bert + 分类。这样融入了更多的语境信息,准确率更高。
也可以在bert后接了两层隐藏单元数为150的FFNN,然后接softmax。
- output = Lambda(lambda x: x[:, 0],
- name='CLS-token')(bert.model.output)
- output = Dense(units=100,
- activation='relu',
- kernel_initializer=bert.initializer)(output)
-
- output = Dense(units=100,
- activation='relu',
- kernel_initializer=bert.initializer)(output)
-
- output = Dense(units=27,
- activation='softmax')(output)
-
- model = keras.models.Model(bert.model.input, output)
其实这种NER的做法 整体模型结构很简单也很好理解 。最复杂的部分就是正负样本的构建。如果负样本过少就会得到大量的错误实体,如果负样本过多,训练的代价会非常大。
这个过程需要根据算法的表现不断调整策略。
有兴趣的同学可以看陈丹琦大佬的一篇最新的关系抽取SOTA《A Frustratingly Easy Approach for Joint Entity and Relation Extraction》,里面使用了这种方式去做NER
还有腾讯AI团队的《Empirical Analysis of Unlabeled Entity Problem in Named Entity Recognition》这篇也论证了这种基于片段排列的数据标注方式,会使模型更有鲁棒性,同时可以减少因为实体漏标对模型造成的负面影响
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。