如果你是科研狗,一定有过被摘要支配的恐惧。
如果你想在浩如烟海的互联网信息里寻找重点,一定想要快速排除多余的内容。
基于机器学习的自动文本摘要工具,将一键解放你的双手,化身抓重点小能手,为你捕捉关键,排除冗余。
近日,有位叫Alfrick Opidi的小哥在入门级深度学习云平台FloydHub 上写了一篇关于自动文本摘要的入门教程,量子位对其进行了编译,希望能帮助大家理解。
自动文本摘要属于自然语言处理(NLP)的范畴,通常用机器学习算法来实现,目前实现的方法主要有两种:
抽取式
就像一支荧光笔,抽取式文本摘要就是给原始文本中的重点单词标上高亮,再将其加以组合形成摘要。
概要式
概要式文本摘要更接近于人类的思维——通过深度学习对原始文本进行释义并提炼主旨,而后形成摘要。相比于抽取式,概要式文本摘要更像在说人话。
很显然概要式的表现会比抽取式更好,然而这种算法需要复杂的深度学习技术和语言模型支撑,还面临这诸如自然语言生成这样的NLP问题。
因此抽取式方法仍然广泛流行。
鉴于本文是一篇入门指南,接下来提到的内容都是基于抽取式方法来实现的。
文本摘要基础步骤
文本摘要是如何实现的呢?
举个例子,用文本摘要机器学习算法来对下面这段文字进行处理:
夜里志明和春娇乘坐出租车去城里聚会。聚会上春娇晕倒并被送进了医院。她被诊断出患有脑损伤,医生告诉志明要一直陪着她直到她好起来。因此,志明待在医院整整陪了她三天。
第一步:把段落转成句子
首先要做的是分割段落。
- 夜里志明和春娇乘坐出租车去城里聚会
- 聚会上春娇晕倒并被送进了医院
- 她被诊断出患有脑损伤,医生告诉志明要一直陪着她直到她好起来
- 因此,志明待在医院整整陪了她三天
第二步:文本处理
接下来,删掉没什么意义的连接词、数字、标点。
就像这样:
- 夜里志明春娇乘坐出租车去城里聚会
- 聚会春娇晕倒送医院
- 诊断脑损伤医生告诉志明陪着好起来
- 志明待在医院天
第三步:标注
然后,对句子进行标记,获得句子中的所有单词:
[‘志明’,‘春娇’,‘乘坐’,‘出租车’,‘去’,‘夜里’,‘聚会’,‘城里‘,‘聚会’,‘春娇’,‘晕倒’,‘医院’,‘诊断’,‘脑’,‘损伤’,‘医生’,‘告诉’,‘志明’,‘陪’,‘好起来’,‘志明’,‘待’,‘医院’,‘天’]
第四步:评估单词的加权出现频率
现在就可以计算单词们的加权出现频率了。
计算公式是:单词加权出现频率 = 单词出现次数 / 段落中最常用单词出现次数
第五步:用加权频率替换单词
把句子中的每个单词都替换成加权频率,就可以计算这个句子的权重。比如在志明和春娇这个例子当中,第一句在整个段落中的权重是最大的,那么它就将构成摘要的主体部分。
以上是机器学习实现文本摘要的基本步骤,下面我们来看看如何在真实世界中构建摘要生成器。
亲手构建摘要生成器
使用Python的NLTK工具包,我们可以亲自动手创造一个文本摘要生成器,实现对Web文章的摘要生成。
来看看代码蓝图:
1 # Creating a dictionary for the word frequency table
2 frequency\_table = \_create\_dictionary\_table(article)
3
4 # Tokenizing the sentences
5 sentences = sent\_tokenize(article)
6
7 # Algorithm for scoring a sentence by its words
8 sentence\_scores = \_calculate\_sentence\_scores(sentences, frequency\_table)
9
10 # Getting the threshold
11 threshold = \_calculate\_average\_score(sentence\_scores)
12
13 # Producing the summary
14 article\_summary = \_get\_article\_summary(sentences, sentence\_scores, 1.5 * threshold)
15
16 print(article\_summary)
第一步:准备数据
这里使用了Beautiful Soup库。
1 import bs4 as BeautifulSoup
2 import urllib.request
3
4 # Fetching the content from the URL
5 fetched\_data = urllib.request.urlopen('https://en.wikipedia.org/wiki...\_century')
6
7 article\_read = fetched\_data.read()
8
9 # Parsing the URL content and storing in a variable
10 article\_parsed = BeautifulSoup.BeautifulSoup(article\_read,'html.parser')
11
12 # Returning
tags
13 paragraphs = article\_parsed.find\_all('p')
14
15 article\_content = ''
16
17 # Looping through the paragraphs and adding them to the variable
18 for p in paragraphs:
19 article\_content += p.text
使用urllib.request实现网页数据的抓取,再调用BeautifulSoup来解析网页数据。
第二步:数据处理
为确保抓取到的文本数据尽可能没有噪音,需要做一些基本的文本清理。这里使用了NLTK的stopwords和PorterStemmer。
PorterStemmer可以将单词还原为词根形式,就是说能把 cleaning, cleaned, cleaner 都还原成 clean。
此外还要创建一个字典,来存储文本中每一个单词的出现频率。
循环整个文本来消除 “a”、“the” 这样的停止词,并记录单词们的出现频率。
1from nltk.corpus import stopwords
2from nltk.stem import PorterStemmer
3def \_create\_dictionary\_table(text\_string) -> dict:
4
5 # Removing stop words
6 stop\_words = set(stopwords.words("english"))
7
8 words = word\_tokenize(text\_string)
9
10 # Reducing words to their root form
11 stem = PorterStemmer()
12
13 # Creating dictionary for the word frequency table
14 frequency\_table = dict()
15 for wd in words:
16 wd = stem.stem(wd)
17 if wd in stop\_words:
18 continue
19 if wd in frequency\_table:
20 frequency\_table[wd] += 1
21 else:
22 frequency\_table[wd] = 1
23
24 return frequency\_table
第三步:将文章标注成句子
1 from nltk.tokenize import word\_tokenize, sent\_tokenize
2
3 sentences = sent\_tokenize(article)
第四步:计算句子的权重
句子的权重取决于它包含的单词的出现频率。
1def \_calculate\_sentence\_scores(sentences, frequency\_table) -> dict:
2
3 # Algorithm for scoring a sentence by its words
4 sentence\_weight = dict()
5
6 for sentence in sentences:
7 sentence\_wordcount = (len(word\_tokenize(sentence)))
8 sentence\_wordcount\_without\_stop\_words = 0
9 for word\_weight in frequency\_table:
10 if word\_weight in sentence.lower():
11 sentence\_wordcount\_without\_stop\_words += 1
12 if sentence[:7] in sentence\_weight:
13 sentence\_weight[sentence[:7]] += frequency\_table[word\_weight]
14 else:
15 sentence\_weight[sentence[:7]] = frequency\_table[word\_weight]
16
17 sentence\_weight[sentence[:7]] = sentence\_weight[sentence[:7]] / sentence\_wordcount\_without\_stop\_words
18
19 return sentence\_weight
需要注意的是,长句有可能得到不必要的高分,为了避免这一点,要将句子的总分数除以该句的单词数。
第五步:计算句子的阈值
为了进一步优化结果,要计算句子的平均分数。使用此阈值,可以避免分数较低的句子的干扰。
1def \_calculate\_average\_score(sentence\_weight) -> int:
2
3 # Calculating the average score for the sentences
4 sum\_values = 0
5 for entry in sentence\_weight:
6 sum\_values += sentence\_weight[entry]
7
8 # Getting sentence average value from source text
9 average\_score = (sum\_values / len(sentence\_weight))
10
11 return average\_score
如果感兴趣,FloydHub提供了进行深度学习模型训练的环境,你可以在FloydHub Notebook上运行整个代码。
还可以更上档次
以上只是机器学习中文本摘要算法的入门小知识,想要达到更上档次的效果,甚至可以把抽取式方法和概要式方法结合起来。
△ 图片来自Taming Recurrent Neural Networks for Better Summarization
传送门
如果还想更深入地了解机器学习中的文本摘要,不妨看看以下资源。
WikiHow,一个大规模、高质量的文本摘要数据集:
https://www.wikihow.com/Main-...
WikiHow食用指南:
https://arxiv.org/pdf/1810.09...
用指针生成网络(Pointer-Generator Networks)实现文本摘要:
https://arxiv.org/pdf/1704.04...
http://www.abigailsee.com/201...
如何在文本摘要中使用基于预训练的编码器-解码器框架:
https://arxiv.org/pdf/1902.09...
原文链接:
https://blog.floydhub.com/gen...
— 完 —
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。