当前位置:   article > 正文

基于python BiLSTM-CRF的命名实体识别 附完整代码_基于bert-bilstm-crf进行中文命名实体识别python源码+数据(高分项目)

基于bert-bilstm-crf进行中文命名实体识别python源码+数据(高分项目)

完整代码:https://download.csdn.net/download/qq_38735017/87427497

实验一、中文分词实现

1.1 问题描述


中文分词指的是将一个汉字序列切分成一个一个单独的词。中文分词是文本挖掘的基础,对于输入的一段中文,成功的进行中文分词,可以达到电脑自动识别语句含义的效果。它是信息提取、信息检索、机器翻译、文本分类、自动文摘、语音识别、文本语音转换、自然语言理解等中文信息处理领域的基础。

1.1.1 基础任务

实现基于词典的分词算法

实验一资料包下的“Dictionary_based”文件夹中提供了基础词典和分词算法的大致框架。分词算法的核心部分需要大家完成,实验中提供了若干测试样本用以帮助大家判断算法是否正确实现。

实现基于统计学习的分词算法

实验中给出 Bi-LSTM+CRF 模型的基础实现,相关代码及说明文档位于实验一资料包下的“Bi-LSTM+CRF”文件夹下。请根据给定的实验资料中 README.md 文件配置相应实验环境,说明:(1)提供源码 PyTorch 语言编写(可根据个人掌情况用其他语言编写),默认运行版本是 CPU 版本;(2)如希望运行 NPU 版本,大家可跟任课老师联系,申请华为云资源运行(需提前统计名单:姓名 + 学号 + 个人手机号码 + 邮箱);

1.1.2 选做任务

优化基础任务中实现的分词器,可考虑的优化方案有:

  • 修改网络结构,例如引入 BERT 等预训练语言模型;

  • 与命名实体识别算法相互配合,减少对命名实体的错误分割;

  • 构造合适的词典集(可扩充 + 人工整理);

  • 实现新词发现(登录)功能,识别测试集中的新词(未登录词);

  • 调整、优化模型训练过程中的超参数。

完成优化后对测试文件“Bi-LSTM+CRF/data/test.txt”进行分词,分词结果保存到.txt 文件中 utf-8 编码,词与词之间以空格分隔,每个测试样本占一行。文件“Bi-LSTM+CRF/cws_result.txt”中给出了输出示例。提交分词结果后,依据单词级别的 F1-score 进行评判,决定选做部分的实验分数。

单词级别的 F1-score 的计算方式如下:

  • Gold: 共同 创造 美好 的 新 世纪 —— 二 ○○ 一年 新年 贺词

  • Hypothesis: 共同 创造 美 好 的 新 世纪 —— 二 ○○ 一年 新年 贺词

  • Precision = 9 / 11 = 0.818

  • Recall = 9 / 10 = 0.9

  • F1-score = 2PrecisionRecall/(Precision+Recall)=0.857

1.2 模块设计-基于词典


1.2.1 前向最大匹配

从待分词句子的左边向右边搜索,寻找词的最大匹配。我们需要规定一个词的最大长度,每次扫描的时候寻找当前开始的这个长度的词来和字典中的词匹配,如果没有找到,就缩短长度继续寻找,直到找到字典中的词或者成为单字。

算法流程如下:

  • (1)从待分词子串中从前往后取出 max_len 个字,然后扫描分词字典,测试该 max_len 个字的子串是否在字典中;

  • (2)如果存在,则从待分词子串中删除掉该 max_len 个字的子串,重新按照规则取子串,重复(1);

  • (3)如果不存在于字典中,则减少该子串的最右一个字,之后重复(1)。

1.2.2 后向最大匹配

从待分词句子的右边向左边搜索,寻找词的最大匹配。同样,我们也需要规定一个词的最大长度,每次扫描的时候寻找当前开始的这个长度的词来和字典中的词匹配,如果没有找到,就缩短长度继续寻找,直到找到字典中的词或者成为单字。

算法流程如下:

  • (1)从待分词子串中从后往前取出 max_len 个字,然后扫描分词字典,测试该 max_len 个字的子串是否在字典中;

  • (2)如果存在,则从待分词子串中删除掉该 max_len 个字的子串,重新按照规则取子串,重复(1);

  • (3)如果不存在于字典中,则减少该子串的最左一个字,之后重复(1)。

1.2.3 双向最大匹配

将前向最大匹配算法和后向最大匹配算法进行比较,从而确定正确的分词方法。

算法流程如下:

  • (1)比较前向最大匹配和后向最大匹配结果;

  • (2)如果分词结果相同,返回其中任意一个;

  • (3)如果分词结果不同:

  • 比较两者分词总数量,数量高者罚分;

  • 比较两者分词中单字词数量,单字词多者罚分;

  • 比较两者分词中非字典词数量,非字典词多者罚分;

  • 选择罚分最少的作为最终结果。

1.3 模块设计-基于统计学习


