当前位置
主页 > 成功案例 >
用Python阐发《三国演义》中的社交网络
2022-05-09 00:13
本文摘要:用Python阐发《三国演义》中的社交网络 媒介 一直以来对自然语言处置惩罚和社交网络阐发都很感乐趣,前者能帮忙我们从文本中得到许多发明,尔后者可以或许让我们对人们和各个事物之间普遍存在的网络般的接洽有更多认识。当二者联合,又会有奈何的魔力呢? 作为一个三国迷,我就有了这样的想法:能不能用文本处置惩罚的方法,获得《三国演义》中的人物社交网络,再举行阐发呢?python中有许多好东西可以或许帮忙我实践我好奇的想法,此刻就开始动手吧。筹办事情 得到《三国演义》的文本。

凯发k8APP下载

用Python阐发《三国演义》中的社交网络 媒介 一直以来对自然语言处置惩罚和社交网络阐发都很感乐趣,前者能帮忙我们从文本中得到许多发明,尔后者可以或许让我们对人们和各个事物之间普遍存在的网络般的接洽有更多认识。当二者联合,又会有奈何的魔力呢? 作为一个三国迷,我就有了这样的想法:能不能用文本处置惩罚的方法,获得《三国演义》中的人物社交网络,再举行阐发呢?python中有许多好东西可以或许帮忙我实践我好奇的想法,此刻就开始动手吧。筹办事情 得到《三国演义》的文本。chapters = get_sanguo # 文本列表,每个元素为一章的文本 print(chapters[ 0][ :106]) 第一回 宴桃园好汉三结义 斩黄巾英雄首建功 滔滔长江东逝水,浪花淘尽英雄。

长短成败回头空。青山依旧在,几度落日红。鹤发渔樵江渚上,惯看秋月东风。

一壶浊酒喜相逢。古今几多事,都付笑谈中 《三国演义》并不是很容易处置惩罚的文本,它靠近古文,我们碰面对昔人的字号等一系列别名。好比电脑怎么知道“玄德”指的就是“刘备”呢?那就要我们给它一些常识。

我们人通过进修知道“玄德”是刘备的字,电脑也可以用雷同的方法完成这个观点的毗连。我们需要告诉电脑,“刘备”是实体(雷同于一个对象的尺度名),而“玄德”则是“刘备”的一个指称,告诉的方式,就是提供电脑一个常识库。entity_mention_dict, entity_type_dict = get_sanguo_entity_dict print( "刘备的指称有:",entity_mention_dict[ "刘备"]) 刘备的指称有:[ '刘备', '刘玄德', '玄德', '使君'] 除了人的实体和指称以外,我们也可以或许包括三国势力等此外类型的指称,好比“蜀”又可以叫“蜀汉”,所以常识库里还可以包括实体的类型信息来加以区分。print( "刘备的类型为",entity_type_dict[ "刘备"]) print( "蜀的类型为",entity_type_dict[ "蜀"]) print( "蜀的指称有",entity_mention_dict[ "蜀"]) 展开全文 刘备的类型为 人名 蜀的类型为 势力 蜀的指称有 [ '蜀', '蜀汉'] 有了这些常识,理论上我们就可以编程接洽起实体的各个外号啦。

不外若是要重新做起的话,个中还会有不少的事情量。而HarvestText[1]是一个封装了这些步骤的文本处置惩罚库,可以帮忙我们轻松完成这个任务。

ht = HarvestText ht.add_entities(entity_mention_dict, entity_type_dict) # 加载模型 print(ht.seg( "誓毕,拜玄德为兄,关羽次之,张飞为弟。",standard_name= True)) [ '誓毕', ',', '拜', '刘备', '为兄', ',', '关羽', '次之', ',', '张飞', '为弟', '。

'] 社交网络成立 乐成地把指称统一到尺度的实体名以后,我们就可以着手挖掘三国的社交网络了。详细的成立方式是操纵相近共现关系。

