将PositionRank模型运行到给定数据集上(四)

2021SC@SDUSC

简介

在上一篇博客中提到,程序正常运行后得到的评分矩阵元素均为0,为了对中文打分需要对原程序的打分模块进行修改。

由于程序可以正常运行,因此可以对程序进行debug分析处理流程。

这里将可以得到评分矩阵的原程序(PositionRank)和针对中文修改算法后的新程序(PositionRank2)进行逐步debug对比:
在这里插入图片描述

当二者都执行完词列表过滤算法后结果如下:

PositionRank:

在这里插入图片描述

PositionRank2

在这里插入图片描述
即positionrank2的候选词被清空了!

因此可以确定词列表过滤算法不适用于对中文的处理。

词列表过滤算法

该算法分析如下

    def filter_candidates(self, stopwords_file=None, max_phrase_length=4, min_word_length=3, valid_punctuation='-.'):
        """
         基于多重保证进行词项过滤

        :param stopwords_file: 停用词列表文件
        :param max_phrase_length: 最长短语长度
        :param min_word_length:  最短词长度
        :param valid_punctuation: 特殊符号
        :return:
        """

        # 如果停用词没有提供
        stopwords_list = []
        if stopwords_file is None:
            from nltk.corpus import stopwords
            stopwords_list = set(stopwords.words('english'))

        else:
            with codecs.open(stopwords_file, 'rb', encoding='utf-8') as f:
                f.readlines()
            f.close()

            for line in f:
                stopwords_list.append(line)

        indices = []
        for i, c in enumerate(self.candidates):

            tokens = c.surface_form.split()
            pos = c.pos_pattern.split()

            # 去除含有停用词的部分
            if set(tokens).intersection(stopwords_list):
                indices.append(i)

            # 去除过长的短语
            elif len(tokens) > max_phrase_length:
                indices.append(i)
                
            # 去除太短的词
            elif min([len(t) for t in tokens]) < min_word_length:
                indices.append(i)
                
            # 去除形容词和以形容词结尾的短语
            elif pos[-1] == 'JJ':
                indices.append(i)

            elif set(tokens).intersection(set(['-lrb-', '-rrb-', '-lcb-', '-rcb-', '-lsb-', '-rsb-'])):
                indices.append(i)

            else:

                # 去除包含特殊字符的短语
                for word in tokens:
                    letters_set = set([u for u in word])

                    if letters_set.issubset(punctuation):
                        indices.append(i)
                        break

                    elif re.match(r'^[a-zA-Z0-9%s]*$' % valid_punctuation, word):
                        continue

                    else:
                        indices.append(i)
                        break

        dels = 0
        for index in indices:
            offset = index - dels
            dels += 1
            del self.candidates[offset]

算法修改

去除对于单个词长度的限制

原程序中会限制word的长度,例如“a”、“an”长度为1和2会被去除,而中文的单个词长度始终为1。

正则表达式加入对中文的匹配

if re.match(r'^[\u4e00-\u9fa5_a-zA-Z0-9]+$' % valid_punctuation, word):
    continue

再次运行程序,

得到了正常的weights列表

在这里插入图片描述

指标计算算法

currentP, currentR, currentF1 = \
                evaluation.PRF_range(system.get_best_k(args.topK), gold_stemmed, k=args.topK)

在这里插入图片描述

关键词是“自然语言处理”

而预测的结果是“自然 语言 处理”

二者取交集,结果为空集。这是因为之前该程序是针对英文的处理程序,每个词之间需要空格,而中文无需空格。回溯predicted的生成,定位到如下代码:

      # 选择一个单词,遍历该句中本单词后的所有内容,如果词性满足我们的要求并且之间的距离小于n(或单词长度-1)
                for j in range(0, len(tokens)):
                    for k in range(j, len(tokens)):
                        # 将满住要求的n-grams加入候选列表candidates
                        if pos_tags[k] in good_pos and k - j < max_length and k < (len(tokens) - 1):
                            self.candidates.append(Candidate(' '.join(tokens[j:k + 1]), ' '.join(pos_tags[j:k + 1]),
                                                             ' '.join(stems[j:k + 1]), j + jump, i))
                        else:
                            break

可见词之间通过空格连接,将连接方式改为:

''.join(tokens[j:k + 1])

再次运行,得到了正确的结果:
在这里插入图片描述

运行程序果不其然得到了评估矩阵
在这里插入图片描述

おすすめ

転載: blog.csdn.net/Simonsdu/article/details/121888643