2021SC@SDUSC

在上一篇博客中,我们分析了TextRank4Keyword类中的函数,但实际上TextRank中词图的构建和文本预处理是由Segmentation.py和utils.py实现的,本篇博客中,我们将分析Segmentation.py和util.py两个文件,并对此次的课题进行总结。

一、util.py的分析

util.py的主要函数如下:

图1: util.py的主要函数

  • combine:构造在window下的单词组合,用来构造单词之间的边
  • get_similarity:默认的用于计算两个句子相似度的函数
  • sort_words:将单词按关键程度从大到小排序
  • sort_sentences:将句子按照关键程度从大到小排序

下面我们来一一分析这些函数,首先是combine。

1.combine函数的分析

def combine(word_list, window = 2):if window < 2: window = 2 # window过小时,初始化窗口为2for x in xrange(1, window): # 外层循环为窗口if x >= len(word_list): # 遍历完word_list,breakbreakword_list2 = word_list[x:] # 从x开始取word_listres = zip(word_list, word_list2) #利用zip打包word_list,word_list2对应位置元素for r in res:yield r

首先是参数:

  • word_list:list或str, 由单词组成的列表
  • windows:int, 窗口大小

首先遍历窗口,当遍历完word_list之后break循环,zip返回列表元素打包后的元组的列表,这里的实现逻辑非常巧妙!例如我们的window=3,也就是对于第四个词,它和它的前三个词,后三个词都有边相连。我们假定一个词列表为[]那么对于而言,[]和[]都应该被一起考虑,也就是对于,这个节点应该和这些节点有边相邻,这里我们依据图论中的定义,依旧将图的边理解成顶点,这里也就是有顶点对.理解了这些之后,我们来看这个函数的逻辑。

首先x==1,从word_list下标为1的地方开始取出子list赋给word_list2,然后用zip函数打包word_list2和word_list,也就是对应位置的元素配对成元组,之后形成列表,得到的结果非常amazing啊!就是我们需要的顶点对!这里word_list2=[],word_list=[]就是配对出了,指定x==1,就是相邻单词之间应该有边相连。x==2时,word_list2=[],word_list=[],配对除出了,也就是相隔一个单词的两个单词配对,x==3时,配对出,对于第一个点而言,配对出了,与window=3一致!

yield的作用类似于return,但可以认为带yield的函数是一个生成器,函数不是立即返回,而是依赖于之后调用next(),下一步的next开始的地方是接着上一次的next停止的地方执行的,而不是重新执行。

2.get_similarity的分析

def get_similarity(word_list1, word_list2):words   = list(set(word_list1 + word_list2)) # 列表word_list1和word_list2拼接后转为set去重    vector1 = [float(word_list1.count(word)) for word in words]# 遍历集合words中的word,对出现在list1中的计数,得到向量,出现的位置记1vector2 = [float(word_list2.count(word)) for word in words]# 遍历集合words中的word,对出现在list2中的计数,得到向量,出现的位置记1vector3 = [vector1[x]*vector2[x]  for x in xrange(len(vector1))]    # 得到向量分量相乘的结果vector4 = [1 for num in vector3 if num > 0.]# 记录大于1的结果,就是共同出现的词co_occur_num = sum(vector4)# 没有共同出现的词,相似性为0if abs(co_occur_num) <= 1e-12:return 0.denominator = math.log(float(len(word_list1))) + math.log(float(len(word_list2))) # 分母经过log处理if abs(denominator) < 1e-12:return 0.return co_occur_num / denominator

参数word_list1, word_list2 :分别代表两个句子,都是由单词组成的列表。

对于两个句子组成的list,首先合并去除共同的单词,得到合并后的集合words,然后遍历words中的word,产生两个向量,分别记录在list1和list2出现的单词,words中的word在list出现了则对应位置计作1,之后作向量对应分量的乘法,然后sum得到1的个数,其实也就是vector1和vector2共同地方出现1的次数,也就是两个list共同出现词的次数。之后处理分母,分母用了len(list)后用log处理然后对数相加后,最后返回相似性结果。

3.sort_words函数的分析

def sort_words(vertex_source, edge_source, window = 2, pagerank_config = {'alpha': 0.85,}):sorted_words   = []word_index     = {}index_word     = {}_vertex_source = vertex_source_edge_source   = edge_source#初始化word_number为0,是对应vocabulary的词的索引words_number   = 0 

sort_words函数实现了将单词按重要性程度从大到小排序,首先分析函数的参数:

  • vertex_source:二维列表,子列表代表句子,子列表的元素是单词,这些单词用来构造pagerank中的节点
  • edge_source:二维列表,子列表代表句子,子列表的元素是单词,根据单词位置关系构造pagerank中的边
  • window:一个句子中相邻的window个单词,两两之间认为有边
  • pagerank_config:pagerank的设置
# 遍历每一个sentence
for word_list in _vertex_source:# 遍历sentence中的wordfor word in word_list:# word没有出现在word_index中if not word in word_index:word_index[word] = words_number # 记录word2idxindex_word[words_number] = word # 记录idx2wordwords_number += 1