每当一对实体在两句话内同时呈现,就给它们加一条边。那么成立网络的整个流程就如同下图所示: 我们可以使用HarvestText提供的函数直接完成这个流程,让我们先在第一章的小文本上实践一下: # 筹办事情 doc = chapters[0].replace( "操", "曹操") # 由于有时使用缩写,这里做一个微调 ch1_sentences = ht.cut_sentences(doc) # 分句 doc_ch01 = [ch1_sentences[i]+ch1_sentences[i+1] fori inrange(len(ch1_sentences)-1)] #得到所有的二连句 ht.set_linking_strategy( "freq") # 成立网络 G = ht.build_entity_graph(doc_ch01, used_types=[ "人名"]) # 对所有人物成立网络,即社交网络 # 挑选主要人物绘图 important_nodes = [node fornode inG.nodes ifG.degree[node]>=5] G_sub = G.subgraph(important_nodes).copy draw_graph(G_sub,alpha=0.5,node_scale=30,figsize=(6,4)) 他们之间详细有什么关系呢?我们可以操纵文本摘要获得本章的详细内容: stopwords = get_baidu_stopwords #过滤停用词以提高质量 fori,doc inenumerate(ht.get_summary(doc_ch01, topK=3, stopwords=stopwords)): print(i,doc) 玄德见皇甫嵩、朱儁,具道卢植之意。嵩曰:“张梁、张宝势穷力乏,必投广宗去依张角。

时张角贼众十五万,植兵五万,相拒于广宗,未见胜负。植谓玄德曰:“我今围贼在此,贼弟张梁、张宝在颍川,与皇甫嵩、朱儁对垒。越日,于桃园中,备下乌牛白马祭礼等项,三人焚香再拜而说誓曰:“念刘备、关羽、张飞,虽然异姓,既结为兄弟,则同心合力, 本章的主要内容,看来就是刘关张桃园三结义,而且共抗黄巾贼的故事。

三国全网络绘制 有了小规模实践的基础,我们就可以用同样的方法,整合每个章节的内容,画出一张高出三国各代的大图。G_chapters = [] forchapter in chapter s: sentences = ht.cut_sentences(chapter) # 分句 docs = [sentences[i]+sentences[i+ 1] fori in range( len(sentences)- 1)] G_chapters. append(ht.build_entity_graph(docs, used_types=[ "人名"])) # 归并各张子图 G_global = nx.Graph forG0 in G_chapter s: for( u,v) in G0.edge s: ifG_global.has_edge( u,v): G_global[ u][v][ "weight"] += G0[ u][v][ "weight"] else: G_global.add_edge( u,v,weight=G0[ u][v][ "weight"]) # 忽略游离的小分支只取最大连通分量 largest_comp = max(nx.connected_components(G_global), key= len) G_global = G_global.subgraph(largest_comp). copy print(nx.info(G_global)) Name: Type: Graph Number of node s:1290 Number of edge s:10096 Average degree: 15.6527 整个社交网络有1290小我私家那么多,另有上万条边!那么我们要把它画出来险些是不行能的,那么我们就挑选个中的关键人物来画出一个子集吧。important_nodes= [node for node in G_global.nodes if G_global.degree[node]>= 30] G_main= G_global.subgraph(important_nodes).copy 用pyecharts举行可视化 frompyecharts importGraph nodes = [{ "name": "结点1", "value": 0, "symbolSize": 10} fori inrange(G_main.number_of_nodes)] fori,name0 inenumerate(G_main.nodes): nodes[i][ "name"] = name0 nodes[i][ "value"] = G_main.degree[name0] nodes[i][ "symbolSize"] = G_main.degree[name0] / 10.0 links = [{ "source": "", "target": ""} fori inrange(G_main.number_of_edges)] fori,(u,v) inenumerate(G_main.edges): links[i][ "source"] = u links[i][ "target"] = v links[i][ "value"] = G_main[u][v][ "weight"] graph = Graph( "三国人物关系力导引图") graph.add( "", nodes, links) graph.render( "./images/三国人物关系力导引图.html") graph 博客上不能显示交互式图表,这里就给出截图:显示了刘备的毗邻结点 整个网络错综庞大,背后是三国故事中无数的南征北伐、钩心斗角。

