使用图分析网络



社交网络分析是使用网络理论探索各种系统的过程。当人们清楚地知道大量现有网络(社会,经济,生物网络)具有通用性时,它就开始被广泛使用:研究一种类型后,您可以了解任何其他网络的结构并学习如何从中进行预测。



任何网络都由个体参与者(网络中的人或物)及其之间的关系组成。网络通常使用图形可视化-图形由许多点和线组成,这些点和线表示这些点之间的连接。参与者表示为网络的节点,而它们之间的关系表示为连接它们的线。这种可视化有助于对网络进行定性和定量评估:





数字: 1.表示形成外汇市场的银行之间的资金周转的方向图(1)。欧盟银行标记为红色,北美标记为蓝色,其他国家标记为绿色。





数字: 2.该图显示了2010-2014年丹麦审计合作伙伴的合作(2)



使用社交网络分析,可以分析物质和信息资源的各种相互作用和交换过程。例如,通过分析银行客户之间的交易网络(节点是银行的客户,边缘是它们之间的转移),可以确定参与欺诈性交易的人员的圈子,或者确定银行员工违反内部法规的行为。



也可以建立工作关系网络(以员工之间各种类型的交流为例),这可以帮助理解组织的社会结构以及每个员工在该结构中的位置。有了关于每位员工的沟通类型的数据,人们甚至可以分析领导,指导和合作等特征如何影响他的职业,并基于所获得的知识确定职业目标并提出实现这些目标的培训计划。



此外,可以使用网络示例预测事件。例如,有些模型可以估算软件故障的可能性,其中一些模型将人们视为预测的源头-毕竟,是人们在发布产品之前对其进行开发和测试。他们的互动形成了一个网络:您可以将开发人员视为节点,并且可以将他们是否在同一个版本的同一文件中一起工作,作为网络的边缘。了解交互作用和有关先前故障的信息将告诉您很多有关最终产品的可靠性,并指出最有可能发生故障的文件。



现在,让我们尝试在实践中应用社交网络的分析。为此,我们将使用Python编程语言,或者使用networkx库处理图形,使用matplotlib库进行可视化,并使用社区库突出显示网络中的社区。让我们导入它们:



1.	import community
2.	import networkx as nx
3.	import matplotlib.cm as cm
4.	import matplotlib.pyplot as plt


1.导入数据并将其转换为图形



作为数据集,让我们从一所欧洲大型大学获得一封电子邮件,其中包含有关研究机构成员之间所有传入和传出电子邮件消息的匿名信息(链接)。数据集包含一个txt文件,其中每行列出了彼此相关的节点对。



1.	G = nx.read_edgelist('email-Eu-core.txt', create_using=nx.DiGraph())
2.	print(' : {}'.format(G.number_of_nodes()))
3.	print(' : {}'.format(G. number_of_edges()))
4.	print('       : {}'.format(round(G.number_of_edges() / float(G.number_of_nodes()), 4)))

 : 1005
 : 25571
      : 25.4438


在上面的代码中,数据集已导入并转换为图形。然后,我们依次推导出图的主要参数:图中的节点数,边数和节点的平均邻居数。最后一个参数反映节点之间相互连接的紧密程度。



2.图形的主要特征



为了了解如何使用每个特定的图,首先需要了解它的工作方式。让我们快速看一下可以理解图结构的特征。



首先,考虑连通性和方向性的概念。如果图中的每对节点都相互连接,即图,则称为连接。从任何节点都可以到达任何其他节点。如果图形断开连接,则可以将其划分为最大连接的子图形(称为组件)。同样,图可以是有向的和无向的。这取决于两个参与者之间关系的方向是否存在。定向网络的一个示例是银行客户之间的交易,其中每个客户可以同时具有收款和付款。



通常,在有向图中,连接不是相互连接的,因此,对于有向图,除了连通性的概念以外,还区分了弱连通性和强连通性的组件的概念。如果忽略方向,则会将一个组件视为弱连接。如果所有顶点相互可达,则强连通性的组成部分可以是这样的。让我们看一下电子邮件数据集中的图形结构:



