自然语言处理

文本摘要方法

2022-06-21  本文已影响0人  晓柒NLP与药物设计

所谓摘要,就是对给定的单个或者多个文档进行梗概,即在保证能够反映原文档的重要内容的情况下,尽可能地保持简明扼要。质量良好的文摘能够在信息检索过程中发挥重要的作用,比如利用文摘代替原文档参与索引,可以有效缩短检索的时间,同时也能减少检索结果中的冗余信息,提高用户体验。随着信息爆炸时代的到来,自动文摘逐渐成为自然语言处理领域的一项重要的研究课题

一. 技术路线

1.1 TF-IDF

《Term Weighting Approaches in Automatic Text Retrieval》

导言:一种统计方法,用以评估一个词对于一个文件集或一个语料库中的其中一份文件的重要程度。其是由两个算法相乘而来,即词频(TF)乘以 逆文档频率指数(IDF)。其中词频表示一个词的常见程度,逆文档频率表示一个词的稀有程度。其基本原理是,字词的重要性随着其在文件中出现的次数成正比增加,但同时会随着其在语料库中出现的频率成反比下降

1.1.1 原理

TF-IDF的主要思想是:如果某个词或短语在一篇文章中出现的频率高,并且在其他文章中很少出现,则认为此词或者短语具有很好的类别区分能力,适合用来分类。其计算公式如下:

TF-IDF=TF×IDF

其中,TF表示词频(Term Frequency)IDF表示逆向文件频率(Inverse Document Frequency)TF表示词在文档d中出现的频率,而IDF的主要思想是:如果包含词t的文档越少,IDF越大,则说明词条t具有很好的类别区分能力。

词频(TF)指的是某一个给定的词语在该文件中出现的频率。这个数字是对词数(term count)的归一化,以防止它偏向长的文件。对于在某一特定文件里的词语来说,它的重要性可表示为:

TF_{i,j}=\frac{n_{i,j}}{\sum_kn_{k,j}}

其中分子是该词在文件中的出现次数,而分母则是在文件中所有字词的出现次数之和

逆向文件频率(IDF)指的是一个词语普遍重要性的度量。某一特定词语的IDF,可以由总文件数目除以包含该词语之文件的数目,再将得到的商取以10为底的对数得到:

DF_i=lg\frac{|D|}{|j:t_i\in d_j|}

某一特定文件内的高词语频率,以及该词语在整个文件集合中的低文件频率,可以产生出高权重的TF-IDF。因此,TF-IDF倾向于过滤掉常见的词语,保留重要的词语。其计算公式如下:

TF-IDF_{i,j}=TF_{i,j}×IDF_i

1.1.2 理论依据及不足

TF-IDF算法基于假设:对区别文档最有意义的词语应该是那些在文档中出现频率高,而在整个文档集合的其他文档中出现频率少的词语,因此引入TF词频作为测度,就可以体现同类文本的特点;另外考虑到单词区别不同类别的能力,TF-IDF法认为一个单词出现的文本频数越小,它区别不同类别文本的能力就越大,因此引入了逆文本频度IDF的概念,以TF和IDF的乘积作为特征空间坐标系的取值测度,完成对TF权重的调整,其目的在于突出重要单词,抑制次要单词。本质上IDF是一种试图抑制噪音的加权,且单纯认为文本频数小的单词就越重要,文本频数大的单词就越无用,显然并不完全正确。IDF的简单结构并不能有效地反映单词的重要程度和特征词的分布情况,使其无法很好地完成对权值调整的功能,所以TF-IDF法的精度并不是很高。此外,在TF-IDF算法中并没有体现出单词的位置信息,特征词在不同的位置对文章内容的反映程度不同,其权重的计算方法也应不同。

1.1.3 代码实现

使用TF_IDF模型实现文本摘要任务,具体思想如下

  1. 输入原文(长文本),可支持任意长度的文本。

  2. 输入文本经过文本清洗(删除html标签、冗余字符、url、异常字符等),再进行分句,得到一系列句子的集合;

  3. 然后对原文中的每个句子进行权重的计算。

  4. 最后将句子按照重要程度进行排序,筛选出超过阈值的重要句子,然后按照原文的序号进行排序。最后组合成完整的摘要文本并输出;

# sklearn的TF-IDF实现
from sklearn.feature_extraction.text import TfidfTransformer, CountVectorizer  
corpus=["I come to China to travel", 
    "This is a car polupar in China",          
    "I love tea and Apple ",   
    "The work is to write some papers in science"] 
vectorizer=CountVectorizer()
transformer = TfidfTransformer()
tfidf = transformer.fit_transform(vectorizer.fit_transform(corpus))  
print tfidf

1.2 TextRank

《TextRank: Bringing Order into Texts》

