伪原创同义词替换(基于知识库的问答系统替换在检索系统中的基础性和必要性)
优采云 发布时间: 2022-01-26 16:20伪原创同义词替换(基于知识库的问答系统替换在检索系统中的基础性和必要性)
问答系统逐渐成为一种非常流行和实用的应用,成为越来越多研究者的研究方向。当前的问答系统包括基于知识库的问答系统、对话系统和聊天机器人。
在问答系统中,当用户想使用问答系统搜索与自己提出的查询相同或相似的问题及其答案时,由于用户输入的查询是自己描述的,所以比较通俗化,而且有是错别字、歧义等。复杂的结构和冗长的句型使得很难从问题中提取出重要的关键词项(提出的关键词质量不高,用词也不尽如人意) . 由于无法准确获取问题中的核心关键词,导致搜索结果不够准确,因此需要对输入查询中的关键词进行同义词扩展。
当用户使用问答系统进行搜索时,为了将同义词与用户输入的查询的关键词进行匹配,从而获得更好的搜索结果,基于同义词的搜索请求(查询)扩展为used,即在使用 query 进行搜索的同时,也使用 query 同义词进行搜索,提高了搜索结果召回的质量。
以上解释了检索系统中同义词替换的基本性和必要性。
最近有一个项目曝光了基于知识库的问答系统,需要扩展关键词的同义词来提高搜索效率。
同义词的扩展在此不再详述。
程序中设计了分词技术和词库表。分词采用哈工大的pyltp,其官方文档链接为。同义词表是利用哈工大的同义词词林(扩展版)对每个词的前两项进行预处理和保留得到的。原来的下载链接是(但是好像网页不存在)。
同义词替换代码如下:
这里使用哈工大的pyltp分词包,加载自定义词典。找到免费下载地址:
哈工大pyltp分词:
# -*- coding: utf-8 -*-
import os
LTP_DATA_DIR = 'ltp_data_v3.4.0' # ltp模型目录的路径
cws_model_path = os.path.join(LTP_DATA_DIR, 'cws.model') # 分词模型路径,模型名称为`cws.model`
from pyltp import Segmentor
segmentor = Segmentor() # 初始化实例
segmentor.load(cws_model_path) # 加载模型
words = segmentor.segment('元芳你怎么看') # 分词
print ('\t'.join(words))
segmentor.release() # 释放模型
结果:
元芳 你 怎么 看
Process finished with exit code 0
同义词替换计划:
# -*- coding: utf-8 -*-
#加载自定义词典
from pyltp import Segmentor
class SynonymsReplacer:
def __init__(self, synonyms_file_path, cws_model_path,userdict_file_path):
self.synonyms = self.load_synonyms(synonyms_file_path)
self.segmentor = self.load_segmentor(cws_model_path,userdict_file_path)
def __del__(self):
"""对象销毁时要释放pyltp分词模型"""
self.segmentor.release()
def load_segmentor(self, cws_model_path,userdict_file_path):
"""
加载ltp分词模型
:param cws_model_path: 分词模型路径
:return: 分词器对象
"""
segmentor = Segmentor()
segmentor.load_with_lexicon(cws_model_path,userdict_file_path)
return segmentor
def segment(self, sentence):
"""调用pyltp的分词方法将str类型的句子分词并以list形式返回"""
return list(self.segmentor.segment(sentence))
def load_synonyms(self, file_path):
"""
加载同义词表
:param file_path: 同义词表路径
:return: 同义词列表[[xx,xx],[xx,xx]...]
"""
synonyms = []
with open(file_path, 'r', encoding='utf-8') as file:
for line in file:
synonyms.append(line.strip().split(' '))
return synonyms
def permutation(self, data):
"""
排列函数
:param data: 需要进行排列的数据,列表形式
:return:
"""
assert len(data) >= 1, "Length of data must greater than 0."
if len(data) == 1: # 当data中只剩(有)一个词及其同义词的列表时,程序返回
return data[0]
else:
head = data[0]
tail = data[1:] # 不断切分到只剩一个词的同义词列表
tail = self.permutation(tail)
permt = []
for h in head: # 构建两个词列表的同义词组合
for t in tail:
if isinstance(t, str): # 传入的整个data的最后一个元素是一个一维列表,其中每个元素为str
permt.extend([[h] + [t]])
elif isinstance(t, list):
permt.extend([[h] + t])
return permt
def get_syno_sents_list(self, input_sentence):
"""
产生同义句,并返回同义句列表,返回的同义句列表没有包含该句本身
:param input_sentence: 需要制造同义句的原始句子
:return:
"""
assert len(input_sentence) > 0, "Length of sentence must greater than 0."
seged_sentence = self.segment(input_sentence)
candidate_synonym_list = [] # 每个元素为句子中每个词及其同义词构成的列表
for word in seged_sentence:
word_synonyms = [word] # 初始化一个词的同义词列表
for syn in self.synonyms: # 遍历同义词表,syn为其中的一条
if word in syn: # 如果句子中的词在同义词表某一条目中,将该条目中它的同义词添加到该词的同义词列表中
syn.remove(word)
word_synonyms.extend(syn)
candidate_synonym_list.append(word_synonyms) # 添加一个词语的同义词列表
perm_sent = self.permutation(candidate_synonym_list) # 将候选同义词列表们排列组合产生同义句
syno_sent_list = [seged_sentence]
for p in perm_sent:
if p != seged_sentence:
syno_sent_list.append(p)
return syno_sent_list
if __name__ == '__main__':
replacer = SynonymsReplacer(synonyms_file_path='tongyici.txt', cws_model_path='ltp_data_v3.4.0/cws.model',userdict_file_path = 'userdict.txt')
test_sentence = '欠债不还犯法吗'
_syn = replacer.get_syno_sents_list(test_sentence)
for s in _syn:
print(s)
测试示例的替换结果:
参考:
ltp 工具包下载: