NLP实践——基于SIFRank的英文关键短语抽取

1. 回顾

之前的文章中介绍了如何用SIFRank进行中文的关键词抽取:
https://blog.csdn.net/weixin_44826203/article/details/121144724

有读者问到是否可以用来做英文,答案是肯定的,SIFRank原本就是做英文的,自然可以采用类似的方法进行改写,使之可以适用于英文。所以这篇文章就对之前我改写的代码进行一点补充,在之前的代码基础上增加对英文场景下的关键词抽取。

所以如果你还没有看过之前那篇文章,请先点击上面的链接跳转,对整个流程有一个大体的了解。

2. 英文关键词抽取

上次将关键词抽取模型梳理成以下几个组件:

  • utils
  • 标点和停用词
  • 预训练词汇权重
  • 分词/词性标注模型
  • 候选短语抽取模型
  • 词形还原模型
  • 编码模型

打对号的是这次不需要进行修改的,剩下的组件或多或少都需要进行一点修改。

2.1 预训练词汇权重

这个其实就是一个词频统计,可以在自己的语料上进行统计。原作者在项目中给出了几个可以用的词频统计结果,通过下方链接跳转到git地址:
https://github.com/sunyilgdx/SIFRank
下载其中auxiliary_data目录下的wiki文件,放在我们目录下resources中,目录结构参考中文关键短语抽取博客。

然后替换原来的目录即可:

weightfile_pretrain = './resources/enwiki_vocab_min200.txt'

2.2 分词/词性标注模型

在中文关键词提取中,我采用了ltp4模型进行分词和词性标注工作,对于英文场景,在此我采用的是stanza模型,这是一个基于python实现的,集分词、词性、句法等功能于一身的nlp工具,很方便,无论是安装、修改都比较方便。在这里不进行详细的介绍,如何安装请自行百度。

当然,你也可以利用nltk,stanfordcoreNLP,spacy或其他nlp工具来实现这一功能。

首先我们配置stanza模型的资源目录,用变量stanza_model_path指向这个目录:

stanza_model_path = 'path_to_your_model/model'

然后实现一个类用于分词和词性标注:

class Stanza_for_tokenize_and_postag:
	"""
	用于英文分词和词性标注
	---------------
	ver: 2021-11-21
	by: changhongyu
	"""
	def __init__(self, stanza_model_path, use_gpu=True):
		"""
		:param stanza_model_path:
		:param use_gpu:
		"""
		print("Initializing Stanza model from {}.".format(stanza_model_path))
		self.stanza_model = stanza.Pipeline(lang='en', dir=stanza_model_path, use_gpu=use_gpu)
		print("Stanza model created.")

	def cut(self, text):
		"""
		:return token_list: list:
		:return token_tag_list: list:
		"""
		token_list = []
		token_tag_list = []
		doc_res = self.stanza_model(text)
		for item in doc_res.sentences:
			for word in item.words:
				token_list.append(word.text)
				token_tag_list.append(word.xpos)

		return [[token, tag] for token, tag in zip(token_list, token_tag_list)]

然后把它实例化:

stanza_pos_model = Stanza_for_tokenize_and_postag(stanza_model_path)

这个模型对应的是中文模型中的ltp_pos_model。

值得注意的是,stanza并没有指定gpu_id,只是用来判断是否使用gpu,可以去stanza的源码中对其进行修改,或者通过os或torch.cuda模块对gpu_id进行指定。

2.3 候选短语抽取模型

候选短语抽取与之前大同小异,只是因为stanza对词性的标记规则有所差异,需要对grammar进行配置。

class CandidateExtractor:
    """
    参考SIFRank项目的词性正则抽取候选短语
    """
    def __init__(self):
    	grammar = """ NP:
    				{<NN.*|JJ>*<NN.*>}  """
        # grammar = """  NP:
        #             {<n.*|a|uw|i|j|x>*<n.*|uw|x>|<x|j><-><m|q>} # Adjective(s)(optional) + Noun(s)"""
        self.parser = nltk.RegexpParser(grammar)
    
    def extract_candidates(self, tokens_tagged):
        keyphrase_candidate = []
        np_pos_tag_tokens = self.parser.parse(tokens_tagged)
        count = 0
        for token in np_pos_tag_tokens:
            if (isinstance(token, nltk.tree.Tree) and token._label == "NP"):
            	# 注意英文的空格
                # np = ''.join(word for word, tag in token.leaves())
                np = ''.join(word + ' ' for word, tag in token.leaves())[: -1]
                length = len(token.leaves())
                start_end = (count, count + length)
                count += length
                keyphrase_candidate.append((np, start_end))
            else:
                count += 1
        
        return keyphrase_candidate
        
candidate_extractor = CandidateExtractor()

如果希望对grammar进行修改,以按照自己的偏好获取候选关键短语,可以参考我上一篇中文的文章。
另外,这里有一个点需要注意,英文候选关键词中有空格,拼接的时候需要小心,在上面的代码中进行了注释。

2.4 编码模型

编码模型部分没有需要修改的代码,只需去huggingface上下载可以处理英文的预训练模型即可,至于选择哪一个,就看你的喜好了。

最后在**SIFRank(ver: 2021-11-02)**类中的最后部分,为了处理中文,我把空格替换成了特殊字符’▲’,如果处理英文,记得把这行代码注释掉。

本期内容到此结束,希望读到这里的同学有所收获,我们下期再见。

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值