若list中句子的word没有出现在word_index中,则令word_index字典的word索引的value为words_number,同时初始化index_word的key为words_number的value为word,之后words_number自增。这里的处理和我们之前分析的vocabulary类非常相似。

graph = np.zeros((words_number, words_number))
# 初始化图的邻接矩阵for word_list in _edge_source:for w1, w2 in combine(word_list, window):# 取出combine的w1和w2if w1 in word_index and w2 in word_index:index1 = word_index[w1] # 获得配对的单词的索引index2 = word_index[w2]graph[index1][index2] = 1.0 # 无向图边赋值,对称矩阵graph[index2][index1] = 1.0debug('graph:\n', graph)

通过刚才的初始化 ,我们已经构建好了词和索引的对应字典,记录下了语料库中所有单词的总数,为words_number,初始化图为words_number*words_number大小的邻接矩阵,对于指定格式的_edge_source,通过conbine函数,得到了途中的顶点对,这里用表示,然后取出,用word2idx获得两个点的索引,(注意这里的仍然还是单词word的形式)然后在对应索引处的邻接矩阵位置赋值,最后完成了图的初始化。

nx_graph = nx.from_numpy_matrix(graph)
scores = nx.pagerank(nx_graph, **pagerank_config)
sorted_scores = sorted(scores.items(), key = lambda item: item[1], reverse=True)
# 按序排列分数
for index, score in sorted_scores:
# 遍历sorted_scoresitem = AttrDict(word=index_word[index], weight=score)# 通过idx2word找到单词sorted_words.append(item)# 返回排序好的单词
return sorted_words

得到graph后,经过pagerank计算可以得到scores,我们得到的是词典的形式,然后遍历sorted_scores,通过idx2word找到word(因为图的构建经过了一遍word2idx换成了索引形式),同时加入score,遍历完之后就能得到排序好的单词。

二、Segmentation.py的分析

Segmentation.py的主要函数如下:

图2:Segmentation.py的类与函数

  • WordSegmentation:该类主要用来分词,有init函数、segment函数和segment_sentence函数
  • SentenceSegmentation:该类主要用来分句,有init函数,segment函数
  • Segmentation:基于WordSegmentation类和SentenceSegmentation类实现,有init函数和segment函数

这里我们将简单分析WordSegmentation类及其函数。

1.init函数

    def __init__(self, stop_words_file = None, allow_speech_tags = util.allow_speech_tags):  allow_speech_tags = [util.as_text(item) for item in allow_speech_tags]# 默认的speech_tag_filter为allow_speech_tagsself.default_speech_tag_filter = allow_speech_tags# 初始化stop_words为空集合self.stop_words = set()self.stop_words_file = get_default_stop_words_file()if type(stop_words_file) is str:# 指定stop_words_file路径self.stop_words_file = stop_words_filefor word in codecs.open(self.stop_words_file, 'r', 'utf-8', 'ignore'):# 加入stop_words_file中的stop_words(删除空格)self.stop_words.add(word.strip())
  • stop_words_file:保存停止词的文件路径,utf8编码,每行一个停止词。若不是str类型,则使用默认的停止词
  • allow_speech_tags:词性列表,用于过滤

首先是初始化stop_words和stop_words_file,读stop_words_file后取出每一个单词,加入stop_words集合中,这个函数主要说明了stopwords。

2.segment函数

    def segment(self, text, lower = True, use_stop_words = True, use_speech_tags_filter = False):text = util.as_text(text)jieba_result = pseg.cut(text) # 对文本进行分词# 是否采用词性过滤if use_speech_tags_filter == True:jieba_result = [w for w in jieba_result if w.flag in self.default_speech_tag_filter]else:jieba_result = [w for w in jieba_result]# 去除特殊符号word_list = [w.word.strip() for w in jieba_result if w.flag!='x']word_list = [word for word in word_list if len(word)>0]# 对于word_list每个单词取小写if lower:word_list = [word.lower() for word in word_list]# 去除停词if use_stop_words:word_list = [word.strip() for word in word_list if word.strip() not in self.stop_words]return word_list

segment函数对一段文本进行分词,并返回list类型的分词结果 。其参数如下:

  • lower:是否将单词小写(英文)
  • use_stop_words:若为True,则利用停止词集合来过滤(去掉停止词)
  • use_speech_tags_filter:是否基于词性进行过滤。若为True,则使用self.default_speech_tag_filter过滤。否则不过滤

首先是用jieba对文本初步分词,然后用单词的flag进行词性过滤,接着判断是否去除特殊符号和是否小写,是否去除停词,注意word.strip()的调用。

3.segment_sentence函数

    def segment_sentences(self, sentences, lower=True, use_stop_words=True, use_speech_tags_filter=False):res = []# 遍历每一个句子for sentence in sentences:# 调用segment函数res.append(self.segment(text=sentence, lower=lower, use_stop_words=use_stop_words, use_speech_tags_filter=use_speech_tags_filter))return res