不外有了计较机的强大算力,我们依然可以从中梳理出某些关键线索,好比: 人物排名-重要性 对这个问题,我们可以用网络中的排序算法解决。PageRank就是这样的一个典型方法,它原来是搜索引擎操纵网站之间的接洽对搜索成果举行排序的方法,不外对人物之间的接洽也是同理。让我们得到最重要的20大人物: page_ranks= pd.Series(nx.algorithms.pagerank(G_global)).sort_values page_ranks.tail( 20).plot(kind= "barh") plt.show 《三国演义》见义勇为的主角就是他们了,哪怕你对三国不熟悉,也必然会对这些人物耳熟能详。

人物排名-权力值 这个问题看上去跟上面一个问题很像,但其实还是有区此外。就像人缘最好的人未必是带领一样,能在团队中心起到凝结感化,使各个成员彼此接洽互助的人才是最有权力的人。

中心度就是这样的一个指标,看看三国中最有权力的人是哪些吧? between= pd.Series(nx.betweenness_centrality(G_global)).sort_values between.tail( 20).plot(kind= "barh") plt.show 成果简直和上面的排序有所差别,我们看到刘备、曹操、孙权、袁绍等主公都压倒一切。而另一个有趣的发明是,司马懿、司马昭、司马师父子三人同样榜上有名,而曹氏的其他后裔则不见其名,可见司马氏之权倾朝野。司马氏之心,似乎就这样被大数据展现了出来! 社群发明 人物关系有亲疏远近,因此往往会形成一些集团。

社交网络阐发里的社区发明算法就可以或许让我们发明这些集团,让我使用community库[2]中的提供的算法来展现这些关系吧。importcommunity # python-louvain partition = community.best_partition(G_main) # Louvain算法划分社区 comm_dict = defaultdict(list) forperson inpartition: comm_dict[partition[person]].append(person) 在下面3个社区里,我们看到的主要是魏蜀吴三国重臣们。(只有一些小“问题”,有趣的是,电脑并不知道他们的所属势力,只是使用算法。) draw_community( 2) community2: 张辽 曹仁 夏侯惇 徐晃 曹洪 夏侯渊 张郃 许褚 乐进 李典 于禁 荀彧 刘晔 郭嘉 满宠 程昱 荀攸 吕虔 典韦 文聘 董昭 毛玠 draw_community( 4) community4: 曹操 诸葛亮 刘备 关羽 赵云 张飞 马超 黄忠 许昌 孟达 [魏]孙乾 曹安民 刘璋 关平 庞德 法正 伊籍 张鲁 刘封 庞统 孟获 严颜 马良 简雍 蔡瑁 陶谦 孔融 刘琮 [刘表子]刘望之 夏侯楙 周仓 陈登 draw_community( 3) community 3: 孙权 孙策 周瑜 陆逊 吕蒙 丁奉 周泰 程普 韩当 徐盛 张昭[吴] 马相 黄盖[吴] 潘璋 甘宁 鲁肃 凌统 太史慈 诸葛瑾 韩吴郡 蒋钦 黄祖 阚泽 朱桓 陈武 吕范 draw_community( 0) community0: 袁绍 吕布 刘表 袁术 董卓 李傕 贾诩 审配 孙坚 郭汜 陈宫 马腾 袁尚 韩遂 公孙瓒 高顺 许攸 [袁绍]臧霸 沮授 郭图 颜良 杨奉 张绣 袁谭 董承 文丑 何进 张邈 [魏]袁熙 另有一些其他社区。

好比在这里,我们看到三国前期,孙坚、袁绍、董卓等主公们群雄逐鹿,好不热闹。draw_community( 1) community1: 司马懿 魏延 姜维 张翼 马岱 廖化 吴懿 司马昭 关兴 吴班 王平 邓芝 邓艾 张苞 [蜀]马忠 [吴]费祎 谯周 马谡 曹真 曹丕 李恢 黄权 钟会 蒋琬 司马师 刘巴 [蜀]张嶷 杨洪 许靖 费诗 李严 郭淮 曹休 樊建 秦宓 夏侯霸 杨仪 高翔 张南 [魏]华歆 曹爽 郤正 许允 [魏]王朗 [司徒]董厥 杜琼 霍峻 胡济 贾充 彭羕 吴兰 诸葛诞 雷铜 孙綝 卓膺 费观 杜义 阎晏 盛勃 刘敏 刘琰 杜祺 上官雝 丁咸 爨习 樊岐 曹芳 周群 这个社区是三国后期的主要人物了。这个网络背后的故事,是司马氏两代三人打败姜维率领的蜀汉群雄,又打扫了曹魏内部的曹家势力,终于登上权力的巅峰。

