【小实验】“关键字”法完成新闻摘要提取

完成一个相对简单的“关键字提取”算法
思路:拥有关键词最多的句子就是最重要的句子。我们把句子按照关键词数量的多少排序,取前n句,即可汇总成我们的摘要。

步骤:

  1. 给在文章中出现的单词按照算法计算出重要性
  2. 按照句子中单词的重要性算出句子的总分
  3. 按照句子的总分给文章中的每个句子排序
  4. 取出前n个句子作为摘要
from nltk.tokenize import sent_tokenize, word_tokenize 
from nltk.corpus import stopwords
from collections import defaultdict
from string import punctuation
from heapq import nlargest

"""
nltk.tokenize 是NLTK提供的分词工具包。所谓的分词 ﴾tokenize﴿ 实际就是把段落分成句子,把句子分成一个个单词的过程。我们导入的 sent_tokenize() 函数对应的是分段为句。 word_tokenize()函数对应的是分句为词。
stopwords 是一个列表,包含了英文中那些频繁出现的词,如am, is, are。
defaultdict 是一个带有默认值的字典容器。
puctuation 是一个列表,包含了英文中的标点和符号。
nlargest() 函数可以很快地求出一个容器中最大的n个数字。
"""

stopwords = set(stopwords.words('english') + list(punctuation))
#stopwords包含的是我们在日常生活中会遇到的出现频率很高的词,如do, I, am, is, are等等,这种词汇是不应该算是我们的 关键字。同样的标点符号(punctuation)也不能被算作是关键字。

max_cut = 0.9
min_cut = 0.1
#限制了在文本中出现重要性过高过低的词。就像在跳水比赛中会去掉最高分和最低分一样。我们也需要去掉那些重 要性过高和过低的词来提升算法的效果。


def compute_frequencies(word_sent):
    """
    计算出每个词出现的频率
    :param word_sent: 是一个已经分好词的列表
    :return: 一个词典freq[], freq[w]代表了w出现的频率
    """
    freq = defaultdict(int)#defaultdict和普通的dict 的区别是它可以设置default值 参数是int默认值是0
    #统计每个词出现的频率:
    for s in word_sent:
        for word in s:
            if word not in stopwords:
                freq[word] += 1
    #得出最高出现频次m            
    m = float(max(freq.values()))
    #所有单词的频次统除m
    for w in list(freq.keys()):
        freq[w] = freq[w]/m
        if freq[w] >= max_cut or freq[w] <= min_cut:
            del freq[w]
    # 最后返回的是
    # {key:单词, value: 重要性}
    return freq

def summarize(text, n):
    """
    用来总结的主要函数
    text是输入的文本 
    n是摘要的句子个数 
    返回包含摘要的列表
    """

    # 首先先把句子分出来
    sents = sent_tokenize(text)
    assert n <= len(sents)

    # 然后再分词
    word_sent = [word_tokenize(s.lower()) for s in sents]
    # self._freq是一个词和词频率的字典
    freq = compute_frequencies(word_sent)
    #ranking则是句子和句子重要性的词典
    ranking = defaultdict(int)
    for i, word in enumerate(word_sent):
        for w in word:
            if w in freq:
                ranking[i] += freq[w]
    sents_idx = rank(ranking, n)
    return [sents[j] for j in sents_idx]

"""
考虑到句子比较多的情况 
用遍历的方式找最大的n个数比较慢 
我们这里调用heapq中的函数 
创建一个最小堆来完成这个功能 
返回的是最小的n个数所在的位置 
"""
def rank(ranking, n):
    return nlargest(n, ranking, key=ranking.get)

#运行程序
if __name__ == '__main__':
    with open("news.txt", "r") as myfile:
        text = myfile.read().replace('\n','')
    res = summarize(text, 2)
    for i in range(len(res)):
        print("* " + res[i])

分析这篇文章:脸书推出人工智能翻译,谷歌感到压力山大
得到:

  • Rather than analyze a sentence sequentially, one piece at a time, a convolutional neural network can analyze many different pieces at once, before organizing those pieces into a logical hierarchy.Even if the system is only marginally more accurate than systems like the one Google rolled out in the fall, the company says its technique is more efficient that other neural network-based methods.Others may help push the technique forward as well.
  • This past fall, Google unveiled a new translation system driven entirely by neural networks that topped existing models, and many other companies and researchers are pushing in the same direction, most notably Microsoft and Chinese web giant Baidu.But Facebook is taking a slightly different tack from most of the other big players.

疑问:

n=2 为什么这么两大段,不应该是两个句子吗?

你可能感兴趣的:(【小实验】“关键字”法完成新闻摘要提取)