1.3.1 data_u.py

  • getist:单个分词转换成 tag 序列。按行读入数据,并分析各个字对应的标签,然后返回分析结果。

  • handle_data:处理数据,并保存至 save_path。按行读取对应文件中的数据,并做相应的处理,然后把处理的结果保存到 data_save.pkl 中。

1.3.2 dataloader.py

读取通过 data_u.py 处理完后的文件 data_save.pkl,并将其向量化。

1.3.3 infer.py

通过已经训练好的模型,完成对测试文件的分析,并将分词结果保存到 cws_result.txt 文件中。

1.3.4 model.py

  • init_hidden:通过 torch.randn 函数进行初始化操作。

  • _get_lstm_features:获取 LSTM 框架。

  • forward:预测每个标签的 loss 值,以减少无效预测。

  • infer:采用 Bi-LSTM+CRF 的基础结构的分析结果。

1.3.5 run.py

采用小批量梯度下降法,对模型进行训练,使得 loss 值降低。

小批量梯度下降,是对批量梯度下降以及随机梯度下降的一个折中办法。其思想是:每次迭代 使用 batch_size 个样本来对参数进行更新,每次使用一个 batch 可以大大减小收敛所需要的迭代次数,同时可以使收敛到的结果更加接近梯度下降的效果。

1.4 代码实现-基于词典


1.4.1 前向最大匹配

  1. defforward_mm_split(self,fmm_text):"""
  2. 正向最大匹配分词算法
  3. :param fmm_text:待分词字符串
  4. :return:分词结果,以list形式存放,每个元素为分出的词
  5. """# 字词列表,存放分词结果word_list=[]# 用于记录分词的起始位置count=0# 字或词当前的长度word_len=self.max_lenwhileword_len>0andcount<len(fmm_text):word=fmm_text[count:count+word_len]word_len=len(word)if(wordinself.words)or(wordinself.delimiter):word_list.append(word)count=count+word_lenword_len=self.max_lenelse:word_len=word_len-1returnword_list

1.4.2 后向最大匹配

  1. defreverse_mm_split(self,rmm_text):"""
  2. 逆向最大匹配分词算法
  3. :param rmm_text:待分词字符串
  4. :return:分词结果,以list形式存放,每个元素为分出的词
  5. """# 字词列表,存放分词结果word_list=[]# 用于记录分词的末尾位置count=len(rmm_text)# 字或词当前的长度word_len=self.max_lenwhileword_len>0andcount>0:ifcount<=word_len:word=rmm_text[:count]else:word=rmm_text[(count-word_len):count]word_len=len(word)if(wordinself.words)or(wordinself.delimiter):word_list.insert(0,word)count=count-word_lenword_len=self.max_lenelse:word_len=word_len-1returnword_list

1.4.3 双向最大匹配

  1. defbidirectional_mm_split(self,bi_text):"""
  2. 双向最大匹配分词算法
  3. :param bi_text:待分词字符串
  4. :return:分词结果,以list形式存放,每个元素为分出的词
  5. """# 前向最大匹配得到的分词结果forward=self.forward_mm_split(bi_text)# 后向最大匹配得到的分词结果reverse=self.reverse_mm_split(bi_text)# 总词数forward_total_words=len(forward)reverse_total_words=len(reverse)# 单字词个数forward_single_words=0reverse_single_words=0# 非字典词数forward_illegal_words=0reverse_illegal_words=0# 罚分,分值越低,表明结果越好forward_score=0reverse_score=0ifforward==reverse:returnforwardelse:# 统计前向匹配的各个词情况
  6. forwordinforward:iflen(word)==1:forward_single_words+=1ifwordnotinself.words:forward_illegal_words+=1# 统计后向匹配的各个词情况
  7. forwordinreverse:iflen(word)==1:reverse_single_words+=1ifwordnotinself.words:reverse_illegal_words+=1# 计算罚分
  8. ifforward_total_words<reverse_total_words:reverse_score+=1
  9. else:forward_score+=1
  10. ifforward_illegal_words<reverse_illegal_words:reverse_score+=1
  11. else:forward_score+=1
  12. ifforward_single_words<reverse_single_words:reverse_score+=1
  13. else:forward_score+=1# 比较罚分情况,罚分最小的选做最终结果
  14. ifforward_score<reverse_score:
  15. returnforward
  16. else:
  17. returnreverse

1.5 运行结果


利用实验包已给出的代码框架,实现完对应的匹配函数后,运行测试样例。

(1)基于词典的中文分词,得到输出结果如下:

(2)基于统计学习的中文分词,将输出的分词文件进行在线测评,结果如下:

1.6 实验小结


实验中总体的代码框架已给出,需要实现的部分为前向最大匹配、后向最大匹配和双向最大匹配三个核心函数。通过相关资料的参考以及对中文分词的个人理解,能够顺利实现各个匹配模式的实现。

基于统计学习的中文分词代码,由于已经给出了代码框架,所以只是在其基础上做了部分优化,并增加了一部分的训练数据。

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

闽ICP备14008679号