1.	if nx.is_directed(G):
2.	        if nx.is_weakly_connected(G):
3.	                print('         .')
4.	        else:
5.	                print('       .')
6.	else:
7.	        if nx.is_connected(G):
8.	                print('    .')
9.	        else:
10.	                print('       .')


该图是有向图,由几个组件组成。



在这里,我们检查了图的方向性和连通性,发现来自数据集的图是有向的,并且包含几个断开的组件。让我们尝试仔细研究强连接和弱连接的最大组成部分:



1.	G_weak = G.subgraph(max(nx.weakly_connected_components(G), key=len))
2.	print(' : {}'.format(G_weak.number_of_nodes()))
3.	print(' : {}'.format(G_weak.number_of_edges()))
4.	print('      : {}'.format(round(G_weak.number_of_edges() / float(G_weak.number_of_nodes()), 4)))
5.	
6.	G_strong = G.subgraph(max(nx.strongly_connected_components(G), key=len))
7.	print(' : {}'.format(G_strong.number_of_nodes()))
8.	print(' : {}'.format(G_strong.number_of_edges()))
9.	print('      : {}'.format(round(G_strong.number_of_edges() / float(G_strong.number_of_nodes()), 4)))


 : 986
 : 25552
      : 25.9148

 : 803
 : 24729
      : 30.7958


因此,我们获得了其中的弱连接组件和强连接组件的主要特征。让我们看看在这个阶段可以得出什么结论。我们看到,在1005名参与者中,有986人相互通信,而其中有183人单方面发送电子邮件给其他人,只有803人保持双向通信。在823种情况下,尝试通过电子邮件建立通信失败。我们还看到最活跃的参与者(包括在强大的连接性组件中)平均与30个人进行交流。



让我们看看定义其结构的图的其他关键特征。如果节点之间的关系不仅反映了连接的存在,而且还反映了该连接的强度的一定权重,则认为图是加权的。我们的电子邮件数据集没有加权,因为它仅考虑了对应的事实,而不考虑发送的电子邮件数量。



另外,节点和链接可以创建不同类型的网络:单子叶,双子叶或多层。单子叶网络由一种类型的参与者及其之间的连接组成。双向网络由两种不同类型的参与者组成,其中一种类型的节点仅与另一种类型相关联。多层网络还包括两种类型的参与者,但是链接可以连接不同类型的参与者和相同类型的参与者(例如,管理者之间的关系以及项目之间的关系)。我们用于研究的数据集是单子叶网络,因为它仅包含一种类型的参与者及其之间的联系。



3.图形可视化



现在,让我们尝试可视化我们获取的数据集。为此,我们需要已在上面导入的matplotlib库:



1.	plt.figure(figsize=(15, 15))
2.	plt.title('E-mails')
3.	nx.draw(G, node_size=5)
4.	plt.show()


第一行设置将来图像的大小,然后为其指定一个特定名称。绘制函数的第三行传递一个图形并指定节点的大小,然后在屏幕上显示该图形。让我们看一下:





图。 3.用户交互以及研究机构成员之间有关所有传入和传出电子邮件的信息的图表。



在结果图上,我们看到有许多与其他通信参与者没有联系的点。这些人与其他参与者没有联系,但他们上了图,因为他们专门给自己发了信。您还可以注意到,在外围有许多点通过一些传入连接与图的其余部分相连-这些参与者属于我们图的弱连接组件,但没有属于强连接组件。



让我们也来看看,说明了强连通分量的图-谁与研究机构的其他成员双向通讯的人:





图。4.与研究机构成员之间有关所有传入和传出电子邮件的信息的强连通性的组成部分...



4.结度和结度分布