导言:最经典的基于图的无监督关键词/句提取算法,是文本任务版本的PageRank。TextRank算法仿照PageRank,将句子作为节点,使用句子间相似度,构造无向有权边。使用边上的权值迭代更新节点值,最后选取N个得分最高的节点,作为摘要。

1.1.1 原理

最经典的TextRank通过将文本建模成无向全连接图结构,在图上利用PageRank迭代计算每个节点的重要性分数,从而能够提取关键节点。对于关键词提取而言,图上的每个节点即为文档的词,边则代表词和词之间的共现关系,即在长度为N的滑动窗口内部的所有词认为是存在共现关系的,这些词也就相互之间有边连接。这里构造的图是无边权的,计算节点V_i的PageRank分数的方法如下式,d的存在目的是为了使模型有一定的概率跳到图上其它随机点上,避免孤立点计算出现死循环,一般取d=0.85,初始节点分数均为1。注意下式是迭代计算的,一般设为20次:

S\left(V_{i}\right)=(1-d)+d * \sum_{j \in \operatorname{In}\left(V_{i}\right)} \frac{1}{\left|\operatorname{Out}\left(V_{j}\right)\right|} S\left(V_{j}\right)

对于关键句提取而言,图上的节点代表文档中的句子,边权则用下式计算,其中S_i,S_j为两个句子,w_k代表句子中的词,也即节点边权定义为和两个句子词重叠率成正比,之所以还要除以句子长度的对数之和,是考虑到越长的句子越可能出现重叠的词

\operatorname{Similarity}\left(S_{i}, S_{j}\right)=\frac{\left|\left\{w_{k} \mid w_{k} \in S_{i} \& w_{k} \in S_{j}\right\}\right|}{\log \left(\left|S_{i}\right|\right)+\log \left(\left|S_{j}\right|\right)}

关键句提取中TextRank方法建立的图为带边权的图,因而以下式计算PageRank分数,这里w_{ij}即为节点V_i,V_j之间的边权大小,d的规定同上:

W S\left(V_{i}\right)=(1-d)+d * \sum_{V_{j} \in In\left(V_{i}\right)} \frac{w_{j i}}{\sum_{V_{k} \in Out \left(V_{j}\right)} w_{j k}} W S\left(V_{j}\right)

故,基于上述方法可知,TextRank方法是无监督的不需要训练

1.1.2 代码实现

这里使用sklearn实现,使用TextRank抽取文档中的关键句,实现无监督提取文本摘要

from sklearn.feature_extraction.text import TfidfVectorizer, TfidfTransformer
def get_abstract(content, size=3):
    """
    利用textrank提取摘要
    :param content:
    :param size:
    :return:
    """
    docs = list(cut_sentence(content))
    tfidf_model = TfidfVectorizer(tokenizer=jieba.cut, stop_words=load_stopwords())
    tfidf_matrix = tfidf_model.fit_transform(docs)
    normalized_matrix = TfidfTransformer().fit_transform(tfidf_matrix)
    similarity = nx.from_scipy_sparse_matrix(normalized_matrix * normalized_matrix.T)
    scores = nx.pagerank(similarity)
    tops = sorted(scores.items(), key=lambda x: x[1], reverse=True)
    size = min(size, len(docs))
    indices = list(map(lambda x: x[0], tops))[:size]
    return list(map(lambda idx: docs[idx], indices))

1.3 Roberta

A Robustly Optimized BERT Pretraining Approach

导言:基于全词掩码策略的中文预训练BERT模型,在多项中文NLP任务中均取得优异性能

Roberta本质上是一个调到最优的bert模型。chinese-roberta-wwm-ext针对中文任务的特点,对roberta的训练策略进行了进一步的优化

1.3.1 原理

整体改进

输入:原始文本是一个句子,如“使用语言模型来预测下一个词的probability”,经过分词和随机mask后,会得到预处理文本“使 用 语 言 [MASK] [MASK] 来 [MASK] [MASK] 下 一 个 词 的 [MASK] [MASK] [MASK]”,这里采用了全词掩码策略

输出:对[MASK]位置的词进行预测,输出概率值

预训练过程:集成了RoBERTa和BERT-wwm的优点,对两者进行了一个自然的结合。 和之前本目录中的模型之间的区别如下:

1.3.2 代码实现
# Roberta模型的训练过程
def Roberta_train(train_file, test_file, model_save_path,out_file):
    trainer = Trainer(data_file=train_file)
    best_rouge_2 = 0.
    best_rouge_l = 0.
    train_epoches = 20
    best_save_model_path = model_save_path
    for epoch in tqdm(range(train_epoches)):
        trainer.train(epoch)
        _,results = trainer.test(model_path = None, test_file = test_file, with_metric = True, 
                                 out_file = 'saved_models/test_test_output_{}.json'.format(epoch))
        if results['rouge-2'] > best_rouge_2 or results['rouge-l'] > best_rouge_l:
            best_rouge_2 = max(results['rouge-2'], best_rouge_2)
            best_rouge_l = max(results['rouge-l'], best_rouge_l)
            best_save_model_path = model_save_path.replace('.bin','0530_{:.4f}_{:.4f}.bin'.format(results['rouge-2'], results['rouge-l']))
            trainer.save(best_save_model_path)
    trainer.test(model_path = best_save_model_path, test_file = test_file, out_file = out_file)