该函数将列表sequences中的每个元素/句子转换为由单词构成的列表,输入参数sequences为列表,每个元素是一个句子(字符串类型)

对于每一个句子,调用segment函数,采用小写,使用停词,过滤符号列表的形式。也就是segment函数实现了对一句话的分词,segment_sentence函数通过调用segment函数对很多句话分词。

至此,我们已经完成了对TextRank4ZH的大致分析,也完成了此次项目源码的分析,通过这门课程,我还是收获很多的。

无监督关键短语的生成问题博客13--Segmentation.py的分析相关推荐

  1. 无监督关键短语的生成问题博客02--extract.py的分析

    2021SC@SDUSC 在上一篇博客中,我们小组各位成员阅读了<Unsupervised Deep Keyphrase Generation>这篇论文,了解了这一关键词抽取模型的任务与主 ...

  2. 无监督关键短语的生成问题博客07--create_vocabulary.py的分析

    2021SC@SDUSC 本文我们将分析create_vocabulary.py文件,该文件主要的功能是创立了一个词典,统计了文本的所有词和词对应的索引,以便后续的指标的计算和处理,将得到的结果保存到 ...

  3. 无监督关键短语的生成问题01--综述

    2021SC@SDUSC 一.问题背景 关键短语提取(Keyphrase generation)可以得到一个能够总结输入的长文档的短语列表,被广泛应用于信息检索.文本总结.文本分类等领域.研究表明,对 ...

  4. 使用hugo生成静态博客并部署在GitHub上

    使用hugo生成静态博客并部署在GitHub上 hugo是一个用Go语言编写的静态网页生成器,只需要一个命令 hugo 就可以在几秒钟内生成一个静态的博客页面,被称为世界上最快的网站构建框架,使hug ...

  5. 博客搜索引擎索引博文数量分析与评估

    /*版权声明:可以任意转载,转载时请务必标明文章原始出处和作者信息 .*/                              博客搜索引擎索引博文数量分析与评估                 ...

  6. 无需成对示例、无监督训练,CycleGAN生成图像简直不要太简单

    作者 |  Jason Brownlee 译者 |  Freesia,Rachel 编辑 |  夕颜 出品 | AI科技大本营(ID: rgznai100) [导读]图像到图像的转换技术一般需要大量的 ...

  7. 无服务器+域名也能搭建个人博客?真的,而且很快

    基于Gitee快速搭建个人博客 一. 背景 个人搭建博客也是有成本的 关于 jekyll 二. 部署 拉取代码 修改和上传配置 _config.yml locale.yml 构建和访问(gitee部署 ...

  8. ChatGPT写作:快速生成优质博客文章的神器

    今天我们将聊聊如何使用ChatGPT快速生成优质的博客文章,并且在短时间内提高写作效率. 首先,让我们简单介绍一下ChatGPT.它是一种基于深度学习的自然语言处理模型,能够自动地生成人类般的文本.通 ...

  9. 基于selenium生成Csdn 博客文章简索的excel文件

    Csdn 上各大博主的博客文章很有参考价值和独特见解,查看起来总觉得不是特别的方便.于是抽空用selenium 做了个简索生成工具.生成的是excel 2007的文章格式. 截图一 截图二 截图三 截 ...

最新文章

  1. 真正的全栈工程师!B站硬核UP主自己造了一个激光雷达
  2. 观察者模式及Java实现例子
  3. 特征选择---文本分类:叉方统计量
  4. python numpy库安装 mac_教程|如何在mac上为Python安装XGBoost!
  5. 如何优雅的激怒C/C++程序员
  6. matlab如何将相近的数据,matlab新手,求帮助!主要是如何将数据和公式导入
  7. [vue] 你知道nextTick的原理吗?
  8. SUN服务器清除所有报错信息,SUN服务器可能遇到的问题总结.doc
  9. 华为c语言编程规范_C语言编程规范
  10. cocos2d-x和objective-c中的retain()和release()
  11. 关于max(X,Y),min(X,Y)
  12. django 之模板层
  13. AOP如何实现及实现原理
  14. (转)Hinton、LeCun和Bengio——深度学习综述
  15. Python列表(list)练习题
  16. 三星 android 调试模式设置,三星 W2016 开启USB调试模式
  17. scanf可以输入负数吗_在excel表格中输入负数应该怎样输
  18. jstat命令查看jvm的GC情况
  19. vrchat模型房_VRChat之blender教程
  20. iOS:简易的音视屏播放框架XYQPlayer

热门文章

  1. 数组大小分配(动态内存分配)
  2. java实现棋盘上的麦子
  3. sql语句——创建临时表
  4. 关于SSL握手的错误解决
  5. 写作经典中的经典——《文心》的读后感作文3600字
  6. Vue大屏实战一:数字翻牌器的实现
  7. Animations的用法
  8. 2023~2023年springboot计算机毕业设计选题
  9. Foursquare解密创新商机
  10. SNS平台ConcourseConnect