现在我们知道了图形的结构并能够对其进行可视化,让我们继续进行更详细的分析。图中的每个节点都有一个度数-该节点的最近邻居数。在定向网络中,可以区分进入程度(到该节点的传入连接的数量)和退出程度(从该节点的传出连接的数量)。如果我们为图的每个节点计算度数,则可以确定节点度数的分布。让我们来看看它的电子邮件图:



1.	degree = dict(G.degree())
2.	degree_values = sorted(set(degree.values()))
3.	hist = [list(degree.values()).count(x) for x in degree_values]
4.	plt.figure(figsize=(10, 10))
5.	plt.plot(degree_values, hist, 'ro-')
6.	plt.legend(['Degree'])
7.	plt.xlabel('Degree')
8.	plt.ylabel('Number of nodes')
9.	plt.show()




数字:5.



接收方图表中方框中包含研究机构成员之间所有传入和传出电子邮件消息的信息的权力分布显示了节点的程度分布:大量节点与邻居之间的联系很少,但是有少量大型单元,其中与其他节点的连接数参与者巨大。这种趋势称为配电的功率定律,对于大型网络非常典型。该法律可以描述不同城市人口的分布,互联网上站点的排名,甚至人们之间的财富分布。



5.图表中的路径,直径和平均距离



现在,让我们确定图的成员之间的连接程度。首先,让我们讨论不同类型的节点间距。



连接节点的任何边缘序列都称为路径。研究通常会考虑一条简单的路径,即没有循环和重复节点的路径。两个节点之间的最短路径称为大地测量距离。图中最长的最短路径称为直径,但是它对偏差非常敏感(数百万美元图中的一条链可以改变其直径)。在有向图中,直径的概念只能用于强连通性的组件,因为要计算直径,必须为每对节点之间有一条路径。在无向图中,连接所考虑的组件就足够了。



另一个非常有用的特性是节点之间的平均距离,可以通过取图中所有最短路径的平均值来获得。平均距离由图的结构确定:如果以链的形式构建图,则该图将很大,但是连接的节点越近,平均距离就越小。可以为强连接的组件和弱连接的组件计算平均距离:



1.	print (': ', nx.diameter(G_strong))
2.	print ('     : ', nx.average_shortest_path_length(G_strong))
3.	print ('     : ', nx.average_shortest_path_length(G_weak))

: 6
     :  2.5474824768713336
     :  2.164486568301397


让我们看一下结果。在这种情况下,直径为我们显示了两个陌生人之间的最大距离,在这里,就像众所周知的六个握手理论一样,该距离为6。组件中的平均距离也很小,对于两个陌生人来说,平均2次“握手”就足够了。在这里还可以看到一个有趣的现象:强连接组件中的平均距离略小于弱连接组件中的平均距离。这可以通过以下事实来解释:对于弱连接的组件,不考虑键的方向(仅是其存在的事实)。因此,弱组件中的连接出现在强组件所不存在的位置。



6.社区的集群和分配



弄清楚参与者之间的距离后,让我们继续研究其他现象,这些现象反映图中参与者之间的相互联系:聚类和社区。



聚类系数表明,通过第三元素连接的图中的两个元素具有很高的概率相互连接。即使它们没有链接,它们将来链接的可能性也比其他两个随机获取的节点高得多。这种现象称为聚类或可传递性,在社会图中极为普遍。



具有高度聚类的图的特征在于存在大量相连的三元组(三个相互连接的节点)。它们是许多社交网络的组成部分,其中此类三角形的数量非常大。通常甚至没有三角形出现,而是整个集群形成(称为社区),它们彼此之间的关系比与图的其余部分关系更紧密。



让我们看一下弱连接组件的聚类和聚类系数:



1.	print (': ', nx.transitivity(G_strong))
2.	print (' : ', nx.average_clustering(G_strong))


:  0.2201493109315837
 :  0.37270757578876434


对于具有强连通性的组件,我们可以获得相同的特征,还可以确定中心节点(与其余节点关系最密切的节点)的数量以及图形外围的节点数量:



