NLP数据预处理——同义词替换程序

自然语言数据预处理中经常会涉及到同义词替换,比如计算两个句子的相似度中,把一个词的两个同义词利用同义词替换技术转换为同一个词,那么就提高了相似度计算的可靠性。学习自然语言处理的同学肯定都会做到数据预处理的工作,下面分享我最近写的一个程序,希望能为从事同样工作的同学提供那么一点帮助,也希望自己的程序能够得到指点。

程序中设计到分词技术和同义词表,分词采用了哈工大的pyltp,其官方文档链接为http://pyltp.readthedocs.io/zh_CN/latest/。同义词表是利用哈工大的同义词词林(扩展版)进行预处理保留每个词的前两项得来的,原版下载链接为https://www.ltp-cloud.com/download/。

我采用的同义词词表是下面这种结构:

人 士
人类 生人
人手 人员
劳力 劳动力
匹夫 个人
家伙 东西
者 手
每人 各人
该人 此人
人民 民

下面是同义词替换程序(注释比较详细,这里不再赘述程序具体实现方式):

from pyltp import Segmentor


class SynonymsReplacer:
    def __init__(self, synonyms_file_path, cws_model_path):
        self.synonyms = self.load_synonyms(synonyms_file_path)
        self.segmentor = self.load_segmentor(cws_model_path)

    def __del__(self):
        """对象销毁时要释放pyltp分词模型"""
        self.segmentor.release()

    def load_segmentor(self, cws_model_path):
        """
        加载ltp分词模型
        :param cws_model_path: 分词模型路径
        :return: 分词器对象
        """
        segmentor = Segmentor()
        segmentor.load(cws_model_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='/your/path', cws_model_path='/your/path')
    test_sentence = '承蒙关照今天早'
    _syn = replacer.get_syno_sents_list(test_sentence)
    for s in _syn:
        print(s)

程序输出如下所示:

['承蒙', '关照', '今天', '早']
['承蒙', '关照', '今天', '早日']
['承蒙', '关照', '今天', '早安']
['承蒙', '关照', '今日', '早']
['承蒙', '关照', '今日', '早日']
['承蒙', '关照', '今日', '早安']
['承情', '关照', '今天', '早']
['承情', '关照', '今天', '早日']
['承情', '关照', '今天', '早安']
['承情', '关照', '今日', '早']
['承情', '关照', '今日', '早日']
['承情', '关照', '今日', '早安']

输入是一个str类型的句子,输出是包含它本身的list形式的句子。欢迎各位朋友指教!

你可能感兴趣的:(自然语言处理NLP,python)