动态网络 研究社交网络随时间的变化,是个很有意思的任务。而《三国演义》大抵根据时间线叙述,且有着极长的时间跨度,顺着故事线往下走,社交网络会产生什么样的变化呢? 这里,我取10章的文本作为跨度,每5章记载一次当前跨度中的社交网络,就相当于留下一张快照,把这些快照毗连起来,我们就可以或许看到一个社交网络变化的动画。快照还是用networkx获得,而建造动画,我们可以用moviepy。山河代有秀士出,让我们看看在故事成长的各个阶段,都是哪一群人活跃在舞台中央呢? importmoviepy.editor asmpy frommoviepy.video.io.bindings importmplfig_to_npimage width, step = 10, 5 range0 = range( 0,len(G_chapters)-width+ 1,step) numFrame, fps = len(range0), 1 duration = numFrame/fps pos_global = nx.spring_layout(G_main) defmake_frame_mpl(t): i = step*int(t*fps) G_part = nx.Graph forG0 inG_chapters[i:i+width]: for(u,v) inG0.edges: ifG_part.has_edge(u,v): G_part[u][v][ "weight"] += G0[u][v][ "weight"] else: G_part.add_edge(u,v,weight=G0[u][v][ "weight"]) largest_comp = max(nx.connected_components(G_part), key=len) used_nodes = set(largest_comp) & set(G_main.nodes) G = G_part.subgraph(used_nodes) fig = plt.figure(figsize=( 12, 8),dpi= 100) nx.draw_networkx_nodes(G,pos_global,node_size=[G.degree[x]* 10forx inG.nodes]) # nx.draw_networkx_edges(G,pos_global) nx.draw_networkx_labels(G,pos_global) plt.xlim([ -1, 1]) plt.ylim([ -1, 1]) plt.axis( "off") plt.title( f"第 {i+ 1} 到第 {i+width+ 1} 章的社交网络" ) returnmplfig_to_npimage(fig) animation = mpy.VideoClip(make_frame_mpl, duration=duration) animation.write_gif("./images/三国社交网络变化.gif", fps=fps) 雅观起见,动画中省略了网络中的边。

跟着时间的变化,曾经站在汗青舞台中央的人们也渐渐地会渐渐脱离,让人不禁唏嘘叹息。正如《三国演义》开篇所言: 古今几多事,都付笑谈中。

本日,小辈操纵python做的一番笑谈也就到此竣事吧…… 注: [0] 本文受到了数据森麟前面的 “水泊梁山“互联网有限公司一百单八将内部社交网络 极大的开导,很兴奋可以或许打仗到这些有趣的数据阐发,和这一群有趣的人~ [1] harvesttext是本人的作品~(*__*) ~,已在Github上开源并可通过pip直接安装,旨在帮忙使用者更等闲地完成像本文这样的文本数据阐发。除了本文涉及的功效以外,另有感情阐发、新词发明等功效。大家以为有用的话,不妨亲身实验下,看看能不能在本身感乐趣的文本上有更多有趣有用的发明呢? [2]commutity库的本名是python-louvain,使用了和Gephi内置沟通的Louvain算法举行社区发明 [3]由于处置惩罚古文的坚苦性,本文中依然有一些比力明明的错误,但愿大家不要介怀~ ◆ ◆ ◆ ◆ ◆返回,检察更多。


本文关键词:凯发k8APP下载,用,Python,阐发,《,三国演义,》,中的,社交,网络

本文来源:凯发k8APP下载-www.luanbanya.com

联系方式

电话:053-40198084

传真:0180-87793988

邮箱:admin@luanbanya.com

地址:湖北省宜昌市海原县视高大楼6836号