当前位置:   article > 正文

基于GPLinker的事件抽取代码解读。(预测部分)_gplinker代码

gplinker代码
  1. tokens  = ['[CLS]', '2020', '年', ',', '法', '院', '一', '审', '判', '处', '主', '要', '成', '员', '程', '杰', '有', '期', '徒', '刑', '22', '年', ',', '王', '绍', '伟', '有', '期', '徒', '刑', '20', '年', '。', '[SEP]']  (20202022都被看成一个token)
  2. mapping = [[], [0, 1, 2, 3], [4], [5], [6], [7], [8], [9], [10], [11], [12], [13], [14], [15], [16], [17], [18], [19], [20], [21], [22, 23], [24], [25], [26], [27], [28], [29], [30], [31], [32], [33, 34], [35], [36], []]  通过token的index 来索引mapping找到text中的字符。
  3. token_ids, segment_ids  =[101, 8439, 2399, 8024, 3791, 7368, 671, 2144, 1161, 1905, 712, 6206, 2768, 1447, 4923, 3345, 3300, 3309, 2530, 1152, 8130, 2399, 8024, 4374, 5305, 836, 3300, 3309, 2530, 1152, 8113, 2399, 511, 102] [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
  4. #outputs[0].shape = (282, 34, 34)  len(tokens) =34
  5. outputs[0][:, [0, -1]] -= np.inf   (1)
  6. outputs[0][:, :, [0, -1]] -= np.inf  (2)

由(1)(2)得每类34*34正方形的外面一圈都是- np.inf 因为cls,seq不是文本内容,使其得分为- np.inf

#构建链接

  1.     for i1, (_, _, h1, t1) in enumerate(argus):
  2.         for i2, (_, _, h2, t2) in enumerate(argus):
  3.             if i2 > i1:
  4.                 if outputs[1][0, min(h1, h2), max(h1, h2)] > threshold:
  5.                     if outputs[2][0, min(t1, t2), max(t1, t2)] > threshold:
  6.                         links.add((h1, t1, h2, t2))
  7.                         links.add((h2, t2, h1, t1))

global point 得分 (首)是一类因此是1*34*34

global point 得分 (尾)是一类因此是1*34*34

论元a首和b首的得分大于阈值0 都是 同理a尾和b尾,建立连接(a首,a尾,b首)和(b首,b尾,a首,a尾)正反都添加是方便后续做遍历查询有关系的节点是否存在links。

然后 析出事件groupby(sorted(argus), key=lambda s: s[0]) 用来分开不同类别,同一类别为一个列表(同一类别可能出现多个事件)。对每个类别进行clique_search。找出互相相关的论元节点构成集合。例如会出现a,b,c,d和c,d,e。其中e不和a,b相关而和c,d相关,集合里面互相都相关,因此可构成a,b,c,d和c,d,e。两集合。

  1.     for _, sub_argus in groupby(sorted(argus), key=lambda s: s[0]):
  2.         for event in clique_search(list(sub_argus), links):
  3.             events.append([])
  4.             for argu in event:
  5.                 start, end = mapping[argu[2]][0], mapping[argu[3]][-1] + 1
  6.                 events[-1].append(argu[:2] + (text[start:end], start))
  7.             if trigger and all([argu[1] != u'触发词' for argu in event]):
  8.             #如果一个触发词都没有,并且任务要求触发词,直接弹出当前事件event列表
  9.                 events.pop()

  for _, sub_argus in groupby(sorted(argus), key=lambda s: s[0]):

  针对不同类型的进行遍历{('司法行为-罚款', '罚款对象', 10, 12), ('司法行为-入狱', '触发词', 15, 16), ('司法行为-入狱', '入狱者', 10, 12), ('司法行为-入狱', '刑期', 13, 14), ('司法行为-罚款', '时间', 1, 4), ('司法行为-罚款', '罚款金额', 22, 25), ('司法行为-罚款', '触发词', 20, 21), ('司法行为-入狱', '时间', 1, 4)}

遍历1  [('司法行为-罚款', '罚款对象', 10, 12),, ('司法行为-罚款', '罚款金额', 22, 25), ('司法行为-罚款', '触发词', 20, 21), ('司法行为-罚款', '时间', 1, 4)]

再遍历2  [('司法行为-入狱', '触发词', 15, 16), ('司法行为-入狱', '入狱者', 10, 12), ('司法行为-入狱', '刑期', 13, 14),('司法行为-入狱', '时间', 1, 4)]

对于遍历1:

执行 for event in clique_search(list(sub_argus), links):

用来确定 司法行为-罚款 类别中 是否 包含多个事件 通过clique_search(list(sub_argus), links)函数来返回。

并同一类型多个事件,进行遍历。添加到events列表中,如果不包含事件不包含触发词则 舍弃。

集合argus = [('司法行为-入狱', '入狱者', 10, 15), ('司法行为-入狱', '入狱者', 23, 25), ('司法行为-入狱', '刑期', 20, 21), ('司法行为-入狱', '刑期', 30, 31), ('司法行为-入狱', '时间', 1, 2), ('司法行为-入狱', '触发词', 16, 19), ('司法行为-入狱', '触发词', 26, 29)]

集合argus 俩俩挨个遍历,找出不相邻的俩个节点

('司法行为-入狱', '入狱者', 10, 15)和('司法行为-入狱', '入狱者', 23, 25) 不相邻

单独再遍历集合argus找出 ('司法行为-入狱', '入狱者', 10, 15)相邻的节点,构成集合

因为现在虽然已经分出事件1,事件2,但事件1中,所有节点只和其中一个指定的节点相关,并不是所有节点都相互相关,因此需要递归找出,互不相关的节点再构成以该节点为中心找出事件1中与其相关的节点。(那么剩下的节点都是互相相关的不再处理,可以构成一个事件返回)

即定义一个函数:

遍历同一个事件类型1集合,找出事件类型1互不相关的节点a,b,并分别以a,b节点为中心,找出事件类型1与a,b相关的节点构成集合A和集合B,然后通过递归再遍历集合A和集合B,找出集合A、集合B互不相关的节点a1,b1,a’1,b’1。对集合A而言,选a1,b1为例,并分别以a1,b1节点为中心,找出与a1,b1相关的节点构成集合A1和集合B1,继续递归,如果找不出互不相关的节点a1,b1,即集合A所有的节点都相关,那么返回集合A。同理集合B

* 它找的是一对儿,例如事件A(a,b,c)都相关,且事件B(a,b,d)都相关,

以上情况只限定同一事件类型,a,b,c,d四个论元节点。c和a,b有关但,c和d无关,且d和a,b有关,已经事件内都互相相关。

同理遍历2 ('司法行为-入狱', '入狱者', 23, 25) 一样。

* 相邻的节点构成事件集合event 如果已经重复存在,则不添加。

  1.             for event in extract_events(l['text']):
  2.                 final_event = {
  3.                     'event_type': event[0][0],
  4.                     'arguments': DedupList()
  5.                 }
  6.                 for argu in event:
  7.                     if argu[1] != u'触发词':
  8.                         final_event['arguments'].append({
  9.                             'role': argu[1],
  10.                             'argument': argu[2]
  11.                         })
  12.                 event_list = [
  13.                     event for event in event_list
  14.                     if not isin(event, final_event)
  15.                 ]
  16.                 if not any([isin(final_event, event) for event in event_list]):
  17.                     event_list.append(final_event)

遍历一个样本的事件,得出事件的事件类型,触发词,role,论元内容。最后为啥要排除event_list中被final_event包含的event, 或者event_list中的有event包含final_event就不添加的操作可以不要这操作吗?在之前不是已经全部遍历找到所有互相相关的论元并构成了一个集合,应该不存在这种一个样本只找了部分的相关论元构成的事件。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/623510
推荐阅读
相关标签
  

闽ICP备14008679号