1.4 mT5 model

Exploring the Limits of Transfer Learning with a Unified Text-to-Text Transformer

导言:一个统一框架,靠着大力出奇迹,将所有 NLP 任务都转化成 Text-to-Text(文本到文本)任务

1.4.1 原理

mT5是T5的多语言变体,已在包含101中语言的新的基于Common Crawl的数据集中进行了预训练。mT5的模型架构和训练过程与T5紧密相似,其改进点在于:使用GeGLU非线性(Shazeer,2020年)激活函数,在更大模型中缩放dmodel而不是改变dff, 对无标签数据进行预训练而没有dropout等措施。

本项目直接加载降级处理后的mT5模型(hugging Face库中对应的版本为:csebuetnlp/mT5_multilingual_XLSum),输入文本通过tokenizer进行分词得到对应的token id (支持最大长度为512),然后调用generate函数,将编码的输入文本进行解码,目前项目在解码过程中的超参数设置如下:支持最大长度max_length=70, 解码所用的beam search所保留的beam值为4。然后将得到的generate token ids经过tokenizer解码生成具体预测的文本。

1.4.2 代码实现
def summarize(text, max_length):
    '''
      text: 要生成摘要的文本
      max_length: 摘要的最大长度
    '''
    preprocess_text = text.strip().replace('\n','')                       # 去掉多余的空格和换行符
    t5_prepared_text = 'summarize: ' + preprocess_text                    # 准备前缀+文本
    print("Preprocessed and prepared text: \n", t5_prepared_text)         # 分词
    tokenized_text = tokenizer.encode(t5_prepared_text, return_tensors="pt").to(device)
    summary_ids = model.generate(tokenized_text,                          # 进行文本摘要
                                 num_beams=4,
                                 no_repeat_ngram_size=2,
                                 min_length=30,
                                 max_length=max_length,
                                 early_stopping=True)
    output = tokenizer.decode(summary_ids[0], skip_special_tokens=True)   # 将id转换为输出 summary_ids.shape = [1, 50]
    return output

二. 评价指标

2.1 ROUGE-N

2.1.1 指标解释

ROUGE英文全称Recall-Oriented Understudy for Gisting Evaluation,专注于召回率而非精度。N指的是N-gram,它会查看有多少个参考译句中的n元词组出现在了输出之中

ROUGE-N=\frac{\sum \limits_{S\in \{ReferenceSummaries\}}\sum \limits_{gram\in S}Count_{match}(gram_N)}{\sum\limits_{S\in \{ReferenceSummaries\}}\sum\limits_{gram\in S}Count(gram_N)}

公式的分母是统计在参考译文中N-gram的个数,而分子是统计参考译文与机器译文共有的N-gram个数。

2.2 bertscore

2.2.1 指标解释

对两个生成句和参考句(word piece进行tokenize)分别用bert提取特征,然后对2个句子的每一个词分别计算内积,可以得到一个相似性矩阵。基于这个矩阵,我们可以分别对参考句和生成句做一个最大相似性得分的累加然后归一化,得到bertscore的precision,recall和F1:

R_{BERT}=\frac{1}{|x|} \sum_{x_i\in x} \max_{\hat x_j\in \hat x}x_i^T\hat x_j\\ P_{BERT}=\frac{1}{|\hat x|} \sum_{\hat x_i\in \hat x} \max_{x_j\in x}x_i^T\hat x_j\\ F_{BERT}=2\frac{P_{BERT}\cdot R_{BERT}}{P_{BERT}+R_{BERT}}

2.3 Perplexity

2.3.1 指标解释

给测试集的句子赋予较高几率值的语言模型较好,当语言模型训练完以后,测试集中的句子都是正常的句子,那么训练好的模型就是在测试集上的几率越高越好,对于句子s

S=W_1,W_2,...,W_k

它的概率为:

P(S)=P(W_1,W_2,...,W_k)=P(W_1)P(W_2|W_1)...P(W_k|W_1,W_2,...,W_{k-1})

困惑度与测试集上的句子概率相关,其基本思想是:给测试集的句子赋予较高概率值的语言模型较好,当语言模型训练完之后,测试集中的句子都是正常的句子,那么训练好的模型就是在测试集上的概率越高越好,公式如下:

PP(W)=P(w_1,w_2,...,w_N)^{-\frac1N} = \sqrt[N]{\frac{1}{P(w_1,w_2,...,w_N)}}

上一篇 下一篇

猜你喜欢

热点阅读