재미있는 재미 - '삼국지'에서 Python을 사용하여 소셜 네트워크 분석

풀어 주다: 2019-04-04 17:37:15
앞으로
2836명이 탐색했습니다.

저는 항상 자연어 처리와 소셜 네트워크 분석에 관심이 있었습니다. 전자는 텍스트에서 많은 발견을 하는 데 도움이 되고 후자는 사람 간의 관계를 이해하는 데 도움이 됩니다. 유비쿼터스 네트워크와 같은 연결에 대한 인식이 높아졌습니다. 이 둘이 합쳐지면 어떤 마법이 생길까요? 삼국지 팬으로서 저는 이런 생각을 했습니다. '삼국지'에 등장하는 등장인물의 소셜 네트워크를 텍스트 처리 방법으로 얻은 다음 분석할 수 있을까요? Python에는 내 호기심 많은 아이디어를 구현하는 데 도움이 되는 좋은 도구가 많이 있습니다. 지금 시작해 보겠습니다.

재미있는 재미 - 삼국지에서 Python을 사용하여 소셜 네트워크 분석

준비

'3인의 로맨스' 텍스트 가져오기 왕국"# 🎜🎜#.

chapters = get_sanguo()                 # 文本列表,每个元素为一章的文本print(chapters[0][:106])第一回 宴桃园豪杰三结义 斩黄巾英雄首立功滚滚长江东逝水,浪花淘尽英雄。是非成败转头空。青山依旧在,几度夕阳红。白发渔樵江渚上,惯看秋月春风。一壶浊酒喜相逢。古今多少事,都付笑谈中
로그인 후 복사

『삼국지』는 다루기 쉬운 텍스트가 아니며 고대 텍스트에 가깝고 글꼴 크기와 같은 일련의 별칭을 직면하게 됩니다. 고대인의. 예를 들어, 컴퓨터는 "Xuande"가 "Liu Bei"를 의미한다는 것을 어떻게 알 수 있습니까? 그런 다음 우리는 그것에 약간의 지식을 주어야 합니다. 우리 인간은 연구를 통해 "선덕"이 유비의 캐릭터라는 것을 알고 있으며, 컴퓨터도 비슷한 방법을 사용하여 이 개념의 연결을 완성할 수 있습니다. "Liu Bei"는 개체(객체의 표준 이름과 유사)이고 "Xuande"는 "Liu Bei"에 대한 참조임을 컴퓨터에 알려야 합니다. 지식 기반.


entity_mention_dict, entity_type_dict = get_sanguo_entity_dict()
print("刘备的指称有:",entity_mention_dict["刘备"]

刘备的指称有: [ 刘备 , 刘玄德 , 玄德 , 使君 ]
로그인 후 복사

인간 개체 및 참조 외에도 삼국의 세력과 같은 다른 유형의 참조도 포함할 수 있습니다. 예를 들어 "Shu"는 "Shuhan"이라고도 합니다. "이므로 엔터티 유형 정보를 포함하여 차별화할 수도 있습니다.

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))[ 誓毕 , , , 拜 , 刘备 , 为兄 , , , 关羽 , 次之 , , , 张飞 , 为弟 , 。 ]
로그인 후 복사

소셜 네트워크 구축

참조를 표준 엔터티 이름으로 성공적으로 통합한 후 삼국지의 소셜 네트워크 탐색을 시작할 수 있습니다. . 이를 확립하는 구체적인 방법은 이웃 동시발생 관계를 이용하는 것입니다. 한 쌍의 개체가 두 문장에 함께 나타날 때마다 가장자리를 추가합니다. 그러면 네트워크 구축의 전체 과정은 아래 그림과 같습니다.

재미있는 재미 - 삼국지에서 Python을 사용하여 소셜 네트워크 분석

HarvestText에서 제공하는 기능을 사용하면 이 과정을 직접 완료할 수 있습니다. 먼저 텍스트의 작은 장에서 연습해 보겠습니다.

# 准备工作
doc = chapters[0].replace("操","曹操")                                  # 由于有时使用缩写,这里做一个微调
ch1_sentences = ht.cut_sentences(doc)     # 分句
doc_ch01 = [ch1_sentences[i]+ch1_sentences[i+1] for i in range(len(ch1_sentences)-1)]  #获得所有的二连句
ht.set_linking_strategy("freq")

# 建立网络
G = ht.build_entity_graph(doc_ch01, used_types=["人名"])              # 对所有人物建立网络,即社交网络