1.	print (': ', nx.transitivity(G_strong))
2.	print (' : ', nx.average_clustering(G_strong))
3.	print ('  : ', len(nx.center(G_strong)))
4.	print ('   : ', len(nx.periphery(G_strong)))


:  0.2328022090200813
 :  0.3905903756516427
  : 46
   : 3


在第二种情况下,聚类和聚类系数增加,反映出强连接的组件包含大量的连接三胞胎。让我们一起尝试在松耦合组件中定义主要社区:



1.	G_undirected = G_weak.to_undirected()
2.	partition = community.best_partition(G_undirected)
3.	communities = set(partition.values())
4.	communities_dict = {c: [k for k, v in partition.items() if v == c] for c in communities}
5.	highest_degree = {k: sorted(v, key=lambda x: G.degree(x))[-5:] for k, v in communities_dict.items()}
6.	print(' : ', len(highest_degree))
7.	print('    :', ', '.join([str(len(highest_degree[key])) for key in highest_degree]))


 : 8
    : 113, 114, 125, 131, 169, 188, 54, 92


因此,在带有电子邮件的列中,可以区分8个社区,它们彼此之间的联系比该列的其余部分更紧密。社区中最小的社区有54个成员,最大的社区有188个成员。对于社区重叠或嵌套的网络,确定最佳分区可能会更加困难。因此,每次您运行代码时,社区的组成可能会有所不同。我们来看一下拆分的可视化效果:



1.	pos = nx.spring_layout(G)
2.	plt.figure(figsize=(15, 15))
3.	cmap = cm.get_cmap('gist_rainbow', max(partition.values()) + 1)
4.	nx.draw_networkx_nodes(G, pos, partition.keys(), node_size=20, cmap=cmap, node_color=list(partition.values()))
5.	nx.draw_networkx_edges(G, pos, alpha=0.5)
6.	plt.show()




数字:6.在松散耦合的组件中显示各种社区,以及有关研究机构成员之间所有传入和传出电子邮件的信息



在上图中,我们看到了按社区划分的成员分布,其中节点的颜色描述了特定社区的归属。



7.互惠关系



除了已经描述的属性外,在定向网络中还存在互惠性。此特征描述了多少百分比的传出链接具有反馈(传入链接)。为了找出答案,我们使用networkx库的特殊功能全面_reciprocity,并查看图及其组件中的互惠级别:



1.	print ('  : ', nx.overall_reciprocity(G))
2.	print ('    : ', nx.overall_reciprocity(G_weak))
3.	print ('    : ', nx.overall_reciprocity(G_strong))

  :  0.6933635759258535
    :  0.6938791484032562
    :  0.7169719762222492


在71%的情况下,用户在强连接性组件中收到了对其邮件的答复。对于连接较弱的组件以及整个图,该级别可以预测地较低。



8.网络的通用属性



总而言之,复杂的网络通常具有某些属性,并且某些属性是许多网络的特征。我们对电子邮件数据集的分析很好地支持了以下趋势:



  1. . , , . : web-, , , (Wikipedia, Microsoft). , .
  2. . , , « ». : , .
  3. , , : 80% , . – , , . , , .
  4. , . , .


我们分析并确认了上面列出的具有电子邮件对应关系的数据集的所有趋势:在图中发现一个很大的连接组件,其中包含所有节点的80%以上。在此组件内,大多数节点都具有少量特征,但是,只有少数参与者具有大量邻居。我们还看到图中的参与者之间的直径和平均距离很小:包含986位参与者的弱连接组件中的平均距离仅为2.1,这意味着大多数参与者在两次“握手”之后便相互连接。此外,该图还具有高度的互惠性:所有参与者中有69%保持双向交流。



笔记



该研究的全文可以在Nikolai Viktorovich Ursul的书《外汇全真相》(2019年)中找到。



Slobodan Kacanski,Dean Lusher(2017,链接在文章“社交网络分析在会计和审计中的应用”中进行了描述



All Articles