当前位置:   article > 正文

领域命名实体NER实现:Bert+BiLSTM+CRF_bert 顺序纠正

bert 顺序纠正

以前通过模板规则的方式进行命名实体的提取,优点是提取速度非常高,但模板规则存在冲突的情况,尝试过使用百度LAC通过词性模板规则进行命名实体的提取,好处是少量规则可以覆盖大部分情况,但也存在规则冲突的情况。本文尝试采用Bert+BiLSTM+CRF的方式进行命名实体的提取。使用Bert的好处是能够学习到语料的语义特征,BiLSTM能学习到词之间较长的上下文关系,CRF能纠正BiLSTM预测的顺序错误。Bert的好处是准确率非常高,缺点也很明显,推理速度低,可以通过部署的方式来提升推理性能,如:使用ONNX 运行环境。

主要步骤如下:

1)准备标注语料(自行准备了224个标注),生成和人民日报语料一样的格式(语料生成代码来自互联网),可以自定义领域命名实体;

  1. #生成的训练语料,一个字一行,格式同人民日报语料
  2. import re
  3. # txt2ner_train_data turn label str into ner trainable data
  4. # s :labeled str eg.'我来到[@1999年#YEAR*]的[@上海#LOC*]的[@东华大学#SCHOOL*]'
  5. # save_path: ner_trainable_txt name
  6. def str2ner_train_data(s, save_path):
  7. ner_data = []
  8. result_1 = re.finditer(r'\[\@', s)
  9. result_2 = re.finditer(r'\*\]', s)
  10. begin = []
  11. end = []
  12. for each in result_1:
  13. begin.append(each.start())
  14. for each in result_2:
  15. end.append(each.end())
  16. print(len(begin) ,len(end))
  17. assert len(begin) == len(end)
  18. i = 0
  19. j = 0
  20. while i < len(s):
  21. if i not in begin:
  22. ner_data.append([s[i], 'O'])
  23. i = i + 1
  24. else:
  25. ann = s[i + 2:end[j] - 2]
  26. entity, ner = ann.rsplit('#')
  27. if (len(entity) == 1):
  28. ner_data.append([entity, 'B-' + ner])
  29. # ner_data.append([entity, 'S-' + ner])
  30. else:
  31. if (len(entity) == 2):
  32. ner_data.append([entity[0], 'B-' + ner])
  33. ner_data.append([entity[1], 'I-' + ner])
  34. # ner_data.append([entity[1], 'E-' + ner])
  35. else:
  36. ner_data.append([entity[0], 'B-' + ner])
  37. for n in range(1, len(entity)):
  38. ner_data.append([entity[n], 'I-' + ner])
  39. # ner_data.append([entity[-1], 'E-' + ner])
  40. i = end[j]
  41. j = j + 1
  42. f = open(save_path, 'a', encoding='utf-8')
  43. for each in ner_data:
  44. f.write(each[0] + ' ' + str(each[1]))
  45. if each[0] == '。' or each[0] == '?' or each[0] == '!':
  46. f.write('\n')
  47. f.write('\n')
  48. else:
  49. f.write('\n')
  50. f.close()
  51. # txt2ner_train_data turn label str into ner trainable data
  52. # file_path :labeled multi lines' txt eg.'我来到[@1999年#YEAR*]的[@上海#LOC*]的[@东华大学#SCHOOL*]'
  53. # save_path: ner_trainable_txt name
  54. def txt2ner_train_data(file_path, save_path):
  55. fr = open(file_path, 'r', encoding='utf-8')
  56. lines = fr.readlines()
  57. s = ''
  58. for line in lines:
  59. line = line.replace('\n', '')
  60. line = line.replace(' ', '')
  61. s = s + line
  62. fr.close()
  63. str2ner_train_data(s, save_path)
  64. if (__name__ == '__main__'):
  65. train_path = './train.txt' #生成的训练语料,一个字一行,格式同人民日报语料
  66. corpus_path = './middle_corpus.txt'#根据领域特征标注语料,可以自定义NER标签,不限于PER(人名),LOC(地名),ORG(机构名)
  67. txt2ner_train_data(corpus_path, train_path)
  1. # 读取自己的预料’
  2. train_path = './train.txt'
  3. test_path = './test.txt'
  4. def get_sequenct_tagging_data(file_path):
  5. data_x, data_y = [], []
  6. with open(file_path, 'r', encoding='utf-8') as f:
  7. lines = f.read().splitlines()
  8. x, y = [], []
  9. for line in lines:
  10. rows = line.split(' ')
  11. if len(rows) == 1:
  12. data_x.append(x)
  13. data_y.append(y)
  14. x = []
  15. y = []
  16. else:
  17. x.append(rows[0])
  18. y.append(rows[1])
  19. return data_x, data_y
  20. train_x, train_y = get_sequenct_tagging_data(train_path)
  21. validate_x, validate_y = get_sequenct_tagging_data(test_path)

2)使用kashgari2.0.1用于快速使用模型进行训练,包括使用Bert作为特征提取,使用中文预训练模型chinese_L-12_H-768_A-12(需要自行下载到本地);

3)模型的保存与装载;

4)使用模型进行推理,推理效果相当不错,比百度LAC的效果好。

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

闽ICP备14008679号