# 挑选主要人物画图
important_nodes = [node for node in G.nodes if G.degree[node]>=5]
G_sub = G.subgraph(important_nodes).copy()
draw_graph(G_sub,alpha=0.5,node_scale=30,figsize=(6,4))
로그인 후 복사

재미있는 재미 - 삼국지에서 Python을 사용하여 소셜 네트워크 분석

그들 사이의 구체적인 관계는 무엇입니까? 텍스트 요약을 사용하여 이 장의 구체적인 내용을 얻을 수 있습니다:

stopwords = get_baidu_stopwords()    #过滤停用词以提高质量for i,doc in enumerate(ht.get_summary(doc_ch01, topK=3, stopwords=stopwords)): print(i,doc)玄德见皇甫嵩、朱儁,具道卢植之意。嵩曰:“张梁、张宝势穷力乏,必投广宗去依张角。时张角贼众十五万,植兵五万,相拒于广宗,未见胜负。植谓玄德曰:“我今围贼在此,贼弟张梁、张宝在颍川,与皇甫嵩、朱儁对垒。次日,于桃园中,备下乌牛白马祭礼等项,三人焚香再拜而说誓曰:“念刘备、关羽、张飞,虽然异姓,既结为兄弟,则同心协力,
로그인 후 복사

이 장의 주요 내용은 Liu, Guan, Zhang Taoyuan이 의형제가 되어 적군에 맞서 싸우는 이야기인 것 같습니다. 황건적 도둑들이 함께합니다.

삼국전망도

소규모 실천을 바탕으로 같은 방법으로 통합할 수 있습니다. 각 장의 내용은 삼국과 세대를 아우르는 큰 그림을 그린다.


G_chapters = []
로그인 후 복사

전체 소셜 네트워크에는 무려 1,290명이 있고, 수만 개의 엣지가 있습니다! 그러면 우리가 그리는 것이 거의 불가능하므로 그 중에서 주요 인물을 선택하여 부분집합을 그려보겠습니다.

important_nodes = [node for node in G_global.nodes if G_global.degree[node]>=30]
로그인 후 복사

pyecharts를 사용한 시각화

from pyecharts import Graph
로그인 후 복사

대화형 차트는 블로그에 표시할 수 없으므로 다음 스크린샷이 있습니다. Liu Bei의 인접 매듭 표시 클릭


재미있는 재미 - 삼국지에서 Python을 사용하여 소셜 네트워크 분석

전체 네트워크는 복잡하고, 그 뒤에는 삼국지 이야기 속 수많은 정복과 음모가 숨겨져 있습니다. 그러나 컴퓨터의 강력한 컴퓨팅 성능을 사용하면 다음과 같은 특정 핵심 단서를 분류할 수 있습니다. 이 문제의 경우 네트워크의 정렬 알고리즘을 사용하여 해결할 수 있습니다. 페이지랭크(PageRank)는 원래 검색 엔진이 웹사이트 간의 연결을 이용해 검색 결과의 순위를 매기는 방식이지만, 사람 간의 연결에도 동일하게 적용됩니다. 가장 중요한 상위 20개를 살펴보겠습니다.

page_ranks = pd.Series(nx.algorithms.pagerank(G_global)).sort_values()
page_ranks.tail(20).plot(kind="barh")
plt.show()
로그인 후 복사

结果的确和上面的排序有所不同,我们看到刘备、曹操、孙权、袁绍等主公都名列前茅。而另一个有趣的发现是,司马懿、司马昭、司马师父子三人同样榜上有名,而曹氏的其他后裔则不见其名,可见司马氏之权倾朝野。司马氏之心,似乎就这样被大数据揭示了出来!

社群发现

人物关系有亲疏远近,因此往往会形成一些集团。社交网络分析里的社区发现算法就能够让我们发现这些集团,让我使用community库[2]中的提供的算法来揭示这些关系吧。

import community                                    # python-louvainpartition = community.best_partition(G_main)         # Louvain算法划分社区comm_dict = defaultdict(list)for person in partition:   comm_dict[partition[person]].append(person)
로그인 후 복사

在下面3个社区里,我们看到的主要是魏蜀吴三国重臣们。(只有一些小“问题”,有趣的是,电脑并不知道他们的所属势力,只是使用算法。)

