如何衡量词语包含信息的多少(词频统计分析)
今天研究了一个有趣的算法,这个算法可以用来计算一段文本中每个词的权重。
是通过什么样的方式计算出每个词的权重的?
有这样的一句话:“《吐槽大会》那么火,来个段子合集,整理出来,传播会怎么样?”
如何统计每个词的权重?
统计权重的思路是这样的
- 剔除Delimiters 定界符
- 使用Jieba分词做分词
- 创建词关联的图
- 使用pagerank算法计算出权重
剔除Delimiters 定界符
确定定界符有以下这些
sentence_delimiters = [‘?’, ‘!’, ‘;’, ‘?’, ‘!’, ‘。’, ‘;’, ‘……’, ‘…’, ‘\n’]
文本剔除定界符之后就变成
'《吐槽大会》那么火,来个段子合集,整理出来,传播会怎么样'
使用Jieba分词做分词
使用jieba分词做完分词之后,输出的结果。
# 过滤停止词,过滤词性
words_all_filters = {list} <class 'list'>: [['吐', '大会', '火', '段子', '合集', '整理出来', '传播', '会']]
# 没有过滤停止词,没有过滤词性
words_no_filter = {list} <class 'list'>: [['吐', '槽', '大会', '那么', '火', '来', '个', '段子', '合集', '整理出来', '传播', '会', '怎么样']]
# 没有过滤停止词,过滤词性
words_no_stop_words = {list} <class 'list'>: [['吐', '槽', '大会', '火', '段子', '合集', '整理出来', '传播', '会']]
创建词关联的图
使用words_all_filters构建图的节点,使用words_no_stop_words来构建节点之间的边。
按照分词后,每个词出现的次序标上序号。
word_index = <class 'dict'>: {'吐': 0, '大会': 1, '火': 2, '段子': 3, '合集': 4, '整理出来': 5, '传播': 6, '会': 7}
graph = np.zeros((words_number, words_number))
# 会创建一个8*8的矩阵
如果word_list是下面这个数组:
['吐', '大会', '火', '段子', '合集', '整理出来', '传播', '会']
那么 *combine(word_list, window)* 函数中的zip方法会将word_list变成下面这样的内容。
('吐', '大会')
('大会', '火')
('火', '段子')
('段子', '合集')
('合集', '整理出来')
('整理出来', '传播')
('传播', '会')
以小的那个数组为准,压缩合并的时候。
以 ('吐', '大会’)为例,如果两个字都在word_index中,那么graph中0,1和1,0位置都会变成1。
使用pagerank算法计算出权重
使用networkx的pagerank算法计算出每个词的权重。
networkx
Networkx 是一个 Python 包,用于创建、操作和研究复杂网络的结构、动态和功能。
项目的地址:NetworkX — NetworkX
nx_graph = nx.from_numpy_matrix(graph)
scores = nx.pagerank(nx_graph, **pagerank_config) # this is a dict
sorted_scores = sorted(scores.items(), key = lambda item: item[1], reverse=True)
<class 'list'>: [(6, 0.16490795878329761), (2, 0.16490795878329756), (5, 0.15652499422860283), (3, 0.1565249942286028), (4, 0.1540263918376574), (7, 0.09106434057976046), (1, 0.09106434057976043), (0, 0.020979020979020983)]
<class 'list'>: [{'word': '传播', 'weight': 0.16490795878329761}, {'word': '火', 'weight': 0.16490795878329756}, {'word': '整理出来', 'weight': 0.15652499422860283}, {'word': '段子', 'weight': 0.1565249942286028}, {'word': '合集', 'weight': 0.1540263918376574}, {'word': '会', 'weight': 0.09106434057976046}, {'word': '大会', 'weight': 0.09106434057976043}, {'word': '吐', 'weight': 0.020979020979020983}]
最终统计出来,“《吐槽大会》那么火,来个段子合集,整理出来,传播会怎么样?”这句话中权重最高的词是传播。
权重越高意味着什么?
权重越高意味着这个词越重要,越重要意味着包含越多的信息。
后记
项目中的一些代码。
self.keywords = util.sort_words(_vertex_source, _edge_source, window = window, pagerank_config = pagerank_config)
_vertex_source
_edge_source
是两个数组,存放着使用jieba分词后的分词。
_vertex_source默认的设置是words_all_filters
使用停止词来过滤
基于词性进行过滤
Google search algorithm也是这个pagerank算法。最早被google用于做网页的排序。
用来标记每个词的权重的时候用到了一个图算法,PageRank - 维基百科,自由的百科全书
其基本假设是:更重要的页面往往更多地被其他页面引用(或称其他页面中会更多地加入通向该页面的超链接)