draw_community(2)
ommunity 2: 张辽 曹仁 夏侯惇 徐晃 曹洪 夏侯渊 张郃 许褚 乐进 李典 于禁 荀彧 刘晔 郭嘉 满宠 程昱 荀攸 吕虔 典韦 文聘 董昭 毛玠
로그인 후 복사
draw_community(4)
community 4: 曹操 诸葛亮 刘备 关羽 赵云 张飞 马超 黄忠 许昌 孟达[魏] 孙乾
曹安民 刘璋 关平 庞德 法正 伊籍 张鲁 刘封 庞统 孟获 严颜 马良 简雍 蔡瑁 
陶谦 孔融 刘琮[刘表子] 刘望之 夏侯楙 周仓 陈登
로그인 후 복사
draw_community(3)
community 3: 孙权 孙策 周瑜 陆逊 吕蒙 丁奉 周泰 程普 韩当 徐盛 张昭[吴] 马相 黄盖[吴] 潘璋 甘宁 鲁肃 凌统 太史慈 诸葛瑾 韩吴郡 蒋钦 黄祖 阚泽 朱桓 陈武 吕范
로그인 후 복사
draw_community(0)
community 0: 袁绍 吕布 刘表 袁术 董卓 李傕 贾诩 审配 孙坚 郭汜 陈宫 马腾 
袁尚 韩遂 公孙瓒 高顺 许攸[袁绍] 臧霸 沮授 郭图 颜良 杨奉 张绣 袁谭 董承 
文丑 何进 张邈[魏] 袁熙
로그인 후 복사

还有一些其他社区。比如在这里,我们看到三国前期,孙坚、袁绍、董卓等主公们群雄逐鹿,好不热闹。

draw_community(1)
community 1: 司马懿 魏延 姜维 张翼 马岱 廖化 吴懿 司马昭 关兴 吴班 王平 
邓芝 邓艾 张苞[蜀] 马忠[吴] 费祎 谯周 马谡 曹真 曹丕 李恢 黄权 钟会 蒋琬
司马师 刘巴[蜀] 张嶷 杨洪 许靖 费诗 李严 郭淮 曹休 樊建 秦宓 夏侯霸 杨仪
 高翔 张南[魏] 华歆 曹爽 郤正 许允[魏] 王朗[司徒] 董厥 杜琼 霍峻 胡济 贾充
  彭羕 吴兰 诸葛诞 雷铜 孙綝 卓膺 费观 杜义 阎晏 盛勃 刘敏 刘琰 杜祺 上官雝 
  丁咸 爨习 樊岐 曹芳 周群
로그인 후 복사

这个社区是三国后期的主要人物了。这个网络背后的故事,是司马氏两代三人打败姜维率领的蜀汉群雄,又扫除了曹魏内部的曹家势力,终于登上权力的顶峰。

动态网络

研究社交网络随时间的变化,是个很有意思的任务。而《三国演义》大致按照时间线叙述,且有着极长的时间跨度,顺着故事线往下走,社交网络会发生什么样的变化呢?

这里,我取10章的文本作为跨度,每5章记录一次当前跨度中的社交网络,就相当于留下一张快照,把这些快照连接起来,我们就能够看到一个社交网络变化的动画。快照还是用networkx得到,而制作动画,我们可以用moviepy。

江山代有才人出,让我们看看在故事发展的各个阶段,都是哪一群人活跃在舞台中央呢?

import moviepy.editor as mpy
from moviepy.video.io.bindings import mplfig_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)

def make_frame_mpl(t):
   i = step*int(t*fps)
   G_part = nx.Graph()
   for G0 in G_chapters[i:i+width]:
       for (u,v) in G0.edges:
           if G_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]*10 for x in G.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}章的社交网络")
   return mplfig_to_npimage(fig)
animation = mpy.VideoClip(make_frame_mpl, duration=duration)

animation.write_gif("./images/三国社交网络变化.gif", fps=fps)
로그인 후 복사

美观起见,动画中省略了网络中的边。

재미있는 재미 - 삼국지에서 Python을 사용하여 소셜 네트워크 분석

随着时间的变化,曾经站在历史舞台中央的人们也渐渐地会渐渐离开,让人不禁唏嘘感叹。正如《三国演义》开篇所言:

古今多少事,都付笑谈中。

今日,小辈利用python做的一番笑谈也就到此结束吧……

【推荐课程:Python视频教程】  

위 내용은 재미있는 재미 - '삼국지'에서 Python을 사용하여 소셜 네트워크 분석의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

관련 라벨:
원천:Python爬虫与数据挖掘
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